Hai Dang Minh
Hai Dang Minh

Reputation: 21

ESP32 Freertos: SPI task blocks other task (even on different core!!)

This is serial output. It did connected to Wifi, it just never ran task 2I'm developing high frequency DAQ based on ESP32 and freeRTOS.There will be 2 task, first task will run on core 0, communicating with sensors to collect data at 4000SPS, using SPI bus. Task 2 will run on core 1, receiving data from first task and send it async over TCP. Ideally, task 2 should send data while task 1 collecting latest one, simultaneously (dual core, right?) When I do a test run, I let SPI bus run as fast as possible, but it just keep blocking task 2 from ever running!! I don't want to use vTaskDelay(1), as it would affect rate of collecting data. What should I do now, to let both task run concurrently? Thanks!!

   void inFromSensor(void *parameter)
{
    for (;;)
    {
        SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0));
      //  digitalWrite(SS, LOW);
        SPI.write(0b000011100);
        SPI.write(0b000011100);
        SPI.write(0b000011100);
        SPI.endTransaction();
        // vTaskDelay(1000/portTICK_PERIOD_MS);
        // for (int i = 0; i < 88; i++)
        // {
        //     testBuffer1[i] = 8;
        //     itoa(testBuffer1[i], &buffer1[i], 10);
        // }
        // buffer1[0] = '1';
        // buffer1[87] = '\n';

        // UBaseType_t res = xRingbufferSend(buf_handle, buffer1, sizeof(buffer1), pdMS_TO_TICKS(1000));
        // if (res != pdTRUE)
        // {
        //     printf("Failed to send item\n");
        // }
        
        TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
        TIMERG0.wdt_feed = 1;
        TIMERG0.wdt_wprotect = 0;
    }
    vTaskDelete(NULL);
}
void outToTCP(void *parameter)
{
    for (;;)
    {
        Serial.println("a");
        WiFiClient client = wifiServer.available();
        if (client)
        {
            Serial.println("client connected");
            while (client.connected())
            {
                unsigned long start = millis();
                while (millis() - start < 5000)
                {
                    size_t item_size;
                    char *item = (char *)xRingbufferReceive(buf_handle, &item_size, pdMS_TO_TICKS(1000));
                    if (item != NULL)
                    {
                        client.write(item);
                        //Return Item
                        vRingbufferReturnItem(buf_handle, (void *)item);
                    }
                    else
                    {
                        //Failed to receive item
                        printf("Failed to receive item\n");
                    }
                }
                Serial.println("done");
                return;
            }

            client.stop();
            Serial.println("Client disconnected");
        }
        
        TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
        TIMERG0.wdt_feed = 1;
        TIMERG0.wdt_wprotect = 0;
    }
    vTaskDelete(NULL);
}
void setup()
{
    Serial.begin(112500);
    WiFi.begin(ssid, password);
    SPI.begin(SCK, MISO, MOSI, SS);
    pinMode(SS, OUTPUT);
    digitalWrite(SS, HIGH);
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(1000);
        Serial.println("Connecting to WiFi..");
    }
    wifiServer.begin();

    buf_handle = xRingbufferCreate(50280, RINGBUF_TYPE_NOSPLIT);
    if (buf_handle == NULL)
    {
        printf("Failed to create ring buffer\n");
    }
    Serial.println("ready");
    xTaskCreatePinnedToCore(
        inFromSensor,      /* Task function. */
        "lowPriorityTask", /* name of task. */
        15000,             /* Stack size of task */
        NULL,              /* parameter of the task */
        4,                 /* priority of the task */
        NULL,              /* Task handle to keep track of created task */
        1);
    delay(500);



xTaskCreatePinnedToCore(
    outToTCP,           /* Task function. */
    "highPriorityTask", /* name of task. */
    15000,              /* Stack size of task */
    NULL,               /* parameter of the task */
    6,                  /* priority of the task */
    NULL,               /* Task handle to keep track of created task */
    0);
delay(500);

Serial.println("ready");}

Upvotes: 1

Views: 1798

Answers (3)

Bhupiister singh
Bhupiister singh

Reputation: 119

void inFromSensor(void *parameter)
{
     VTaskDelay(NULL) // this will prevent task from running right after it is initialised, NULL parameter known that it is asking itself to delay.
    for (;;)
    {
    }
}

void setup()
{
xTaskCreatePinnedToCore(inFromSensor,"lowPriorityTask", 15000, NULL,4,Task1,1);// give task handle such as Task1 and you will have to declare this on top.

delay(500);
// You can then here control the order of resuming the task
vTaskResume(Task1);// this will start the task and you should do this ideally

}

Upvotes: 0

Hai Dang Minh
Hai Dang Minh

Reputation: 21

Solved! I just switched the order of creation of task ( xTaskCreatedPinnedToCore()), create task 2 first, then task 1. Looks like in the first situation, task 1, after being created, run continuously, thus task 2 never had a chance to be created!

Upvotes: 1

Tarmo
Tarmo

Reputation: 4825

Please post the serial output.

Anyway, my guess is that Task 1 is hogging the core which runs the WiFi stack, so WiFi never gets a chance to connect. Yet Task 2 depends on WiFi to be connected. Additionally Task 2 is waiting for data to be available in the ring buffers, but your code doesn't post anything there.

Anyway, this is something that would benefit from a timer. If you need to run a sampling process at specific intervals, configure a timer with the interval, do the sampling in the interrupt and post this to your processing thread. This is much more deterministic than spinning in a loop, hogging an entire core. Plus it leaves the spare cycles to those tasks that need them (there are quite a few in addition to your code).

Upvotes: 2

Related Questions