1.. _module-pw_sync_freertos: 2 3================ 4pw_sync_freertos 5================ 6This is a set of backends for pw_sync based on FreeRTOS. 7 8-------------------------------- 9Critical Section Lock Primitives 10-------------------------------- 11 12Mutex & TimedMutex 13================== 14The FreeRTOS backend for the Mutex and TimedMutex use ``StaticSemaphore_t`` as 15the underlying type. It is created using ``xSemaphoreCreateMutexStatic`` as part 16of the constructors and cleaned up using ``vSemaphoreDelete`` in the 17destructors. 18 19.. Note:: 20 Static allocation support is required in your FreeRTOS configuration, i.e. 21 ``configSUPPORT_STATIC_ALLOCATION == 1``. 22 23InterruptSpinLock 24================= 25The FreeRTOS backend for InterruptSpinLock is backed by ``UBaseType_t`` and a 26``bool`` which permits these objects to stash the saved interrupt mask and to 27detect accidental recursive locking. 28 29This object uses ``taskENTER_CRITICAL_FROM_ISR`` and 30``taskEXIT_CRITICAL_FROM_ISR`` from interrupt contexts and 31``taskENTER_CRITICAL`` and ``taskEXIT_CRITICAL`` from other contexts. 32 33-------------------- 34Signaling Primitives 35-------------------- 36 37ThreadNotification & TimedThreadNotification 38============================================ 39An optimized FreeRTOS backend for the ThreadNotification and 40TimedThreadNotification is provided using Task Notifications. It is backed by a 41``TaskHandle_t`` and a ``bool`` which permits these objects to track the 42notification value outside of the task's TCB (AKA FreeRTOS Task Notification 43State and Value). 44 45.. Warning:: 46 By default this backend uses the task notification at index 0, just like 47 FreeRTOS Stream and Message Buffers. If you want to maintain the state of a 48 task notification across blocking acquiring calls to ThreadNotifications, then 49 you must do one of the following: 50 51 1. Adjust ``PW_SYNC_FREERTOS_CONFIG_THREAD_NOTIFICATION_INDEX`` to an index 52 which does not collide with existing incompatible use. 53 2. Migrate your existing use of task notifications away from index 0. 54 3. Do not use this optimized backend and instead use the binary semaphore 55 backends for ThreadNotifications 56 (``pw_sync:binary_semaphore_thread_notification_backend``). 57 58 You are using any of the following Task Notification APIs, it means you are 59 using notification indices: 60 61 - ``xTaskNotify`` / ``xTaskNotifyIndexed`` 62 - ``xTaskNotifyFromISR`` / ``xTaskNotifyIndexedFromISR`` 63 - ``xTaskNotifyGive`` / ``xTaskNotifyGiveIndexed`` 64 - ``xTaskNotifyGiveFromISR`` / ``xTaskNotifyGiveIndexedFromISR`` 65 - ``xTaskNotifyAndQuery`` / ``xTaskNotifyAndQueryIndexed`` 66 - ``xTaskNotifyAndQueryFromISR`` / ``xTaskNotifyAndQueryIndexedFromISR`` 67 - ``ulTaskNotifyTake`` / ``ulTaskNotifyTakeIndexed`` 68 - ``xTaskNotifyWait`` / ``xTaskNotifyWaitIndexed`` 69 - ``xTaskNotifyStateClear`` / ``xTaskNotifyStateClearIndexed`` 70 - ``ulTaskNotifyValueClear`` / ``ulTaskNotifyValueClearIndexed`` 71 72 APIs without ``Indexed`` in the name use index 0 implicitly. 73 74 Prior to FreeRTOS V10.4.0 each task had a single "notification index", and all 75 task notification API functions operated on that implicit index of 0. 76 77This backend is compatible with sharing the notification index 78with native FreeRTOS 79`Stream and Message Buffers <https://www.freertos.org/RTOS-task-notifications.html>`_ 80at index 0. 81 82Just like FreeRTOS Stream and Message Buffers, this backend uses the task 83notification index only within callsites where the task must block until a 84notification is received or a timeout occurs. The notification index's state is 85always cleaned up before returning. The notification index is never used when 86the acquiring task is not going to block. 87 88.. Note:: 89 Task notification support is required in your FreeRTOS configuration, i.e. 90 ``configUSE_TASK_NOTIFICATIONS == 1``. 91 92Design Notes 93------------ 94You may ask, why are Task Notifications used at all given the risk associated 95with global notification index allocations? It turns out there's no other 96lightweight mechanism to unblock a task in FreeRTOS. 97 98Task suspension (i.e. ``vTaskSuspend``, ``vTaskResume``, & 99``vTaskResumeFromISR``) seems like a good fit, however ``xTaskResumeAll`` does 100not participate in reference counting and will wake up all suspended tasks 101whether you want it to or not. 102 103Lastly, there's also ``xTaskAbortDelay`` but there is no interrupt safe 104equivalent of this API. Note that it uses ``vTaskSuspendAll`` internally for 105the critical section which is not interrupt safe. If in the future an interrupt 106safe version of this API is offerred, then this would be a great alternative! 107 108Lastly, we want to briefly explain how Task Notifications actually work in 109FreeRTOS to show why you cannot directly share notification indeces even if the 110bits used in the ``ulNotifiedValue`` are unique. This is a very common source of 111bugs when using FreeRTOS and partially why Pigweed does not recommend using the 112native Task Notification APIs directly. 113 114FreeRTOS Task Notifications use a task's TCB's ``ucNotifyState`` to capture the 115notification state even when the task is not blocked. This state transitions 116``taskNOT_WAITING_NOTIFICATION`` to ``task_NOTIFICATION_RECEIVED`` if the task 117ever notified. This notification state is used to determine whether the next 118task notification wait call should block, irrespective of the notification 119value. 120 121In order to enable this optimized backend, native task notifications are only 122used when the task needs to block. If a timeout occurs the task unregisters for 123notifications and clears the notification state before returning. This exact 124mechanism is used by FreeRTOS internally for their Stream and Message Buffer 125implementations. 126 127BinarySemaphore 128=============== 129The FreeRTOS backend for the BinarySemaphore uses ``StaticSemaphore_t`` as the 130underlying type. It is created using ``xSemaphoreCreateBinaryStatic`` as part 131of the constructor and cleaned up using ``vSemaphoreDelete`` in the destructor. 132 133.. Note:: 134 Static allocation support is required in your FreeRTOS configuration, i.e. 135 ``configSUPPORT_STATIC_ALLOCATION == 1``. 136 137CountingSemaphore 138================= 139The FreeRTOS backend for the CountingSemaphore uses ``StaticSemaphore_t`` as the 140underlying type. It is created using ``xSemaphoreCreateCountingStatic`` as part 141of the constructor and cleaned up using ``vSemaphoreDelete`` in the destructor. 142 143.. Note:: 144 Counting semaphore support is required in your FreeRTOS configuration, i.e. 145 ``configUSE_COUNTING_SEMAPHORES == 1``. 146.. Note:: 147 Static allocation support is required in your FreeRTOS configuration, i.e. 148 ``configSUPPORT_STATIC_ALLOCATION == 1``. 149 150 151