mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-03 12:44:33 +02:00
docs: Update SMP descriptions for taskENTER_CRITICAL/taskEXIT_CRITICAL
Closes https://github.com/espressif/esp-idf/issues/6259
This commit is contained in:
@@ -134,7 +134,7 @@ do not disable the interrupts (because they already are).
|
|||||||
This all assumes that interrupts are either entirely disabled or enabled. Interrupt priority levels
|
This all assumes that interrupts are either entirely disabled or enabled. Interrupt priority levels
|
||||||
will break this scheme.
|
will break this scheme.
|
||||||
|
|
||||||
Remark: For the ESP32, portENTER_CRITICAL and portENTER_CRITICAL_ISR both alias vTaskEnterCritical, meaning
|
Remark: For the ESP32, portENTER_CRITICAL and portENTER_CRITICAL_ISR both alias vPortEnterCritical, meaning
|
||||||
that either function can be called both from ISR as well as task context. This is not standard FreeRTOS
|
that either function can be called both from ISR as well as task context. This is not standard FreeRTOS
|
||||||
behaviour; please keep this in mind if you need any compatibility with other FreeRTOS implementations.
|
behaviour; please keep this in mind if you need any compatibility with other FreeRTOS implementations.
|
||||||
*/
|
*/
|
||||||
|
@@ -223,7 +223,7 @@ In vanilla FreeRTOS, suspending the scheduler via :cpp:func:`vTaskSuspendAll` wi
|
|||||||
prevent calls of ``vTaskSwitchContext`` from context switching until the
|
prevent calls of ``vTaskSwitchContext`` from context switching until the
|
||||||
scheduler has been resumed with :cpp:func:`xTaskResumeAll`. However servicing ISRs
|
scheduler has been resumed with :cpp:func:`xTaskResumeAll`. However servicing ISRs
|
||||||
are still permitted. Therefore any changes in task states as a result from the
|
are still permitted. Therefore any changes in task states as a result from the
|
||||||
current running task or ISRSs will not be executed until the scheduler is
|
current running task or ISRs will not be executed until the scheduler is
|
||||||
resumed. Scheduler suspension in vanilla FreeRTOS is a common protection method
|
resumed. Scheduler suspension in vanilla FreeRTOS is a common protection method
|
||||||
against simultaneous access of data shared between tasks, whilst still allowing
|
against simultaneous access of data shared between tasks, whilst still allowing
|
||||||
ISRs to be serviced.
|
ISRs to be serviced.
|
||||||
@@ -279,15 +279,14 @@ to unblock multiple tasks at the same time.
|
|||||||
Critical Sections & Disabling Interrupts
|
Critical Sections & Disabling Interrupts
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
Vanilla FreeRTOS implements critical sections in ``vTaskEnterCritical`` which
|
Vanilla FreeRTOS implements critical sections with ``taskENTER_CRITICAL()`` which
|
||||||
disables the scheduler and calls ``portDISABLE_INTERRUPTS``. This prevents
|
calls ``portDISABLE_INTERRUPTS()``. This prevents preemptive context switches and
|
||||||
context switches and servicing of ISRs during a critical section. Therefore,
|
servicing of ISRs during a critical section. Therefore, critical sections are
|
||||||
critical sections are used as a valid protection method against simultaneous
|
used as a valid protection method against simultaneous access in vanilla FreeRTOS.
|
||||||
access in vanilla FreeRTOS.
|
|
||||||
|
|
||||||
.. only:: not CONFIG_FREERTOS_UNICORE
|
.. only:: not CONFIG_FREERTOS_UNICORE
|
||||||
|
|
||||||
On the other hand, the ESP32 has no hardware method for cores to disable each
|
On the other hand, {IDF_TARGET_NAME} has no hardware method for cores to disable each
|
||||||
other’s interrupts. Calling ``portDISABLE_INTERRUPTS()`` will have no effect on
|
other’s interrupts. Calling ``portDISABLE_INTERRUPTS()`` will have no effect on
|
||||||
the interrupts of the other core. Therefore, disabling interrupts is **NOT**
|
the interrupts of the other core. Therefore, disabling interrupts is **NOT**
|
||||||
a valid protection method against simultaneous access to shared data as it
|
a valid protection method against simultaneous access to shared data as it
|
||||||
@@ -299,42 +298,44 @@ access in vanilla FreeRTOS.
|
|||||||
ESP-IDF contains some modifications to work with dual core concurrency,
|
ESP-IDF contains some modifications to work with dual core concurrency,
|
||||||
and the dual core API is used even on a single core only chip.
|
and the dual core API is used even on a single core only chip.
|
||||||
|
|
||||||
For this reason, ESP-IDF FreeRTOS implements critical sections using special mutexes,
|
For this reason, ESP-IDF FreeRTOS implements critical sections using special
|
||||||
referred by portMUX_Type objects on top of specific spinlock component
|
mutexes, referred by ``portMUX_Type`` objects. These are implemented on top of a
|
||||||
and calls to enter or exit a critical must provide a spinlock object that
|
specific spinlock component. Calls to ``taskENTER_CRITICAL`` or
|
||||||
is associated with a shared resource requiring access protection.
|
``taskEXIT_CRITICAL`` each provide a spinlock object as an argument. The
|
||||||
When entering a critical section in ESP-IDF FreeRTOS, the calling core will disable
|
spinlock is associated with a shared resource requiring access protection. When
|
||||||
its scheduler and interrupts similar to the vanilla FreeRTOS implementation. However,
|
entering a critical section in ESP-IDF FreeRTOS, the calling core will disable
|
||||||
the calling core will also take the locks whilst the other core is left unaffected during
|
interrupts similar to the vanilla FreeRTOS implementation, and will then take the
|
||||||
the critical section. If the other core attempts to take the spinlock, it
|
spinlock and enter the critical section. The other core is unaffected at this point,
|
||||||
will spin until the lock is released. Therefore, the ESP-IDF FreeRTOS
|
unless it enters its own critical section and attempts to take the same spinlock.
|
||||||
implementation of critical sections allows a core to have protected access to a
|
In that case it will spin until the lock is released. Therefore, the ESP-IDF FreeRTOS
|
||||||
shared resource without disabling the other core. The other core will only be
|
implementation of critical sections allows a core to have protected access to a shared
|
||||||
affected if it tries to concurrently access the same resource.
|
resource without disabling the other core. The other core will only be affected if it
|
||||||
|
tries to concurrently access the same resource.
|
||||||
|
|
||||||
The ESP-IDF FreeRTOS critical section functions have been modified as follows…
|
The ESP-IDF FreeRTOS critical section functions have been modified as follows…
|
||||||
|
|
||||||
- ``taskENTER_CRITICAL(mux)``, ``taskENTER_CRITICAL_ISR(mux)``,
|
- ``taskENTER_CRITICAL(mux)``, ``taskENTER_CRITICAL_ISR(mux)``,
|
||||||
``portENTER_CRITICAL(mux)``, ``portENTER_CRITICAL_ISR(mux)`` are all macro
|
``portENTER_CRITICAL(mux)``, ``portENTER_CRITICAL_ISR(mux)`` are all macro
|
||||||
defined to call :cpp:func:`vTaskEnterCritical`
|
defined to call internal function :cpp:func:`vPortEnterCritical`
|
||||||
|
|
||||||
- ``taskEXIT_CRITICAL(mux)``, ``taskEXIT_CRITICAL_ISR(mux)``,
|
- ``taskEXIT_CRITICAL(mux)``, ``taskEXIT_CRITICAL_ISR(mux)``,
|
||||||
``portEXIT_CRITICAL(mux)``, ``portEXIT_CRITICAL_ISR(mux)`` are all macro
|
``portEXIT_CRITICAL(mux)``, ``portEXIT_CRITICAL_ISR(mux)`` are all macro
|
||||||
defined to call :cpp:func:`vTaskExitCritical`
|
defined to call internal function :cpp:func:`vPortExitCritical`
|
||||||
|
|
||||||
- ``portENTER_CRITICAL_SAFE(mux)``, ``portEXIT_CRITICAL_SAFE(mux)`` macro identifies
|
- ``portENTER_CRITICAL_SAFE(mux)``, ``portEXIT_CRITICAL_SAFE(mux)`` macro identifies
|
||||||
the context of execution, i.e ISR or Non-ISR, and calls appropriate critical
|
the context of execution, i.e ISR or Non-ISR, and calls appropriate critical
|
||||||
section functions (``port*_CRITICAL`` in Non-ISR and ``port*_CRITICAL_ISR`` in ISR)
|
section functions (``port*_CRITICAL`` in Non-ISR and ``port*_CRITICAL_ISR`` in ISR)
|
||||||
in order to be in compliance with Vanilla FreeRTOS.
|
in order to be in compliance with Vanilla FreeRTOS.
|
||||||
|
|
||||||
For more details see :component_file:`esp_hw_support/include/soc/spinlock.h`
|
For more details see :component_file:`esp_hw_support/include/soc/spinlock.h`,
|
||||||
|
:component_file:`freertos/include/freertos/task.h`,
|
||||||
and :component_file:`freertos/tasks.c`
|
and :component_file:`freertos/tasks.c`
|
||||||
|
|
||||||
It should be noted that when modifying vanilla FreeRTOS code to be ESP-IDF
|
It should be noted that when modifying vanilla FreeRTOS code to be ESP-IDF
|
||||||
FreeRTOS compatible, it is trivial to modify the type of critical section
|
FreeRTOS compatible, it is trivial to modify the type of critical section called
|
||||||
called as they are all defined to call the same function. As long as the same
|
as they are all defined to call the same function. As long as the same spinlock
|
||||||
spinlock is provided upon entering and exiting, the type of call should not
|
is provided upon entering and exiting, the exact macro or function used for the
|
||||||
matter.
|
call should not matter.
|
||||||
|
|
||||||
|
|
||||||
.. only:: not CONFIG_FREERTOS_UNICORE
|
.. only:: not CONFIG_FREERTOS_UNICORE
|
||||||
|
Reference in New Issue
Block a user