Open FFBoard
Open source force feedback firmware
osal_freertos.h
Go to the documentation of this file.
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2019 Ha Thach (tinyusb.org)
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 * This file is part of the TinyUSB stack.
25 */
26
27#ifndef TUSB_OSAL_FREERTOS_H_
28#define TUSB_OSAL_FREERTOS_H_
29
30// FreeRTOS Headers
31#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,FreeRTOS.h)
32#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,semphr.h)
33#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,queue.h)
34#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,task.h)
35
36#ifdef __cplusplus
37extern "C" {
38#endif
39
40//--------------------------------------------------------------------+
41// MACRO CONSTANT TYPEDEF PROTYPES
42//--------------------------------------------------------------------+
43
44#if configSUPPORT_STATIC_ALLOCATION
45 typedef StaticSemaphore_t osal_semaphore_def_t;
46 typedef StaticSemaphore_t osal_mutex_def_t;
47#else
48 // not used therefore defined to smallest possible type to save space
49 typedef uint8_t osal_semaphore_def_t;
50 typedef uint8_t osal_mutex_def_t;
51#endif
52
53typedef SemaphoreHandle_t osal_semaphore_t;
54typedef SemaphoreHandle_t osal_mutex_t;
55typedef QueueHandle_t osal_queue_t;
56
57typedef struct
58{
59 uint16_t depth;
60 uint16_t item_sz;
61 void* buf;
62
63#if defined(configQUEUE_REGISTRY_SIZE) && (configQUEUE_REGISTRY_SIZE>0)
64 char const* name;
65#endif
66
67#if configSUPPORT_STATIC_ALLOCATION
68 StaticQueue_t sq;
69#endif
71
72#if defined(configQUEUE_REGISTRY_SIZE) && (configQUEUE_REGISTRY_SIZE>0)
73 #define _OSAL_Q_NAME(_name) .name = #_name
74#else
75 #define _OSAL_Q_NAME(_name)
76#endif
77
78// _int_set is not used with an RTOS
79#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \
80 static _type _name##_##buf[_depth];\
81 osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf, _OSAL_Q_NAME(_name) }
82
83//--------------------------------------------------------------------+
84// TASK API
85//--------------------------------------------------------------------+
86
87TU_ATTR_ALWAYS_INLINE static inline uint32_t _osal_ms2tick(uint32_t msec) {
88 if ( msec == OSAL_TIMEOUT_WAIT_FOREVER ) return portMAX_DELAY;
89 if ( msec == 0 ) return 0;
90
91 uint32_t ticks = pdMS_TO_TICKS(msec);
92
93 // configTICK_RATE_HZ is less than 1000 and 1 tick > 1 ms
94 // we still need to delay at least 1 tick
95 if ( ticks == 0 ) ticks = 1;
96
97 return ticks;
98}
99
100TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) {
101 vTaskDelay(pdMS_TO_TICKS(msec));
102}
103
104//--------------------------------------------------------------------+
105// Semaphore API
106//--------------------------------------------------------------------+
107
108TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t *semdef) {
109#if configSUPPORT_STATIC_ALLOCATION
110 return xSemaphoreCreateBinaryStatic(semdef);
111#else
112 (void) semdef;
113 return xSemaphoreCreateBinary();
114#endif
115}
116
117TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) {
118 vSemaphoreDelete(semd_hdl);
119 return true;
120}
121
122TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) {
123 if ( !in_isr ) {
124 return xSemaphoreGive(sem_hdl) != 0;
125 } else {
126 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
127 BaseType_t res = xSemaphoreGiveFromISR(sem_hdl, &xHigherPriorityTaskWoken);
128
129#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3
130 // not needed after https://github.com/espressif/esp-idf/commit/c5fd79547ac9b7bae06fa660e9f814d18d3390b7
131 if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR();
132#else
133 portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
134#endif
135
136 return res != 0;
137 }
138}
139
140TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) {
141 return xSemaphoreTake(sem_hdl, _osal_ms2tick(msec));
142}
143
144TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) {
145 xQueueReset(sem_hdl);
146}
147
148//--------------------------------------------------------------------+
149// MUTEX API (priority inheritance)
150//--------------------------------------------------------------------+
151
152TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) {
153#if configSUPPORT_STATIC_ALLOCATION
154 return xSemaphoreCreateMutexStatic(mdef);
155#else
156 (void) mdef;
157 return xSemaphoreCreateMutex();
158#endif
159}
160
161TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) {
162 vSemaphoreDelete(mutex_hdl);
163 return true;
164}
165
166TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) {
167 return osal_semaphore_wait(mutex_hdl, msec);
168}
169
170TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) {
171 return xSemaphoreGive(mutex_hdl);
172}
173
174//--------------------------------------------------------------------+
175// QUEUE API
176//--------------------------------------------------------------------+
177
178TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) {
179 osal_queue_t q;
180
181#if configSUPPORT_STATIC_ALLOCATION
182 q = xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq);
183#else
184 q = xQueueCreate(qdef->depth, qdef->item_sz);
185#endif
186
187#if defined(configQUEUE_REGISTRY_SIZE) && (configQUEUE_REGISTRY_SIZE>0)
188 vQueueAddToRegistry(q, qdef->name);
189#endif
190
191 return q;
192}
193
194TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) {
195 vQueueDelete(qhdl);
196 return true;
197}
198
199TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) {
200 return xQueueReceive(qhdl, data, _osal_ms2tick(msec));
201}
202
203TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const *data, bool in_isr) {
204 if ( !in_isr ) {
205 return xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER) != 0;
206 } else {
207 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
208 BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &xHigherPriorityTaskWoken);
209
210#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3
211 // not needed after https://github.com/espressif/esp-idf/commit/c5fd79547ac9b7bae06fa660e9f814d18d3390b7 (IDF v5)
212 if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR();
213#else
214 portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
215#endif
216
217 return res != 0;
218 }
219}
220
221TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) {
222 return uxQueueMessagesWaiting(qhdl) == 0;
223}
224
225#ifdef __cplusplus
226}
227#endif
228
229#endif
static struct @612 data
static bool in_isr
StaticSemaphore_t osal_semaphore_def_t
Definition: osal_freertos.h:45
static TU_ATTR_ALWAYS_INLINE bool osal_queue_empty(osal_queue_t qhdl)
static TU_ATTR_ALWAYS_INLINE bool osal_semaphore_delete(osal_semaphore_t semd_hdl)
static TU_ATTR_ALWAYS_INLINE bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec)
static TU_ATTR_ALWAYS_INLINE osal_queue_t osal_queue_create(osal_queue_def_t *qdef)
StaticSemaphore_t osal_mutex_def_t
Definition: osal_freertos.h:46
QueueHandle_t osal_queue_t
Definition: osal_freertos.h:55
static TU_ATTR_ALWAYS_INLINE bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec)
static TU_ATTR_ALWAYS_INLINE void osal_task_delay(uint32_t msec)
static TU_ATTR_ALWAYS_INLINE bool osal_queue_send(osal_queue_t qhdl, void const *data, bool in_isr)
SemaphoreHandle_t osal_semaphore_t
Definition: osal_freertos.h:53
static TU_ATTR_ALWAYS_INLINE bool osal_mutex_unlock(osal_mutex_t mutex_hdl)
static TU_ATTR_ALWAYS_INLINE bool osal_mutex_delete(osal_mutex_t mutex_hdl)
static TU_ATTR_ALWAYS_INLINE bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr)
static TU_ATTR_ALWAYS_INLINE bool osal_queue_receive(osal_queue_t qhdl, void *data, uint32_t msec)
static TU_ATTR_ALWAYS_INLINE bool osal_queue_delete(osal_queue_t qhdl)
static TU_ATTR_ALWAYS_INLINE void osal_semaphore_reset(osal_semaphore_t const sem_hdl)
SemaphoreHandle_t osal_mutex_t
Definition: osal_freertos.h:54
static TU_ATTR_ALWAYS_INLINE osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t *semdef)
static TU_ATTR_ALWAYS_INLINE uint32_t _osal_ms2tick(uint32_t msec)
Definition: osal_freertos.h:87
static TU_ATTR_ALWAYS_INLINE osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef)
char const * name
Definition: osal_freertos.h:64
StaticQueue_t sq
Definition: osal_freertos.h:68