freertos-smp.rst 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. ESP-IDF FreeRTOS SMP Changes
  2. ============================
  3. Overview
  4. --------
  5. .. only:: not CONFIG_FREERTOS_UNICORE
  6. The vanilla FreeRTOS is designed to run on a single core. However the ESP32 is
  7. dual core containing a Protocol CPU (known as **CPU 0** or **PRO_CPU**) and an
  8. Application CPU (known as **CPU 1** or **APP_CPU**). The two cores are
  9. identical in practice and share the same memory. This allows the two cores to
  10. run tasks interchangeably between them.
  11. The ESP-IDF FreeRTOS is a modified version of vanilla FreeRTOS which supports
  12. symmetric multiprocessing (SMP). ESP-IDF FreeRTOS is based on the Xtensa port
  13. of FreeRTOS v8.2.0. This guide outlines the major differences between vanilla
  14. FreeRTOS and ESP-IDF FreeRTOS. The API reference for vanilla FreeRTOS can be
  15. found via https://www.freertos.org/a00106.html
  16. For information regarding features that are exclusive to ESP-IDF FreeRTOS,
  17. see :doc:`ESP-IDF FreeRTOS Additions<../api-reference/system/freertos_additions>`.
  18. :ref:`backported-features`: Although ESP-IDF FreeRTOS is based on the Xtensa
  19. port of FreeRTOS v8.2.0, a number of FreeRTOS v9.0.0 features have been backported
  20. to ESP-IDF.
  21. .. only:: not CONFIG_FREERTOS_UNICORE
  22. :ref:`tasks-and-task-creation`: Use :cpp:func:`xTaskCreatePinnedToCore` or
  23. :cpp:func:`xTaskCreateStaticPinnedToCore` to create tasks in ESP-IDF FreeRTOS. The
  24. last parameter of the two functions is ``xCoreID``. This parameter specifies
  25. which core the task is pinned to. Acceptable values are ``0`` for **PRO_CPU**,
  26. ``1`` for **APP_CPU**, or ``tskNO_AFFINITY`` which allows the task to run on
  27. both.
  28. :ref:`round-robin-scheduling`: The ESP-IDF FreeRTOS scheduler will skip tasks when
  29. implementing Round-Robin scheduling between multiple tasks in the Ready state
  30. that are of the same priority. To avoid this behavior, ensure that those tasks either
  31. enter a blocked state, or are distributed across a wider range of priorities.
  32. :ref:`scheduler-suspension`: Suspending the scheduler in ESP-IDF FreeRTOS will only
  33. affect the scheduler on the the calling core. In other words, calling
  34. :cpp:func:`vTaskSuspendAll` on **PRO_CPU** will not prevent **APP_CPU** from scheduling, and
  35. vice versa. Use critical sections or semaphores instead for simultaneous
  36. access protection.
  37. :ref:`tick-interrupt-synchronicity`: Tick interrupts of **PRO_CPU** and **APP_CPU**
  38. are not synchronized. Do not expect to use :cpp:func:`vTaskDelay` or
  39. :cpp:func:`vTaskDelayUntil` as an accurate method of synchronizing task execution
  40. between the two cores. Use a counting semaphore instead as their context
  41. switches are not tied to tick interrupts due to preemption.
  42. :ref:`critical-sections`: In ESP-IDF FreeRTOS, critical sections are implemented using
  43. mutexes. Entering critical sections involve taking a mutex, then disabling the
  44. scheduler and interrupts of the calling core. However the other core is left
  45. unaffected. If the other core attemps to take same mutex, it will spin until
  46. the calling core has released the mutex by exiting the critical section.
  47. :ref:`floating-points`: The {IDF_TARGET_NAME} supports hardware acceleration of single
  48. precision floating point arithmetic (``float``). However the use of hardware
  49. acceleration leads to some behavioral restrictions in ESP-IDF FreeRTOS.
  50. Therefore, tasks that utilize ``float`` will automatically be pinned to a core if
  51. not done so already. Furthermore, ``float`` cannot be used in interrupt service
  52. routines.
  53. `Task Deletion`_: Task deletion behavior has been backported from FreeRTOS
  54. v9.0.0 and modified to be SMP compatible. Task memory will be freed immediately
  55. when :cpp:func:`vTaskDelete` is called to delete a task that is not currently running
  56. and not pinned to the other core. Otherwise, freeing of task memory will still
  57. be delegated to the Idle Task.
  58. :ref:`deletion-callbacks`: ESP-IDF FreeRTOS has backported the Thread Local
  59. Storage Pointers (TLSP) feature. However the extra feature of Deletion Callbacks has been
  60. added. Deletion callbacks are called automatically during task deletion and are
  61. used to free memory pointed to by TLSP. Call
  62. :cpp:func:`vTaskSetThreadLocalStoragePointerAndDelCallback()` to set TLSP and Deletion
  63. Callbacks.
  64. :ref:`esp-idf-freertos-configuration`: Several aspects of ESP-IDF FreeRTOS can be
  65. set in the project configuration (``idf.py menuconfig``) such as running ESP-IDF in
  66. Unicore (single core) Mode, or configuring the number of Thread Local Storage Pointers
  67. each task will have.
  68. .. _backported-features:
  69. Backported Features
  70. -------------------
  71. The following features have been backported from FreeRTOS v9.0.0 to ESP-IDF.
  72. Static Alocation
  73. ^^^^^^^^^^^^^^^^^
  74. This feature has been backported from FreeRTOS v9.0.0 to ESP-IDF. The
  75. :ref:`CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION` option must be enabled in `menuconfig`
  76. in order for static allocation functions to be available. Once enabled, the
  77. following functions can be called...
  78. - :cpp:func:`xTaskCreateStatic` (see :ref:`backporting-notes` below)
  79. - :c:macro:`xQueueCreateStatic`
  80. - :c:macro:`xSemaphoreCreateBinaryStatic`
  81. - :c:macro:`xSemaphoreCreateCountingStatic`
  82. - :c:macro:`xSemaphoreCreateMutexStatic`
  83. - :c:macro:`xSemaphoreCreateRecursiveMutexStatic`
  84. - :cpp:func:`xTimerCreateStatic` (see :ref:`backporting-notes` below)
  85. - :cpp:func:`xEventGroupCreateStatic`
  86. Other Features
  87. ^^^^^^^^^^^^^^
  88. - :cpp:func:`vTaskSetThreadLocalStoragePointer` (see :ref:`backporting-notes` below)
  89. - :cpp:func:`pvTaskGetThreadLocalStoragePointer` (see :ref:`backporting-notes` below)
  90. - :cpp:func:`vTimerSetTimerID`
  91. - :cpp:func:`xTimerGetPeriod`
  92. - :cpp:func:`xTimerGetExpiryTime`
  93. - :cpp:func:`pcQueueGetName`
  94. - :c:macro:`uxSemaphoreGetCount`
  95. .. _backporting-notes:
  96. Backporting Notes
  97. ^^^^^^^^^^^^^^^^^
  98. **1)** :cpp:func:`xTaskCreateStatic` has been made SMP compatible in a similar
  99. fashion to :cpp:func:`xTaskCreate` (see :ref:`tasks-and-task-creation`). Therefore
  100. :cpp:func:`xTaskCreateStaticPinnedToCore` can also be called.
  101. **2)** Although vanilla FreeRTOS allows the Timer feature's daemon task to
  102. be statically allocated, the daemon task is always dynamically allocated in
  103. ESP-IDF. Therefore ``vApplicationGetTimerTaskMemory`` **does not** need to be
  104. defined when using statically allocated timers in ESP-IDF FreeRTOS.
  105. **3)** The Thread Local Storage Pointer feature has been modified in ESP-IDF
  106. FreeRTOS to include Deletion Callbacks (see :ref:`deletion-callbacks`). Therefore
  107. the function :cpp:func:`vTaskSetThreadLocalStoragePointerAndDelCallback` can also be
  108. called.
  109. .. _tasks-and-task-creation:
  110. Tasks and Task Creation
  111. -----------------------
  112. Tasks in ESP-IDF FreeRTOS are designed to run on a particular core, therefore
  113. two new task creation functions have been added to ESP-IDF FreeRTOS by
  114. appending ``PinnedToCore`` to the names of the task creation functions in
  115. vanilla FreeRTOS. The vanilla FreeRTOS functions of :cpp:func:`xTaskCreate`
  116. and :cpp:func:`xTaskCreateStatic` have led to the addition of
  117. :cpp:func:`xTaskCreatePinnedToCore` and :cpp:func:`xTaskCreateStaticPinnedToCore` in
  118. ESP-IDF FreeRTOS (see :ref:`backported-features`).
  119. For more details see :component_file:`freertos/tasks.c`
  120. The ESP-IDF FreeRTOS task creation functions are nearly identical to their
  121. vanilla counterparts with the exception of the extra parameter known as
  122. ``xCoreID``. This parameter specifies the core on which the task should run on
  123. and can be one of the following values.
  124. - ``0`` pins the task to **PRO_CPU**
  125. - ``1`` pins the task to **APP_CPU**
  126. - ``tskNO_AFFINITY`` allows the task to be run on both CPUs
  127. For example ``xTaskCreatePinnedToCore(tsk_callback, “APP_CPU Task”, 1000, NULL, 10, NULL, 1)``
  128. creates a task of priority 10 that is pinned to **APP_CPU** with a stack size
  129. of 1000 bytes. It should be noted that the ``uxStackDepth`` parameter in
  130. vanilla FreeRTOS specifies a task’s stack depth in terms of the number of
  131. words, whereas ESP-IDF FreeRTOS specifies the stack depth in terms of bytes.
  132. Note that the vanilla FreeRTOS functions :cpp:func:`xTaskCreate` and
  133. :cpp:func:`xTaskCreateStatic` have been defined in ESP-IDF FreeRTOS as inline functions which call
  134. :cpp:func:`xTaskCreatePinnedToCore` and :cpp:func:`xTaskCreateStaticPinnedToCore`
  135. respectively with ``tskNO_AFFINITY`` as the ``xCoreID`` value.
  136. Each Task Control Block (TCB) in ESP-IDF stores the ``xCoreID`` as a member.
  137. Hence when each core calls the scheduler to select a task to run, the
  138. ``xCoreID`` member will allow the scheduler to determine if a given task is
  139. permitted to run on the core that called it.
  140. Scheduling
  141. ----------
  142. The vanilla FreeRTOS implements scheduling in the ``vTaskSwitchContext()``
  143. function. This function is responsible for selecting the highest priority task
  144. to run from a list of tasks in the Ready state known as the Ready Tasks List
  145. (described in the next section). In ESP-IDF FreeRTOS, each core will call
  146. ``vTaskSwitchContext()`` independently to select a task to run from the
  147. Ready Tasks List which is shared between both cores. There are several
  148. differences in scheduling behavior between vanilla and ESP-IDF FreeRTOS such as
  149. differences in Round Robin scheduling, scheduler suspension, and tick interrupt
  150. synchronicity.
  151. .. _round-robin-scheduling:
  152. Round Robin Scheduling
  153. ^^^^^^^^^^^^^^^^^^^^^^
  154. Given multiple tasks in the Ready state and of the same priority, vanilla
  155. FreeRTOS implements Round Robin scheduling between each task. This will result
  156. in running those tasks in turn each time the scheduler is called
  157. (e.g. every tick interrupt). On the other hand, the ESP-IDF FreeRTOS scheduler
  158. may skip tasks when Round Robin scheduling multiple Ready state tasks of the
  159. same priority.
  160. The issue of skipping tasks during Round Robin scheduling arises from the way
  161. the Ready Tasks List is implemented in FreeRTOS. In vanilla FreeRTOS,
  162. ``pxReadyTasksList`` is used to store a list of tasks that are in the Ready
  163. state. The list is implemented as an array of length ``configMAX_PRIORITIES``
  164. where each element of the array is a linked list. Each linked list is of type
  165. ``List_t`` and contains TCBs of tasks of the same priority that are in the
  166. Ready state. The following diagram illustrates the ``pxReadyTasksList``
  167. structure.
  168. .. figure:: ../../_static/freertos-ready-task-list.png
  169. :align: center
  170. :alt: Vanilla FreeRTOS Ready Task List Structure
  171. Illustration of FreeRTOS Ready Task List Data Structure
  172. Each linked list also contains a ``pxIndex`` which points to the last TCB
  173. returned when the list was queried. This index allows the ``vTaskSwitchContext()``
  174. to start traversing the list at the TCB immediately after ``pxIndex`` hence
  175. implementing Round Robin Scheduling between tasks of the same priority.
  176. In ESP-IDF FreeRTOS, the Ready Tasks List is shared between cores hence
  177. ``pxReadyTasksList`` will contain tasks pinned to different cores. When a core
  178. calls the scheduler, it is able to look at the ``xCoreID`` member of each TCB
  179. in the list to determine if a task is allowed to run on calling the core. The
  180. ESP-IDF FreeRTOS ``pxReadyTasksList`` is illustrated below.
  181. .. figure:: ../../_static/freertos-ready-task-list-smp.png
  182. :align: center
  183. :alt: ESP-IDF FreeRTOS Ready Task List Structure
  184. Illustration of FreeRTOS Ready Task List Data Structure in ESP-IDF
  185. Therefore when **PRO_CPU** calls the scheduler, it will only consider the tasks
  186. in blue or purple. Whereas when **APP_CPU** calls the scheduler, it will only
  187. consider the tasks in orange or purple.
  188. Although each TCB has an ``xCoreID`` in ESP-IDF FreeRTOS, the linked list of
  189. each priority only has a single ``pxIndex``. Therefore when the scheduler is
  190. called from a particular core and traverses the linked list, it will skip all
  191. TCBs pinned to the other core and point the pxIndex at the selected task. If
  192. the other core then calls the scheduler, it will traverse the linked list
  193. starting at the TCB immediately after ``pxIndex``. Therefore, TCBs skipped on
  194. the previous scheduler call from the other core would not be considered on the
  195. current scheduler call. This issue is demonstrated in the following
  196. illustration.
  197. .. figure:: ../../_static/freertos-ready-task-list-smp-pxIndex.png
  198. :align: center
  199. :alt: ESP-IDF pxIndex Behavior
  200. Illustration of pxIndex behavior in ESP-IDF FreeRTOS
  201. Referring to the illustration above, assume that priority 9 is the highest
  202. priority, and none of the tasks in priority 9 will block hence will always be
  203. either in the running or Ready state.
  204. 1) **PRO_CPU** calls the scheduler and selects Task A to run, hence moves
  205. ``pxIndex`` to point to Task A
  206. 2) **APP_CPU** calls the scheduler and starts traversing from the task after
  207. ``pxIndex`` which is Task B. However Task B is not selected to run as it is not
  208. pinned to **APP_CPU** hence it is skipped and Task C is selected instead.
  209. ``pxIndex`` now points to Task C
  210. 3) **PRO_CPU** calls the scheduler and starts traversing from Task D. It skips
  211. Task D and selects Task E to run and points ``pxIndex`` to Task E. Notice that
  212. Task B isn’t traversed because it was skipped the last time **APP_CPU** called
  213. the scheduler to traverse the list.
  214. 4) The same situation with Task D will occur if **APP_CPU** calls the
  215. scheduler again as ``pxIndex`` now points to Task E
  216. One solution to the issue of task skipping is to ensure that every task will
  217. enter a blocked state so that they are removed from the Ready Task List.
  218. Another solution is to distribute tasks across multiple priorities such that
  219. a given priority will not be assigned multiple tasks that are pinned to
  220. different cores.
  221. .. _scheduler-suspension:
  222. Scheduler Suspension
  223. ^^^^^^^^^^^^^^^^^^^^
  224. In vanilla FreeRTOS, suspending the scheduler via :cpp:func:`vTaskSuspendAll` will
  225. prevent calls of ``vTaskSwitchContext`` from context switching until the
  226. scheduler has been resumed with :cpp:func:`xTaskResumeAll`. However servicing ISRs
  227. are still permitted. Therefore any changes in task states as a result from the
  228. current running task or ISRSs will not be executed until the scheduler is
  229. resumed. Scheduler suspension in vanilla FreeRTOS is a common protection method
  230. against simultaneous access of data shared between tasks, whilst still allowing
  231. ISRs to be serviced.
  232. In ESP-IDF FreeRTOS, :cpp:func:`xTaskSuspendAll` will only prevent calls of
  233. ``vTaskSwitchContext()`` from switching contexts on the core that called for the
  234. suspension. Hence if **PRO_CPU** calls :cpp:func:`vTaskSuspendAll`, **APP_CPU** will
  235. still be able to switch contexts. If data is shared between tasks that are
  236. pinned to different cores, scheduler suspension is **NOT** a valid method of
  237. protection against simultaneous access. Consider using critical sections
  238. (disables interrupts) or semaphores (does not disable interrupts) instead when
  239. protecting shared resources in ESP-IDF FreeRTOS.
  240. In general, it's better to use other RTOS primitives like mutex semaphores to protect
  241. against data shared between tasks, rather than :cpp:func:`vTaskSuspendAll`.
  242. .. _tick-interrupt-synchronicity:
  243. Tick Interrupt Synchronicity
  244. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  245. In ESP-IDF FreeRTOS, tasks on different cores that unblock on the same tick
  246. count might not run at exactly the same time due to the scheduler calls from
  247. each core being independent, and the tick interrupts to each core being
  248. unsynchronized.
  249. In vanilla FreeRTOS the tick interrupt triggers a call to
  250. :cpp:func:`xTaskIncrementTick` which is responsible for incrementing the tick
  251. counter, checking if tasks which have called :cpp:func:`vTaskDelay` have fulfilled
  252. their delay period, and moving those tasks from the Delayed Task List to the
  253. Ready Task List. The tick interrupt will then call the scheduler if a context
  254. switch is necessary.
  255. In ESP-IDF FreeRTOS, delayed tasks are unblocked with reference to the tick
  256. interrupt on PRO_CPU as PRO_CPU is responsible for incrementing the shared tick
  257. count. However tick interrupts to each core might not be synchronized (same
  258. frequency but out of phase) hence when PRO_CPU receives a tick interrupt,
  259. APP_CPU might not have received it yet. Therefore if multiple tasks of the same
  260. priority are unblocked on the same tick count, the task pinned to PRO_CPU will
  261. run immediately whereas the task pinned to APP_CPU must wait until APP_CPU
  262. receives its out of sync tick interrupt. Upon receiving the tick interrupt,
  263. APP_CPU will then call for a context switch and finally switches contexts to
  264. the newly unblocked task.
  265. Therefore, task delays should **NOT** be used as a method of synchronization
  266. between tasks in ESP-IDF FreeRTOS. Instead, consider using a counting semaphore
  267. to unblock multiple tasks at the same time.
  268. .. _critical-sections:
  269. Critical Sections & Disabling Interrupts
  270. ----------------------------------------
  271. Vanilla FreeRTOS implements critical sections in ``vTaskEnterCritical`` which
  272. disables the scheduler and calls ``portDISABLE_INTERRUPTS``. This prevents
  273. context switches and servicing of ISRs during a critical section. Therefore,
  274. critical sections are used as a valid protection method against simultaneous
  275. access in vanilla FreeRTOS.
  276. .. only:: not CONFIG_FREERTOS_UNICORE
  277. On the other hand, the ESP32 has no hardware method for cores to disable each
  278. other’s interrupts. Calling ``portDISABLE_INTERRUPTS()`` will have no effect on
  279. the interrupts of the other core. Therefore, disabling interrupts is **NOT**
  280. a valid protection method against simultaneous access to shared data as it
  281. leaves the other core free to access the data even if the current core has
  282. disabled its own interrupts.
  283. .. only:: CONFIG_FREERTOS_UNICORE
  284. ESP-IDF contains some modifications to work with dual core concurrency,
  285. and the dual core API is used even on a single core only chip.
  286. For this reason, ESP-IDF FreeRTOS implements critical sections using special mutexes,
  287. referred by portMUX_Type objects on top of specific spinlock component
  288. and calls to enter or exit a critical must provide a spinlock object that
  289. is associated with a shared resource requiring access protection.
  290. When entering a critical section in ESP-IDF FreeRTOS, the calling core will disable
  291. its scheduler and interrupts similar to the vanilla FreeRTOS implementation. However,
  292. the calling core will also take the locks whilst the other core is left unaffected during
  293. the critical section. If the other core attempts to take the spinlock, it
  294. will spin until the lock is released. Therefore, the ESP-IDF FreeRTOS
  295. implementation of critical sections allows a core to have protected access to a
  296. shared resource without disabling the other core. The other core will only be
  297. affected if it tries to concurrently access the same resource.
  298. The ESP-IDF FreeRTOS critical section functions have been modified as follows…
  299. - ``taskENTER_CRITICAL(mux)``, ``taskENTER_CRITICAL_ISR(mux)``,
  300. ``portENTER_CRITICAL(mux)``, ``portENTER_CRITICAL_ISR(mux)`` are all macro
  301. defined to call :cpp:func:`vTaskEnterCritical`
  302. - ``taskEXIT_CRITICAL(mux)``, ``taskEXIT_CRITICAL_ISR(mux)``,
  303. ``portEXIT_CRITICAL(mux)``, ``portEXIT_CRITICAL_ISR(mux)`` are all macro
  304. defined to call :cpp:func:`vTaskExitCritical`
  305. - ``portENTER_CRITICAL_SAFE(mux)``, ``portEXIT_CRITICAL_SAFE(mux)`` macro identifies
  306. the context of execution, i.e ISR or Non-ISR, and calls appropriate critical
  307. section functions (``port*_CRITICAL`` in Non-ISR and ``port*_CRITICAL_ISR`` in ISR)
  308. in order to be in compliance with Vanilla FreeRTOS.
  309. For more details see :component_file:`soc/include/soc/spinlock.h`
  310. and :component_file:`freertos/tasks.c`
  311. It should be noted that when modifying vanilla FreeRTOS code to be ESP-IDF
  312. FreeRTOS compatible, it is trivial to modify the type of critical section
  313. called as they are all defined to call the same function. As long as the same
  314. spinlock is provided upon entering and exiting, the type of call should not
  315. matter.
  316. .. only:: not CONFIG_FREERTOS_UNICORE
  317. .. _floating-points:
  318. Floating Point Arithmetic
  319. -------------------------
  320. ESP-IDF FreeRTOS implements Lazy Context Switching for FPUs. In other words,
  321. the state of a core's FPU registers are not immediately saved when a context
  322. switch occurs. Therefore, tasks that utilize ``float`` must be pinned to a
  323. particular core upon creation. If not, ESP-IDF FreeRTOS will automatically pin
  324. the task in question to whichever core the task was running on upon the task's
  325. first use of ``float``. Likewise due to Lazy Context Switching, only interrupt
  326. service routines of lowest priority (that is it the Level 1) can use ``float``,
  327. higher priority interrupts do not support FPU usage.
  328. ESP32 does not support hardware acceleration for double precision floating point
  329. arithmetic (``double``). Instead ``double`` is implemented via software hence the
  330. behavioral restrictions with regards to ``float`` do not apply to ``double``. Note
  331. that due to the lack of hardware acceleration, ``double`` operations may consume
  332. significantly larger amount of CPU time in comparison to ``float``.
  333. .. _task-deletion:
  334. Task Deletion
  335. -------------
  336. FreeRTOS task deletion prior to v9.0.0 delegated the freeing of task memory
  337. entirely to the Idle Task. Currently, the freeing of task memory will occur
  338. immediately (within :cpp:func:`vTaskDelete`) if the task being deleted is not currently
  339. running or is not pinned to the other core (with respect to the core
  340. :cpp:func:`vTaskDelete` is called on). TLSP deletion callbacks will also run immediately
  341. if the same conditions are met.
  342. However, calling :cpp:func:`vTaskDelete` to delete a task that is either currently
  343. running or pinned to the other core will still result in the freeing of memory
  344. being delegated to the Idle Task.
  345. .. _deletion-callbacks:
  346. Thread Local Storage Pointers & Deletion Callbacks
  347. --------------------------------------------------
  348. Thread Local Storage Pointers (TLSP) are pointers stored directly in the TCB.
  349. TLSP allow each task to have its own unique set of pointers to data structures.
  350. However task deletion behavior in vanilla FreeRTOS does not automatically
  351. free the memory pointed to by TLSP. Therefore if the memory pointed to by
  352. TLSP is not explicitly freed by the user before task deletion, memory leak will
  353. occur.
  354. ESP-IDF FreeRTOS provides the added feature of Deletion Callbacks. Deletion
  355. Callbacks are called automatically during task deletion to free memory pointed
  356. to by TLSP. Each TLSP can have its own Deletion Callback. Note that due to the
  357. to `Task Deletion`_ behavior, there can be instances where Deletion
  358. Callbacks are called in the context of the Idle Tasks. Therefore Deletion
  359. Callbacks **should never attempt to block** and critical sections should be kept
  360. as short as possible to minimize priority inversion.
  361. Deletion callbacks are of type
  362. ``void (*TlsDeleteCallbackFunction_t)( int, void * )`` where the first parameter
  363. is the index number of the associated TLSP, and the second parameter is the
  364. TLSP itself.
  365. Deletion callbacks are set alongside TLSP by calling
  366. :cpp:func:`vTaskSetThreadLocalStoragePointerAndDelCallback`. Calling the vanilla
  367. FreeRTOS function :cpp:func:`vTaskSetThreadLocalStoragePointer` will simply set the
  368. TLSP's associated Deletion Callback to `NULL` meaning that no callback will be
  369. called for that TLSP during task deletion. If a deletion callback is `NULL`,
  370. users should manually free the memory pointed to by the associated TLSP before
  371. task deletion in order to avoid memory leak.
  372. :ref:`CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS` in menuconfig can be used
  373. to configure the number TLSP and Deletion Callbacks a TCB will have.
  374. For more details see :doc:`FreeRTOS API reference<../api-reference/system/freertos>`.
  375. .. _esp-idf-freertos-configuration:
  376. Configuring ESP-IDF FreeRTOS
  377. ----------------------------
  378. The ESP-IDF FreeRTOS can be configured in the project configuration menu
  379. (``idf.py menuconfig``) under ``Component Config/FreeRTOS``. The following section
  380. highlights some of the ESP-IDF FreeRTOS configuration options. For a full list of
  381. ESP-IDF FreeRTOS configurations, see :doc:`FreeRTOS <../api-reference/kconfig>`
  382. .. only:: not CONFIG_FREERTOS_UNICORE
  383. :ref:`CONFIG_FREERTOS_UNICORE` will run ESP-IDF FreeRTOS only
  384. on **PRO_CPU**. Note that this is **not equivalent to running vanilla
  385. FreeRTOS**. Behaviors of multiple components in ESP-IDF will be modified such
  386. as :component_file:`esp32/cpu_start.c`. For more details regarding the
  387. effects of running ESP-IDF FreeRTOS on a single core, search for
  388. occurences of ``CONFIG_FREERTOS_UNICORE`` in the ESP-IDF components.
  389. .. only:: CONFIG_FREERTOS_UNICORE
  390. As {IDF_TARGET_NAME} is a single core SoC, the config item :ref:`CONFIG_FREERTOS_UNICORE` is
  391. always set. This means ESP-IDF only runs on the single CPU. Note that this is **not
  392. equivalent to running vanilla FreeRTOS**. Behaviors of multiple components in ESP-IDF
  393. will be modified. For more details regarding the effects of running ESP-IDF FreeRTOS
  394. on a single core, search for occurences of ``CONFIG_FREERTOS_UNICORE`` in the ESP-IDF components.
  395. :ref:`CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS` will define the
  396. number of Thread Local Storage Pointers each task will have in ESP-IDF
  397. FreeRTOS.
  398. :ref:`CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION` will enable the backported
  399. functionality of :cpp:func:`xTaskCreateStaticPinnedToCore` in ESP-IDF FreeRTOS
  400. :ref:`CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION` will trigger a halt in
  401. particular functions in ESP-IDF FreeRTOS which have not been fully tested
  402. in an SMP context.
  403. :ref:`CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER` will enclose all task functions
  404. within a wrapper function. In the case that a task function mistakenly returns
  405. (i.e. does not call :cpp:func:`vTaskDelete`), the call flow will return to the
  406. wrapper function. The wrapper function will then log an error and abort the
  407. application, as illustrated below::
  408. E (25) FreeRTOS: FreeRTOS task should not return. Aborting now!
  409. abort() was called at PC 0x40085c53 on core 0