151 lines
6.4 KiB
ReStructuredText
151 lines
6.4 KiB
ReStructuredText
.. _module-pw_sync_freertos:
|
|
|
|
================
|
|
pw_sync_freertos
|
|
================
|
|
This is a set of backends for pw_sync based on FreeRTOS.
|
|
|
|
--------------------------------
|
|
Critical Section Lock Primitives
|
|
--------------------------------
|
|
|
|
Mutex & TimedMutex
|
|
==================
|
|
The FreeRTOS backend for the Mutex and TimedMutex use ``StaticSemaphore_t`` as
|
|
the underlying type. It is created using ``xSemaphoreCreateMutexStatic`` as part
|
|
of the constructors and cleaned up using ``vSemaphoreDelete`` in the
|
|
destructors.
|
|
|
|
.. Note::
|
|
Static allocation support is required in your FreeRTOS configuration, i.e.
|
|
``configSUPPORT_STATIC_ALLOCATION == 1``.
|
|
|
|
InterruptSpinLock
|
|
=================
|
|
The FreeRTOS backend for InterruptSpinLock is backed by ``UBaseType_t`` and a
|
|
``bool`` which permits these objects to stash the saved interrupt mask and to
|
|
detect accidental recursive locking.
|
|
|
|
This object uses ``taskENTER_CRITICAL_FROM_ISR`` and
|
|
``taskEXIT_CRITICAL_FROM_ISR`` from interrupt contexts and
|
|
``taskENTER_CRITICAL`` and ``taskEXIT_CRITICAL`` from other contexts.
|
|
|
|
--------------------
|
|
Signaling Primitives
|
|
--------------------
|
|
|
|
ThreadNotification & TimedThreadNotification
|
|
============================================
|
|
An optimized FreeRTOS backend for the ThreadNotification and
|
|
TimedThreadNotification is provided using Task Notifications. It is backed by a
|
|
``TaskHandle_t`` and a ``bool`` which permits these objects to track the
|
|
notification value outside of the task's TCB (AKA FreeRTOS Task Notification
|
|
State and Value).
|
|
|
|
.. Warning::
|
|
By default this backend uses the task notification at index 0, just like
|
|
FreeRTOS Stream and Message Buffers. If you want to maintain the state of a
|
|
task notification across blocking acquiring calls to ThreadNotifications, then
|
|
you must do one of the following:
|
|
|
|
1. Adjust ``PW_SYNC_FREERTOS_CONFIG_THREAD_NOTIFICATION_INDEX`` to an index
|
|
which does not collide with existing incompatible use.
|
|
2. Migrate your existing use of task notifications away from index 0.
|
|
3. Do not use this optimized backend and instead use the binary semaphore
|
|
backends for ThreadNotifications
|
|
(``pw_sync:binary_semaphore_thread_notification_backend``).
|
|
|
|
You are using any of the following Task Notification APIs, it means you are
|
|
using notification indices:
|
|
|
|
- ``xTaskNotify`` / ``xTaskNotifyIndexed``
|
|
- ``xTaskNotifyFromISR`` / ``xTaskNotifyIndexedFromISR``
|
|
- ``xTaskNotifyGive`` / ``xTaskNotifyGiveIndexed``
|
|
- ``xTaskNotifyGiveFromISR`` / ``xTaskNotifyGiveIndexedFromISR``
|
|
- ``xTaskNotifyAndQuery`` / ``xTaskNotifyAndQueryIndexed``
|
|
- ``xTaskNotifyAndQueryFromISR`` / ``xTaskNotifyAndQueryIndexedFromISR``
|
|
- ``ulTaskNotifyTake`` / ``ulTaskNotifyTakeIndexed``
|
|
- ``xTaskNotifyWait`` / ``xTaskNotifyWaitIndexed``
|
|
- ``xTaskNotifyStateClear`` / ``xTaskNotifyStateClearIndexed``
|
|
- ``ulTaskNotifyValueClear`` / ``ulTaskNotifyValueClearIndexed``
|
|
|
|
APIs without ``Indexed`` in the name use index 0 implicitly.
|
|
|
|
Prior to FreeRTOS V10.4.0 each task had a single "notification index", and all
|
|
task notification API functions operated on that implicit index of 0.
|
|
|
|
This backend is compatible with sharing the notification index
|
|
with native FreeRTOS
|
|
`Stream and Message Buffers <https://www.freertos.org/RTOS-task-notifications.html>`_
|
|
at index 0.
|
|
|
|
Just like FreeRTOS Stream and Message Buffers, this backend uses the task
|
|
notification index only within callsites where the task must block until a
|
|
notification is received or a timeout occurs. The notification index's state is
|
|
always cleaned up before returning. The notification index is never used when
|
|
the acquiring task is not going to block.
|
|
|
|
.. Note::
|
|
Task notification support is required in your FreeRTOS configuration, i.e.
|
|
``configUSE_TASK_NOTIFICATIONS == 1``.
|
|
|
|
Design Notes
|
|
------------
|
|
You may ask, why are Task Notifications used at all given the risk associated
|
|
with global notification index allocations? It turns out there's no other
|
|
lightweight mechanism to unblock a task in FreeRTOS.
|
|
|
|
Task suspension (i.e. ``vTaskSuspend``, ``vTaskResume``, &
|
|
``vTaskResumeFromISR``) seems like a good fit, however ``xTaskResumeAll`` does
|
|
not participate in reference counting and will wake up all suspended tasks
|
|
whether you want it to or not.
|
|
|
|
Lastly, there's also ``xTaskAbortDelay`` but there is no interrupt safe
|
|
equivalent of this API. Note that it uses ``vTaskSuspendAll`` internally for
|
|
the critical section which is not interrupt safe. If in the future an interrupt
|
|
safe version of this API is offerred, then this would be a great alternative!
|
|
|
|
Lastly, we want to briefly explain how Task Notifications actually work in
|
|
FreeRTOS to show why you cannot directly share notification indeces even if the
|
|
bits used in the ``ulNotifiedValue`` are unique. This is a very common source of
|
|
bugs when using FreeRTOS and partially why Pigweed does not recommend using the
|
|
native Task Notification APIs directly.
|
|
|
|
FreeRTOS Task Notifications use a task's TCB's ``ucNotifyState`` to capture the
|
|
notification state even when the task is not blocked. This state transitions
|
|
``taskNOT_WAITING_NOTIFICATION`` to ``task_NOTIFICATION_RECEIVED`` if the task
|
|
ever notified. This notification state is used to determine whether the next
|
|
task notification wait call should block, irrespective of the notification
|
|
value.
|
|
|
|
In order to enable this optimized backend, native task notifications are only
|
|
used when the task needs to block. If a timeout occurs the task unregisters for
|
|
notifications and clears the notification state before returning. This exact
|
|
mechanism is used by FreeRTOS internally for their Stream and Message Buffer
|
|
implementations.
|
|
|
|
BinarySemaphore
|
|
===============
|
|
The FreeRTOS backend for the BinarySemaphore uses ``StaticSemaphore_t`` as the
|
|
underlying type. It is created using ``xSemaphoreCreateBinaryStatic`` as part
|
|
of the constructor and cleaned up using ``vSemaphoreDelete`` in the destructor.
|
|
|
|
.. Note::
|
|
Static allocation support is required in your FreeRTOS configuration, i.e.
|
|
``configSUPPORT_STATIC_ALLOCATION == 1``.
|
|
|
|
CountingSemaphore
|
|
=================
|
|
The FreeRTOS backend for the CountingSemaphore uses ``StaticSemaphore_t`` as the
|
|
underlying type. It is created using ``xSemaphoreCreateCountingStatic`` as part
|
|
of the constructor and cleaned up using ``vSemaphoreDelete`` in the destructor.
|
|
|
|
.. Note::
|
|
Counting semaphore support is required in your FreeRTOS configuration, i.e.
|
|
``configUSE_COUNTING_SEMAPHORES == 1``.
|
|
.. Note::
|
|
Static allocation support is required in your FreeRTOS configuration, i.e.
|
|
``configSUPPORT_STATIC_ALLOCATION == 1``.
|
|
|
|
|