FreeRTOS Task causes TWDT triggered

User avatar
SSSSSteven
Posts: 11
Joined: Tue Dec 05, 2023 1:53 pm
Location: Shanghai, China
Contact:

FreeRTOS Task causes TWDT triggered

Postby SSSSSteven » Sun Apr 07, 2024 4:45 pm

I'm new to ESP-IDF and FreeRTOS. I'm using ESP32-S3 and ESP-IDF v5.2.1.

I have a FreeRTOS task which runs at a high frequency (for example, 2000Hz). I added vTaskDelay(0.5 / portTICK_PERIOD_MS) at the end of the task, but then the task caused Task Watchdog Timer triggered, and all code after xTaskCreate won't be executed. I want to know how to solve this. Please help, thanks.

Code: Select all

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

void task(void* pvParameters) {
    // ... Task code here
    vTaskDelay(0.5 / portTICK_PERIOD_MS);
}

void app_main() {
    // ... some code
    xTaskCreate(task, "task", 4096, NULL, 10, NULL);
    // ... other code, won't be executed
}


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

Re: FreeRTOS Task causes TWDT triggered

Postby ESP_Sprite » Mon Apr 08, 2024 1:30 am

Your tick frequency (by default) is 100Hz, so 0.5mS is less than a tick. That gets rounded down to 0, making the vTaskDelay not do anything.

Suggest you either use an esp_timer callback, or something like a hardware timer to do the thing you want.

User avatar
SSSSSteven
Posts: 11
Joined: Tue Dec 05, 2023 1:53 pm
Location: Shanghai, China
Contact:

Re: FreeRTOS Task causes TWDT triggered

Postby SSSSSteven » Wed Apr 10, 2024 10:35 pm

ESP_Sprite wrote:
Mon Apr 08, 2024 1:30 am
Your tick frequency (by default) is 100Hz, so 0.5mS is less than a tick. That gets rounded down to 0, making the vTaskDelay not do anything.

Suggest you either use an esp_timer callback, or something like a hardware timer to do the thing you want.
Thanks for the reply. Actually, what I'm doing in the task is check if there is a message in the FreeRTOS queue by if(xQueueReceive == pdTRUE), then store the value into a global variable (I need the value for next steps). Messages are sent by the General Purpose Timer callback and other ISRs (e.g. GPIO). It's quite similar to what it's doing in the GPIO example (https://github.com/espressif/esp-idf/bl ... .c#L62-L76). I've tried removing the vTaskDelay in my task (just as the GPIO example, without vTaskDelay in the task), but it still triggered TWDT.

I'm confused now. Could you please explain what should I do?

Sorry for the poor English.

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

Re: FreeRTOS Task causes TWDT triggered

Postby ESP_Sprite » Thu Apr 11, 2024 12:11 am

My point is that the vTaskDelay doesn't do anything with a wait time of less than 10mS, so having it there or not having it there does not make a difference, as you found. This is expected behaviour.

If your question is why your task triggers the TWDT in general, I'd suggest you post its full code.

User avatar
SSSSSteven
Posts: 11
Joined: Tue Dec 05, 2023 1:53 pm
Location: Shanghai, China
Contact:

Re: FreeRTOS Task causes TWDT triggered

Postby SSSSSteven » Thu Apr 11, 2024 12:58 am

ESP_Sprite wrote:
Thu Apr 11, 2024 12:11 am
My point is that the vTaskDelay doesn't do anything with a wait time of less than 10mS, so having it there or not having it there does not make a difference, as you found. This is expected behaviour.

If your question is why your task triggers the TWDT in general, I'd suggest you post its full code.
Here's the code:

Code: Select all

static uint32_t last_time = 0;
static QueueHandle_t queue = NULL;

static void IRAM_ATTR gpio_isr_handler(void* arg) {
    uint32_t now = esp_timer_get_time();
    xQueueSendFromISR(queue, &now, NULL);
}

static void IRAM_ATTR gpio_task(void *pvParameter) {
    uint32_t *var= (uint32_t *)pvParameter;
    for(;;) {
        uint32_t message;
        if(xQueueReceive(queue, &message, 0) == pdTRUE) {
            uint32_t diff = message - last_time;
            *var= 1000000 / diff;
            last_time = message;
        }
    }

}

esp_err_t gpio_init(uint8_t *var) {
    queue = xQueueCreate(10, sizeof(uint32_t));
    gpio_config_t io_config = {
        .intr_type = GPIO_INTR_POSEDGE,
        .mode = GPIO_MODE_INPUT,
        .pin_bit_mask = 1ULL << GPIO_PIN,
        .pull_down_en = true,
    };
    gpio_glitch_filter_handle_t filter = NULL;
    gpio_pin_glitch_filter_config_t filter_config = {
        .clk_src = GLITCH_FILTER_CLK_SRC_DEFAULT,
        .gpio_num = GPIO_PIN,
    };
    gpio_config(&io_config);
    gpio_new_pin_glitch_filter(&filter_config, &filter);
    gpio_glitch_filter_enable(filter);
    gpio_install_isr_service(ESP_INTR_FLAG_EDGE);
    xTaskCreate(gpio_task, "gpio_task", 2048, var, 10, NULL, 1);
    gpio_isr_handler_add(GPIO_PIN, gpio_isr_handler, NULL);
    return ESP_OK;
}
and the backtrace:

Code: Select all

E (5832) task_wdt: Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:
E (5832) task_wdt:  - IDLE0 (CPU 0)
E (5832) task_wdt: Tasks currently running:
E (5832) task_wdt: CPU 0: gpio_task
E (5832) task_wdt: CPU 1: IDLE1
E (5832) task_wdt: Print CPU 0 (current core) backtrace


Backtrace: 0x42041D23:0x3FC9AD60 0x42042140:0x3FC9AD80 0x40377675:0x3FC9ADB0 0x400559DD:0x3FCC6920 0x4037F2DE:0x3FCC6930 0x4037CF04:0x3FCC6950 0x403771E5:0x3FCC6990 0x4037D201:0x3FCC69C0
0x42041d23: task_wdt_timeout_handling at C:/Espressif/frameworks/esp-idf-v5.2.1/components/esp_system/task_wdt/task_wdt.c:441
0x42042140: task_wdt_isr at C:/Espressif/frameworks/esp-idf-v5.2.1/components/esp_system/task_wdt/task_wdt.c:515
0x40377675: _xt_lowint1 at C:/Espressif/frameworks/esp-idf-v5.2.1/components/xtensa/xtensa_vectors.S:1240
0x400559dd: _xtos_set_intlevel in ROM
0x4037f2de: vPortClearInterruptMaskFromISR at C:/EspresssiffNone/frameworks/ef
sppWa-iidf-v5.2.ti1/cong fomponre ntthse/ fdevrieceert toos reco/nneFrceteRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h:564
 (inlined by) xTaskGetSchedulerState at C:/Espressif/frameworks/esp-idf-v5.2.1/components/freertos/FreeRTOS-Kernel/tasks.c:4948
0x4037cf04: xQueueReceive at C:/Espressif/frameworks/esp-idf-v5.2.1/components/freertos/FreeRTOS-Kernel/queue.c:1540
0x403771e5: gpio_task at C:/Users/littl/Workspace/ESP/measurer/main/gpio.c:24
0x4037d201: vPortTaskWrapper at C:/Espressif/frameworks/esp-idf-v5.2.1/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:134
gpio_init will be called by app_main, then TWDT will be triggered very soon.

BTW, there may be multiple (maybe 2?) tasks need to be executed with such a high frequency (and the same priority), while some other tasks runs with vTaskDelay(100 / portTICK_PERIOD) and lower priority. But for now, there is only one task, that is gpio_task in the code above.

User avatar
ok-home
Posts: 78
Joined: Sun May 02, 2021 7:23 pm
Location: Russia Novosibirsk
Contact:

Re: FreeRTOS Task causes TWDT triggered

Postby ok-home » Thu Apr 11, 2024 1:54 am

Hi
If your queue is empty

Code: Select all

xQueueueReceive(queue, &message, 0)

will return control immediately without delay, you will get a loop without waiting, put

Code: Select all

xQueueueReceive(queue, &message, portMAX_DELAY)

User avatar
SSSSSteven
Posts: 11
Joined: Tue Dec 05, 2023 1:53 pm
Location: Shanghai, China
Contact:

Re: FreeRTOS Task causes TWDT triggered

Postby SSSSSteven » Thu Apr 11, 2024 8:05 pm

ok-home wrote:
Thu Apr 11, 2024 1:54 am
Hi
If your queue is empty

Code: Select all

xQueueueReceive(queue, &message, 0)

will return control immediately without delay, you will get a loop without waiting, put

Code: Select all

xQueueueReceive(queue, &message, portMAX_DELAY)
Thanks for your reply! Now gpio_task won't trigger TWDT anymore.

But another problem came out. I have another task named oled_task, which edits the LVGL label to the global variable I mentioned before, running with vTaskDelay(100 / portTICK_PERIOD). It runs normally at first, but after a while it will trigger TWDT, and the screen just display weird things (two question marks "??").

I also found the refresh rate is extremely low (only 2Hz?), while the task is running at 10Hz. (I tried to make a number count in this task, count + 1 & edit the LVGL label to show the count on screen, with vTaskDelay(100 / portTICK_PERIOD), but the number on screen just +5 then +5 then +5 then +5 ...) I'm using a 128*64px monochrome OLED screen driven by SSD1306 bought online, and all components are connected by breadboard and crappy jump wire.

It's annoying to reset the board like every 2 minutes, but I have no idea about any reason of this problem. Could you please explain to me why the task triggered TWDT?

Here's the code:

Code: Select all

static lv_disp_t *disp;
static lv_obj_t *scr;
static lv_obj_t *label;
void oled_task(void *pvParameter) {
    uint32_t *variable = (uint32_t*)pvParameter;
    for(;;) {
        lv_label_set_text_fmt(label, "%d", *variable);
        vTaskDelay(100 / portTICK_PERIOD_MS);
    }
}

esp_err_t oled_init(uint32_t *var) { // will be called in app_main
    ... // Initalize I2C SSD1306 driver and LVGL
    disp = lvgl_port_add_disp(&disp_cfg);
    lv_disp_set_rotation(disp, LV_DISP_ROT_180);
    scr = lv_disp_get_scr_act(disp);
    label = lv_label_create(scr);
    lv_label_set_text(label, "Initializing...");
    lv_obj_set_align(label, LV_ALIGN_TOP_LEFT);
    xTaskCreate(oled_task, "oled_task", 2048, var, 2, NULL);
    return ESP_OK;
}
and the backtrace:

Code: Select all

E (128236) task_wdt: Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:
E (128236) task_wdt:  - IDLE0 (CPU 0)
E (128236) task_wdt: Tasks currently running:
E (128236) task_wdt: CPU 0: oled_task
E (128236) task_wdt: CPU 1: IDLE1
E (128236) task_wdt: Print CPU 0 (current core) backtrace


Backtrace: 0x42042883:0x3FC9AD70 0x42042CA0:0x3FC9AD90 0x403776A5:0x3FC9ADC0 0x4201F714:0x3FCC5DA0 0x4201E8A1:0x3FCC5DC0 0x42020A81:0x3FCC5DE0 0x4200A175:0x3FCC5E30 0x4037D231:0x3FCC5E50
0x42042883: task_wdt_timeout_handling at C:/Espressif/frameworks/esp-idf-v5.2.1/components/esp_system/task_wdt/task_wdt.c:441
0x42042ca0: task_wdt_isr at C:/Espressif/frameworks/esp-idf-v5.2.1/components/esp_system/task_wdt/task_wdt.c:515
0x403776a5: _xt_lowint1 at C:/Espressif/frameworks/esp-idf-v5.2.1/components/xtensa/xtensa_vectors.S:1240
0x4201f714: lv_tlsf_free at C:/Users/littl/Workspace/ESP/measurer/components/lvgl__lvgl/src/misc/lv_tlsf.c:1167
0x4201e8a1: lv_mem_free at C:/Users/littl/Workspace/ESP/measurer/components/lvgl__lvgl/src/misc/lv_mem.c:179
0x42020a81: lv_label_set_text_fmt at C:/Users/littl/Workspace/ESP/measurer/components/lvgl__lvgl/src/widgets/lv_label.c:162
0x4200a175: oled_task at C:/Users/littl/Workspace/ESP/measurer/main/oled.c:21
0x4037d231: vPortTaskWrapper at C:/Espressif/frameworks/esp-idf-v5.2.1/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:134

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

Re: FreeRTOS Task causes TWDT triggered

Postby ESP_Sprite » Fri Apr 12, 2024 2:27 am

Where and how is 'var' defined? You sure it doesn't go out of scope?

User avatar
SSSSSteven
Posts: 11
Joined: Tue Dec 05, 2023 1:53 pm
Location: Shanghai, China
Contact:

Re: FreeRTOS Task causes TWDT triggered

Postby SSSSSteven » Fri Apr 12, 2024 5:44 am

ESP_Sprite wrote:
Fri Apr 12, 2024 2:27 am
Where and how is 'var' defined? You sure it doesn't go out of scope?
var is defined in as a global variable, passed into gpio_init, gpio_task, oled_init and oled_task as a pointer.

Code: Select all

uint32_t realVariable;

void app_main() {
	gpio_init(&realVariable);
	oled_init(&realVariable);
}

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

Re: FreeRTOS Task causes TWDT triggered

Postby ESP_Sprite » Fri Apr 12, 2024 5:48 am

Hm, no clue. Any other tasks doing anything with lvgl? Wondering if you may have some sort of concurrency issue.

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 86 guests