Ewout van Bekkum | 660ebba | 2020-11-11 13:40:10 -0800 | [diff] [blame] | 1 | .. _module-pw_sync_freertos: |
| 2 | |
Ewout van Bekkum | 258171a | 2021-11-01 12:46:03 -0700 | [diff] [blame] | 3 | ================ |
Ewout van Bekkum | 660ebba | 2020-11-11 13:40:10 -0800 | [diff] [blame] | 4 | pw_sync_freertos |
Ewout van Bekkum | 258171a | 2021-11-01 12:46:03 -0700 | [diff] [blame] | 5 | ================ |
| 6 | This is a set of backends for pw_sync based on FreeRTOS. |
| 7 | |
| 8 | -------------------------------- |
| 9 | Critical Section Lock Primitives |
| 10 | -------------------------------- |
| 11 | |
| 12 | Mutex & TimedMutex |
| 13 | ================== |
| 14 | The FreeRTOS backend for the Mutex and TimedMutex use ``StaticSemaphore_t`` as |
| 15 | the underlying type. It is created using ``xSemaphoreCreateMutexStatic`` as part |
| 16 | of the constructors and cleaned up using ``vSemaphoreDelete`` in the |
| 17 | destructors. |
| 18 | |
| 19 | .. Note:: |
| 20 | Static allocation support is required in your FreeRTOS configuration, i.e. |
| 21 | ``configSUPPORT_STATIC_ALLOCATION == 1``. |
| 22 | |
| 23 | InterruptSpinLock |
| 24 | ================= |
| 25 | The 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 |
| 27 | detect accidental recursive locking. |
| 28 | |
| 29 | This 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 | -------------------- |
| 34 | Signaling Primitives |
| 35 | -------------------- |
| 36 | |
| 37 | ThreadNotification & TimedThreadNotification |
| 38 | ============================================ |
| 39 | An optimized FreeRTOS backend for the ThreadNotification and |
| 40 | TimedThreadNotification is provided using Task Notifications. It is backed by a |
| 41 | ``TaskHandle_t`` and a ``bool`` which permits these objects to track the |
| 42 | notification value outside of the task's TCB (AKA FreeRTOS Task Notification |
| 43 | State 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 | |
| 77 | This backend is compatible with sharing the notification index |
| 78 | with native FreeRTOS |
| 79 | `Stream and Message Buffers <https://www.freertos.org/RTOS-task-notifications.html>`_ |
| 80 | at index 0. |
| 81 | |
| 82 | Just like FreeRTOS Stream and Message Buffers, this backend uses the task |
| 83 | notification index only within callsites where the task must block until a |
| 84 | notification is received or a timeout occurs. The notification index's state is |
| 85 | always cleaned up before returning. The notification index is never used when |
| 86 | the 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 | |
| 92 | Design Notes |
| 93 | ------------ |
| 94 | You may ask, why are Task Notifications used at all given the risk associated |
| 95 | with global notification index allocations? It turns out there's no other |
| 96 | lightweight mechanism to unblock a task in FreeRTOS. |
| 97 | |
| 98 | Task suspension (i.e. ``vTaskSuspend``, ``vTaskResume``, & |
| 99 | ``vTaskResumeFromISR``) seems like a good fit, however ``xTaskResumeAll`` does |
| 100 | not participate in reference counting and will wake up all suspended tasks |
| 101 | whether you want it to or not. |
| 102 | |
| 103 | Lastly, there's also ``xTaskAbortDelay`` but there is no interrupt safe |
| 104 | equivalent of this API. Note that it uses ``vTaskSuspendAll`` internally for |
| 105 | the critical section which is not interrupt safe. If in the future an interrupt |
| 106 | safe version of this API is offerred, then this would be a great alternative! |
| 107 | |
| 108 | Lastly, we want to briefly explain how Task Notifications actually work in |
| 109 | FreeRTOS to show why you cannot directly share notification indeces even if the |
| 110 | bits used in the ``ulNotifiedValue`` are unique. This is a very common source of |
| 111 | bugs when using FreeRTOS and partially why Pigweed does not recommend using the |
| 112 | native Task Notification APIs directly. |
| 113 | |
| 114 | FreeRTOS Task Notifications use a task's TCB's ``ucNotifyState`` to capture the |
| 115 | notification state even when the task is not blocked. This state transitions |
| 116 | ``taskNOT_WAITING_NOTIFICATION`` to ``task_NOTIFICATION_RECEIVED`` if the task |
| 117 | ever notified. This notification state is used to determine whether the next |
| 118 | task notification wait call should block, irrespective of the notification |
| 119 | value. |
| 120 | |
| 121 | In order to enable this optimized backend, native task notifications are only |
| 122 | used when the task needs to block. If a timeout occurs the task unregisters for |
| 123 | notifications and clears the notification state before returning. This exact |
| 124 | mechanism is used by FreeRTOS internally for their Stream and Message Buffer |
| 125 | implementations. |
| 126 | |
| 127 | BinarySemaphore |
| 128 | =============== |
| 129 | The FreeRTOS backend for the BinarySemaphore uses ``StaticSemaphore_t`` as the |
| 130 | underlying type. It is created using ``xSemaphoreCreateBinaryStatic`` as part |
| 131 | of 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 | |
| 137 | CountingSemaphore |
| 138 | ================= |
| 139 | The FreeRTOS backend for the CountingSemaphore uses ``StaticSemaphore_t`` as the |
| 140 | underlying type. It is created using ``xSemaphoreCreateCountingStatic`` as part |
| 141 | of 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 | |
Ewout van Bekkum | 660ebba | 2020-11-11 13:40:10 -0800 | [diff] [blame] | 150 | |