Closed Kampi closed 1 year ago
esp_task_wdt_reset()
feeds the watchdog for the current task, in this case Lepton_CaptureTask
, but the error you are seeing is coming from the idle
task.
Since Lepton_CaptureTask
is spinning in a while loop the idle task in FreeRTOS never gets a chance to run and thus never resets its watchdog. The idle
task WDT purpose is to monitor exactly this, that one task doesnt block the core forever without yielding.
The correct way to avoid this would be to:
ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1
)vTaskDelay()
, as this will ensure that the idle tasks gets the chance to run as well. Hi @ESP-Marius
thanks for your explanations. I´ve thought about it and how I can improve this. Basically Lepton_CaptureTask
has to wait for a V-Sync signal to become high. I came up with the idea to use an interrupt and a queue for the ISR (based on the esp-idf GPIO example). I have changed the functions in the following way:
static void IRAM_ATTR Lepton_VSync_ISR_Handler(void* p_Args)
{
uint32_t Value;
Lepton_t* Device;
Device = static_cast<Lepton_t*>(p_Args);
Value = static_cast<uint32_t>(Device->Internal.VSync.IO);
xQueueSendFromISR(Device->Internal.VSync.Queue, &Value, NULL);
}
Lepton_Error_t Lepton_StartCapture(Lepton_t* p_Device)
{
Lepton_Error_t Error;
Error = LEPTON_ERR_OK;
// Create a queue to handle GPIO events from ISR.
p_Device->Internal.VSync.Queue = xQueueCreate(8, sizeof(uint32_t));
if(p_Device->Internal.VSync.Queue == NULL)
{
goto Lepton_StartCapture_Error_1;
Error = LEPTON_ERR_NO_MEM;
}
xTaskCreatePinnedToCore(&Lepton_CaptureTask, "Lepton_Capture", CONFIG_LEPTON_TASK_STACK, p_Device,
if(p_Device->Internal.Task.Handle == NULL)
{
goto Lepton_StartCapture_Error_2;
Error = LEPTON_ERR_NO_MEM;
}
esp_task_wdt_add(p_Device->Internal.Task.Handle);
// V-Sync is a high-level signal. So we need to add a positive edge interrupt.
gpio_set_direction(p_Device->Internal.VSync.IO, GPIO_MODE_INPUT);
gpio_set_pull_mode(p_Device->Internal.VSync.IO, GPIO_PULLDOWN_ONLY);
gpio_set_intr_type(p_Device->Internal.VSync.IO, GPIO_INTR_POSEDGE);
gpio_install_isr_service(0);
// Hook ISR handler for specific GPIO.
gpio_isr_handler_add(p_Device->Internal.VSync.IO, Lepton_VSync_ISR_Handler, p_Device);
return Error;
Lepton_StartCapture_Error_2:
vQueueDelete(p_Device->Internal.VSync.Queue);
Lepton_StartCapture_Error_1:
return Error;
}
static void Lepton_CaptureTask(void* p_Args)
{
Lepton_t* Device;
VSyncCount = 0;
Device = static_cast<Lepton_t*>(p_Args);
Device->Internal.Task.isRunning = true;
while(Device->Internal.Task.isRunning)
{
uint32_t io_num;
esp_task_wdt_reset();
if(xQueueReceive(Device->Internal.VSync.Queue, &io_num, 10 / portTICK_PERIOD_MS))
{
printf("GPIO[%"PRIu32"] intr, val: %d\n", io_num, gpio_get_level(static_cast<gpio_num_t>(io_num)));
}
}
vTaskSuspend(NULL);
vTaskDelete(NULL);
}
I guess this will solve the problem, but I need to check this more closely because I have to make sure that no V-Sync is missed.
Yeah, something similar to this approach seems like the correct way to approach it.
I think we can just close this issue then right? As there doesnt seem to be any ESP-IDF related problems here.
@Kampi does your camera use DVP interface (VSYNC, HSYNC, D0-D7)? If yes, you might consider ESP32-S2 and ESP32-S3 — they have an LCD_CAM peripheral which can receive frames from the camera, writing them to memory using DMA.
Hi @igrr, thanks for your suggestion. Unfortunately no. It´s a FLIR Lepton Thermal Camera that uses an SPI to transmit the data.
Answers checklist.
General issue report
Hello,
I have an issue with understanding the task watchdog and the triggering of the task watchdog (esp-idf v5). Please take a look at this code snippet from my Lepton driver. This snippet creates a task for reading the camera, but I get a task watchdog trigger every 5 seconds and don´t understand why.
I get this message every ~5 seconds (configured watchdog time).
What do you think the correct way is to avoid this?
Thanks!