esp32: New Task Watchdog API

Legacy API of task watchdog used the same function esp_task_wdt_feed() to add
and feed a task. This caused issues of implicitly adding a task to the wdt list
if the function was used in shared code.

The new API introduces init, adding, feeding, deleting, deinit functions. Tasks
must now be explicitly added to the task watchdog using their handles. Deletion
must also be explicit using task handles. This resolves the issue of implicit
task additions to the task watchdog due to shared code calling
esp_task_wdt_feed().

Task watchdog is now fully configurable at runtime by calling the init and
deinit functions.

Also added functions to get the handles of idle tasks of the other core. This
helps when adding idle tasks to the watchdog at run time.

Configuring the task watchdog using menu config is still available, however
menu config will only result in calling the init and add functions for idle
tasks shortly after the scheduler starts.

Menu config also allows for using legacy behavior, however the legacy behavior
willcall the new API functions but with slight variations to make them legacy
compatible.

Documentation and example have also been updated

gcov_rtio.c headers updated to prevent error of freertos header files being
included in the wrong order.

Resolves issue TW#13265
This commit is contained in:
Darian Leung
2017-08-30 21:11:10 +08:00
parent ae9041ab71
commit 616baa239d
12 changed files with 645 additions and 194 deletions
+42 -18
View File
@@ -28,23 +28,40 @@ Task watchdog
^^^^^^^^^^^^^
Any tasks can elect to be watched by the task watchdog. If such a task does not feed the watchdog within the time
specified by the task watchdog timeout (which is configurable using ``make menuconfig``), the watchdog will
print out a warning with information about which processes are running on the ESP32 CPUs and which processes
failed to feed the watchdog.
specified by the task watchdog timeout, the watchdog will print out a warning with information about which processes
are running on the ESP32 CPUs and which processes failed to feed the watchdog.
By default, the task watchdog watches the idle tasks. The usual cause of idle tasks not feeding the watchdog
Ideally, the task watchdog should watch the idle tasks. The usual cause of the idle tasks not feeding the watchdog
is a higher-priority process looping without yielding to the lower-priority processes, and can be an indicator
of badly-written code that spinloops on a peripheral or a task that is stuck in an infinite loop.
Other task can elect to be watched by the task watchdog by calling ``esp_task_wdt_feed()``. Calling this routine
for the first time will register the task to the task watchdog; calling it subsequent times will feed
the watchdog. If a task does not want to be watched anymore (e.g. because it is finished and will call
``vTaskDelete()`` on itself), it needs to call ``esp_task_wdt_delete()``.
Other task can elect to be watched by the task watchdog. If the watchdog watches multiple tasks, all the tasks
must feed before the watchdog times out. If one or more tasks fails to feed, the watchdog timeout will trigger.
The watchdog timer can be initialized using :cpp:func:`esp_task_wdt_init` which will configure the hardware timer and
establish the hardware timer interrupts. In order for a task to be watched by the task watchdog, a task must subscribe to
the task watchdog using :cpp:func:`esp_task_wdt_add`. Once added, each subscribed task must call :cpp:func:`esp_task_wdt_feed`
periodically to prevent the watchdog from timing out. If all tasks being watched have fed, the watchdog timer counter immediately resets
and starts recounting to the timeout value from zero. To unsubscribe a task from the task watchdog, call :cpp:func:`esp_task_wdt_delete()`.
Once all tasks have been unsubscribed form the task watchdog, :cpp:func:`esp_task_wdt_deinit()` can be called to deinitialize
the task watchdog. Deinitialization will stop the hardware timer, deregister the hardware timer interrupts, and remove the idle hooks
if idle tasks were being watched.
The task watchdog is built around the hardware watchdog in timer group 0. If this watchdog for some reason
By setting the task watchdog options in ``make menuconfig``, the task watchdog can be automatically initialized
during startup by enabling the :ref:`CONFIG_TASK_WDT`. Moreover the two Idle tasks can also be subscibed to the
task watchdog on startup as well by enabling :ref:`CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0` and
:ref:`CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1`.
The task watchdog is built around the hardware watchdog in timer group 0. If the watchdog for some reason
cannot execute the interrupt handler that prints the task data (e.g. because IRAM is overwritten by garbage
or interrupts are disabled entirely) it will hard-reset the SOC.
Note: ``make menuconfig`` provides a :ref:`CONFIG_TASK_WDT_LEGACY_BEHAVIOR` option which will change the behavior of the
task watchdog to make it compatible with the legacy code. Note that the legacy behavior causes tasks to subscribe to the
task watchdog on their first call to :cpp:func:`esp_task_wdt_feed`. Moreover, legacy behavior only allows
tasks to unsubscribe on their own behalf when calling :cpp:func:`esp_task_wdt_delete()`. It is strongly recommended that
non-legacy behavior is used as additions/deletions/feeds are explicit.
JTAG and watchdogs
^^^^^^^^^^^^^^^^^^
@@ -53,20 +70,27 @@ CPU. This makes it very hard to debug code; that is why the OpenOCD config will
This does mean that you will not get any warnings or panics from either the task or interrupt watchdog when the ESP32
is connected to OpenOCD via JTAG.
API Reference
-------------
Interrupt Watchdog API Reference
--------------------------------
Header Files
^^^^^^^^^^^^
Header File
^^^^^^^^^^^
* :component_file:`esp32/include/esp_int_wdt.h`
* :component_file:`esp32/include/esp_task_wdt.h`
Functions
---------
.. doxygenfunction:: esp_int_wdt_init
.. doxygenfunction:: esp_task_wdt_init
.. doxygenfunction:: esp_task_wdt_feed
.. doxygenfunction:: esp_task_wdt_delete
Task Watchdog API Reference
----------------------------
NOTE: Ensure that the :ref:`CONFIG_TASK_WDT_LEGACY_BEHAVIOR` configuraiton is disabled using ``make menuconfig``
to prevent legacy behavior of the task watchdog.
A full example using the Task Watchdog is available in esp-idf: :example:`system/task_watchdog`
.. include:: /_build/inc/esp_task_wdt.inc