esp_wifi_connect() does not yield to other tasks?

jcsbanks
Posts: 300
Joined: Tue Mar 28, 2017 8:03 pm

esp_wifi_connect() does not yield to other tasks?

Postby jcsbanks » Tue Jun 05, 2018 11:05 am

I have a task called task_RMT_Rx that regularly flushes an RMT receive buffer that records pulse width hi/lo pairs. Because my hi/lo pairs are continuous, I have to do this as no interrupt can be called. If task_RMT_Rx is not run often enough, the RMT buffer overflows and I have to do a rather clumsy reset of all RMT channels rather than just the one that has overflowed.

When I do esp_wifi_connect, the RMT buffer overflows. If I wait 5000ms after calling esp_wifi_connect before starting the task_RMT_Rx, all behaves well, but I want to handle the situation so that WiFi can start and stop and not upset RMT.

This works:

Code: Select all

ESP_ERROR_CHECK( esp_wifi_connect() );
vTaskDelay(5000);
xTaskCreate(task_RMT_Rx, "RMTFFS", 2048, NULL, 5, NULL);
This does not work:

Code: Select all

xTaskCreate(task_RMT_Rx, "RMTFFS", 2048, NULL, 5, NULL);
ESP_ERROR_CHECK( esp_wifi_connect() );
I am suspicious that my task is not being run whilst esp_wifi_connect occurs. Is this expected/by design? I thought that WiFi would be on one core and my application on another and have no such problems, but I'm missing something.

I am going to investigate esp_wifi_connect code, but am still getting used to freeRTOS and how to properly get tasks to yield without introducing too much latency but also avoiding watchdog warnings. I am wondering if I need to do an HRT callback instead of a freeRTOS task to be certain my task_RMT_Rx will run reliably.

jcsbanks
Posts: 300
Joined: Tue Mar 28, 2017 8:03 pm

Re: esp_wifi_connect() does not yield to other tasks?

Postby jcsbanks » Tue Jun 05, 2018 11:26 am

Bit more context, in this case with the 5 second delay between esp_wifi_connect and starting task_RMT_Rx:

Code: Select all

void app_main()
{
    nvs_flash_init();
    tcpip_adapter_init();
    ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
    ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
    wifi_config_t sta_config =
    {
        .sta = {.ssid = "[removed]", .password = "[removed]", .bssid_set = false}
    };
    ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config) );
    ESP_ERROR_CHECK( esp_wifi_start() );
    ESP_ERROR_CHECK( esp_wifi_connect() );

    xTaskCreate(&task_process_WebSocket, "ws_process_rx", 2048, NULL, 5, NULL);
    xTaskCreate(&ws_server, "ws_server", 2048, NULL, 5, NULL);
    xTaskCreate(task_CAN_Rx, "CANRx", 2048, NULL, 5, NULL);
    xTaskCreate(task_CAN_Tx, "CANTx", 2048, NULL, 5, NULL);
    vTaskDelay(5000);
    xTaskCreate(task_RMT_Rx, "RMTFFS", 2048, NULL, 5, NULL);
    xTaskCreate(task_CAN_ERR, "CAN_ERR", 2048, NULL, 5, NULL);

ESP_Sprite
Posts: 3444
Joined: Thu Nov 26, 2015 4:08 am

Re: esp_wifi_connect() does not yield to other tasks?

Postby ESP_Sprite » Wed Jun 06, 2018 2:05 am

Depending on the things you do in the RMT tasks (do you use floats anywhere?) your task can be implicitly pinned to core 0. Try pinning it explicitely to core 1 when you create it, see if that fixes the issue. Do you know how long your RMT task can be starved before problems occur? Thing is, WiFi initialization can do a write to NVS and thus flash, and this effectively stops all normal processes for the duration of the flash write.

jcsbanks
Posts: 300
Joined: Tue Mar 28, 2017 8:03 pm

Re: esp_wifi_connect() does not yield to other tasks?

Postby jcsbanks » Wed Jun 06, 2018 2:02 pm

Thanks ESP_Sprite. Very helpful, will investigate along these lines.

Yes I do use floats in the RMT task that normally runs every 5ms.

The RMT task can be starved for at least 400ms depending on frequency.

If one core is writing to flash, can the other core still run normally?

ESP_Sprite
Posts: 3444
Joined: Thu Nov 26, 2015 4:08 am

Re: esp_wifi_connect() does not yield to other tasks?

Postby ESP_Sprite » Thu Jun 07, 2018 2:08 am

Not with 'normal' tasks; as the flash is unavailable, in order to make sure nothing tries to execute from flash, on the other core a high-priority task will run for the duration of the flash process, starving all other tasks. You can theoretically put your RMT task in IRAM and give it a higher priority than the IPC task which does this, but you need to keep in mind that *everything* that your task calls should be in IRAM. However, 400mS is a pretty long time, all things considered; unless you're trying to write megabytes at a time somewhere (WiFi doesn't do this), the RMT task shouldn't be starved that easily.

ESP_Angus
Posts: 2110
Joined: Sun May 08, 2016 4:11 am

Re: esp_wifi_connect() does not yield to other tasks?

Postby ESP_Angus » Fri Jun 08, 2018 12:30 am

To expand on ESP_Sprite's comments:
jcsbanks wrote: Yes I do use floats in the RMT task that normally runs every 5ms.

The RMT task can be starved for at least 400ms depending on frequency.
The WiFi task is pinned to core 0 (by default) at priority 23. A lot of other tasks (like the TCP/IP task) also have priorities in the 20s range, see here (configMAX_PRIORITY is 25).

If your RMT task uses floats then it will pin to the first core it makes a floating point calculation on, which may be 0.

So you should be able to get much better performance by some combination of:

- Pin RMT task to core 1 with xTaskCreatePinnedToCore()
- Set higher priority on the RMT task to your other tasks (the posted code creates all tasks at priority 5, so your other tasks may also starve out the RMT task).
- Create RMT task with priority 24, so it will never be preempted by TCP/IP or other system tasks (note that if you do this, you have to make sure your RMT task doesn't starve out other parts of the system.)

Who is online

Users browsing this forum: No registered users and 16 guests