0

The getting started examples in Espressif's esp-idf are hello-world and blink. Hello-world outputs prints then calls esp_restart(); - so it is in it's own special infinite loop.

The blink example (with comments removed) has this app_main, which is also an infinite loop:

void app_main(void)
{
    gpio_pad_select_gpio(BLINK_GPIO);
    gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
    while(1) {
      printf("Turning off the LED\n");
      gpio_set_level(BLINK_GPIO, 0);
      vTaskDelay(1000 / portTICK_PERIOD_MS);

      printf("Turning on the LED\n");
      gpio_set_level(BLINK_GPIO, 1);
      vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

I copied the blink example to my ~/esp folder, did NOT run makeconfig (so just with the defaults), build, flash and monitor it, and it works - the monitor just shows 'Turning off the LED' and 'Turning on the LED'. No mention of watchdog timers.

I wrote my own, most simple application I could, without the vTaskDelay() call:

void app_main(void) {
  long timeSinceBoot;
  while (1) {
    timeSinceBoot = esp_timer_get_time();
    printf("Helloooo world %ld\n!",timeSinceBoot);
  };
}

This results in the serial monitor showing the following output periodically:

E (20298) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (20298) task_wdt:  - IDLE0 (CPU 0)
E (20298) task_wdt: Tasks currently running:
E (20298) task_wdt: CPU 0: main
E (20298) task_wdt: CPU 1: IDLE1

I understand why - I need to call back to the OS for it to do what it needs to do. I have done this with a yield statement in other systems.

I only want to use one core, and am trying to avoid using xTaskCreate to keep my code simple to understand.

If I don't want to delay (like the blink example does) what is the most efficient way to pass control from app_main back to FreeRTOS so it returns as soon as it can?

isherwood
  • 58,414
  • 16
  • 114
  • 157
NULL pointer
  • 1,116
  • 1
  • 14
  • 27

2 Answers2

1

The problem is no to pass control back to FreeRTOS but the handling of the watchdog in the eps-idf framework.

The watchdog is "fed" in the IDLE task and while the APP_MAIN task has a higher priority than IDLE it is never interrupted.

If you don't want to use vTaskDelay maybe you could make the priority of the IDLE and the MAIN task equal. Than both should be executed (but you must be careful if there any even more task that do not get enough attention).

theSealion
  • 1,082
  • 7
  • 13
  • Thanks @theSealion. My objective is not to supress the watchdog message, but to ensure that my app_main loop does not monopolise the CPU. I think the adjusting the relative priority of the app_main task and the idle task is a workaround, rather than an elegant solution. I am not ideologically agains calling vTaskDelay - I can use vTaskDelay(0), but if there a 'proper' way to yield? – NULL pointer Sep 13 '19 at 00:52
  • 'yield' will transfer the control to a waiting task with equal or higher priority. Since there is no higher task app_main will get all cpu time. (And the IDLE task, that feeds the watchdog, will starve) An elegant solution would be to hook you application to the IDLE task. If you do so all other tasks could interrupt the main routine if necessary. But I don't know if the ESP_IDF still support the IDLE Hook. – theSealion Sep 13 '19 at 09:40
0

I don't recommend doing this for anything but testing, but you can simply disable the task watchdog on the IDLE tasks.

menuconfig->Component config->Esp32-specific config -> deactivate Task watchdog

For production code you should follow best-practice and use the FreeRTOS functions such as vTaskDelay so you don't hog the CPU.

phatpaul
  • 166
  • 7