mikroSDK Reference Manual
osal_freertos.h
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_post(osal_semaphore_t sem_hdl, bool in_isr) {
118 if ( !in_isr ) {
119 return xSemaphoreGive(sem_hdl) != 0;
120 } else {
121 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
122 BaseType_t res = xSemaphoreGiveFromISR(sem_hdl, &xHigherPriorityTaskWoken);
123
124#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3
125 // not needed after https://github.com/espressif/esp-idf/commit/c5fd79547ac9b7bae06fa660e9f814d18d3390b7
126 if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR();
127#else
128 portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
129#endif
130
131 return res != 0;
132 }
133}
134
135TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) {
136 return xSemaphoreTake(sem_hdl, _osal_ms2tick(msec));
137}
138
139TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) {
140 xQueueReset(sem_hdl);
141}
142
143//--------------------------------------------------------------------+
144// MUTEX API (priority inheritance)
145//--------------------------------------------------------------------+
146
147TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) {
148#if configSUPPORT_STATIC_ALLOCATION
149 return xSemaphoreCreateMutexStatic(mdef);
150#else
151 (void) mdef;
152 return xSemaphoreCreateMutex();
153#endif
154}
155
156TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) {
157 return osal_semaphore_wait(mutex_hdl, msec);
158}
159
160TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) {
161 return xSemaphoreGive(mutex_hdl);
162}
163
164//--------------------------------------------------------------------+
165// QUEUE API
166//--------------------------------------------------------------------+
167
168TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) {
169 osal_queue_t q;
170
171#if configSUPPORT_STATIC_ALLOCATION
172 q = xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq);
173#else
174 q = xQueueCreate(qdef->depth, qdef->item_sz);
175#endif
176
177#if defined(configQUEUE_REGISTRY_SIZE) && (configQUEUE_REGISTRY_SIZE>0)
178 vQueueAddToRegistry(q, qdef->name);
179#endif
180
181 return q;
182}
183
184TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) {
185 return xQueueReceive(qhdl, data, _osal_ms2tick(msec));
186}
187
188TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const *data, bool in_isr) {
189 if ( !in_isr ) {
190 return xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER) != 0;
191 } else {
192 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
193 BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &xHigherPriorityTaskWoken);
194
195#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3
196 // not needed after https://github.com/espressif/esp-idf/commit/c5fd79547ac9b7bae06fa660e9f814d18d3390b7 (IDF v5)
197 if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR();
198#else
199 portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
200#endif
201
202 return res != 0;
203 }
204}
205
206TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) {
207 return uxQueueMessagesWaiting(qhdl) == 0;
208}
209
210#ifdef __cplusplus
211}
212#endif
213
214#endif
Definition osal_freertos.h:58
Definition osal_none.h:47