1 /**************************************************************************/ /**
2 * @file
3 * @brief OS abstraction layer primitives for platform/security on CMSIS RTOS2
4 *******************************************************************************
5 * # License
6 * <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
7 *******************************************************************************
8 *
9 * SPDX-License-Identifier: Zlib
10 *
11 * The licensor of this software is Silicon Laboratories Inc.
12 *
13 * This software is provided 'as-is', without any express or implied
14 * warranty. In no event will the authors be held liable for any damages
15 * arising from the use of this software.
16 *
17 * Permission is granted to anyone to use this software for any purpose,
18 * including commercial applications, and to alter it and redistribute it
19 * freely, subject to the following restrictions:
20 *
21 * 1. The origin of this software must not be misrepresented; you must not
22 * claim that you wrote the original software. If you use this software
23 * in a product, an acknowledgment in the product documentation would be
24 * appreciated but is not required.
25 * 2. Altered source versions must be plainly marked as such, and must not be
26 * misrepresented as being the original software.
27 * 3. This notice may not be removed or altered from any source distribution.
28 *
29 ******************************************************************************/
30
31 #ifndef SLI_PSEC_OSAL_CMSIS_RTOS_H
32 #define SLI_PSEC_OSAL_CMSIS_RTOS_H
33
34 // -----------------------------------------------------------------------------
35 // Includes
36 #include "sl_common.h"
37 #include "sl_status.h"
38 #include "cmsis_os2.h"
39 #include "sl_core.h"
40 #include "sl_code_classification.h"
41
42 #if defined (SL_COMPONENT_CATALOG_PRESENT)
43 #include "sl_component_catalog.h"
44 #endif
45
46 #if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)
47 #include "FreeRTOSConfig.h"
48 #if (configSUPPORT_STATIC_ALLOCATION == 1)
49 #include "FreeRTOS.h" // StaticSemaphore_t
50 #include <string.h>
51 #endif
52 #endif
53
54 #ifdef __cplusplus
55 extern "C" {
56 #endif
57
58 // -----------------------------------------------------------------------------
59 // Defines
60
61 /// In order to wait forever in blocking functions the user can pass the
62 /// following value.
63 #define SLI_PSEC_OSAL_WAIT_FOREVER (osWaitForever)
64 /// In order to return immediately in blocking functions the user can pass the
65 /// following value.
66 #define SLI_PSEC_OSAL_NON_BLOCKING (0)
67
68 // Checks if kernel is running
69 #define SLI_PSEC_OSAL_KERNEL_RUNNING (osKernelGetState() == osKernelRunning)
70
71 // Lock kernel (task scheduler) to enter critical section
72 #define SLI_PSEC_OSAL_KERNEL_CRITICAL_SECTION_START \
73 int32_t kernel_lock_state = 0; \
74 osKernelState_t kernel_state = osKernelGetState(); \
75 if (kernel_state != osKernelInactive && kernel_state != osKernelReady) { \
76 kernel_lock_state = osKernelLock(); \
77 if (kernel_lock_state < 0) { \
78 return SL_STATUS_FAIL; \
79 } \
80 }
81
82 // Resume kernel to exit critical section
83 #define SLI_PSEC_OSAL_KERNEL_CRITICAL_SECTION_END \
84 if (kernel_state != osKernelInactive && kernel_state != osKernelReady) { \
85 if (osKernelRestoreLock(kernel_lock_state) < 0) { \
86 return SL_STATUS_FAIL; \
87 } \
88 }
89
90 // -----------------------------------------------------------------------------
91 // Typedefs
92
93 /// Completion object used to wait for and signal end of an operation.
94 typedef struct sli_psec_osal_completion {
95 #if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT) && (configSUPPORT_STATIC_ALLOCATION == 1)
96 osSemaphoreAttr_t semaphore_attr;
97 StaticSemaphore_t static_sem_object;
98 #endif
99 osSemaphoreId_t semaphore_ID;
100 } sli_psec_osal_completion_t;
101
102 /// SLI PSEC lock definition for CMSIS RTOS2.
103 typedef struct sli_psec_osal_lock {
104 #if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT) && (configSUPPORT_STATIC_ALLOCATION == 1)
105 StaticSemaphore_t static_sem_object;
106 #endif
107 osMutexAttr_t mutex_attr;
108 osMutexId_t mutex_ID;
109 } sli_psec_osal_lock_t;
110
111 // -----------------------------------------------------------------------------
112 // Functions
113
114 /***************************************************************************//**
115 * @brief Set recursive attribute of lock
116 *
117 * @details If recursive lock is needed, this function must be called
118 * before calling sli_psec_osal_init_lock.
119 *
120 * @param lock Pointer to the lock
121 *
122 * @return SL_STATUS_OK on success, error code otherwise.
123 *****************************************************************************/
124 __STATIC_INLINE
sli_psec_osal_set_recursive_lock(sli_psec_osal_lock_t * lock)125 sl_status_t sli_psec_osal_set_recursive_lock(sli_psec_osal_lock_t *lock)
126 {
127 if (lock == NULL) {
128 return SL_STATUS_INVALID_PARAMETER;
129 }
130 lock->mutex_attr.attr_bits |= osMutexRecursive;
131 return SL_STATUS_OK;
132 }
133
134 /***************************************************************************//**
135 * @brief Initialize a given lock
136 *
137 * @param lock Pointer to the lock needing initialization
138 *
139 * @return SL_STATUS_OK on success, error code otherwise.
140 *****************************************************************************/
sli_psec_osal_init_lock(sli_psec_osal_lock_t * lock)141 __STATIC_INLINE sl_status_t sli_psec_osal_init_lock(sli_psec_osal_lock_t *lock)
142 {
143 if (lock == NULL) {
144 return SL_STATUS_FAIL;
145 }
146
147 #if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT) && (configSUPPORT_STATIC_ALLOCATION == 1)
148 // Zeroize all members of the lock attributes object and setup the static control block.
149 lock->mutex_attr.cb_mem = &lock->static_sem_object;
150 lock->mutex_attr.cb_size = sizeof(lock->static_sem_object);
151 #endif
152
153 lock->mutex_ID = osMutexNew(&lock->mutex_attr);
154
155 return (lock->mutex_ID == NULL ? SL_STATUS_FAIL : SL_STATUS_OK);
156 }
157
158 /***************************************************************************//**
159 * @brief Free a given lock
160 *
161 * @param lock Pointer to the lock being freed
162 *
163 * @return SL_STATUS_OK on success, error code otherwise.
164 *****************************************************************************/
sli_psec_osal_free_lock(sli_psec_osal_lock_t * lock)165 __STATIC_INLINE sl_status_t sli_psec_osal_free_lock(sli_psec_osal_lock_t *lock)
166 {
167 if (lock == NULL) {
168 return SL_STATUS_FAIL;
169 }
170
171 osStatus_t status = osMutexDelete(lock->mutex_ID);
172 return (status == osOK ? SL_STATUS_OK : SL_STATUS_FAIL);
173 }
174
175 /***************************************************************************//**
176 * @brief Pend on a lock with timeout
177 *
178 * @param lock Pointer to the lock being pended on
179 *
180 * @return SL_STATUS_OK on success, error code otherwise.
181 *****************************************************************************/
182 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_PSEC_OSAL, SL_CODE_CLASS_TIME_CRITICAL)
183 sl_status_t sli_psec_osal_take_lock_timeout(sli_psec_osal_lock_t *lock,
184 uint32_t timeout);
185
186 /***************************************************************************//**
187 * @brief Pend on a lock forever
188 *
189 * @param lock Pointer to the lock being pended on
190 *
191 * @return SL_STATUS_OK on success, error code otherwise.
192 *****************************************************************************/
sli_psec_osal_take_lock(sli_psec_osal_lock_t * lock)193 __STATIC_INLINE sl_status_t sli_psec_osal_take_lock(sli_psec_osal_lock_t *lock)
194 {
195 return sli_psec_osal_take_lock_timeout(lock, SLI_PSEC_OSAL_WAIT_FOREVER);
196 }
197
198 /***************************************************************************//**
199 * @brief Try to acquire ownership of a lock without waiting.
200 *
201 * @param lock Pointer to the lock being tested
202 *
203 * @return SL_STATUS_OK on success (= lock successfully owned),
204 * error code otherwise.
205 *****************************************************************************/
206 __STATIC_INLINE
sli_psec_osal_take_lock_non_blocking(sli_psec_osal_lock_t * lock)207 sl_status_t sli_psec_osal_take_lock_non_blocking(sli_psec_osal_lock_t *lock)
208 {
209 return sli_psec_osal_take_lock_timeout(lock, SLI_PSEC_OSAL_NON_BLOCKING);
210 }
211
212 /***************************************************************************//**
213 * @brief Release a lock
214 *
215 * @param lock Pointer to the lock being released
216 *
217 * @return SL_STATUS_OK on success, error code otherwise.
218 *****************************************************************************/
219 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_PSEC_OSAL, SL_CODE_CLASS_TIME_CRITICAL)
220 sl_status_t sli_psec_osal_give_lock(sli_psec_osal_lock_t *lock);
221
222 /***************************************************************************//**
223 * @brief Initialize a completion object.
224 *
225 * @param p_comp Pointer to an sli_psec_osal_completion_t object allocated
226 * by the user.
227 *
228 * @return Status code, @ref sl_status.h.
229 *****************************************************************************/
230 __STATIC_INLINE sl_status_t
sli_psec_osal_init_completion(sli_psec_osal_completion_t * p_comp)231 sli_psec_osal_init_completion(sli_psec_osal_completion_t *p_comp)
232 {
233 if (p_comp == NULL) {
234 return SL_STATUS_FAIL;
235 }
236
237 #if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT) && (configSUPPORT_STATIC_ALLOCATION == 1)
238 // Zeroize all members of the semaphore attributes object and setup the static control block.
239 memset(&p_comp->semaphore_attr, 0, sizeof(p_comp->semaphore_attr));
240 p_comp->semaphore_attr.cb_mem = &p_comp->static_sem_object;
241 p_comp->semaphore_attr.cb_size = sizeof(p_comp->static_sem_object);
242 p_comp->semaphore_ID = osSemaphoreNew(1u, 0u, &p_comp->semaphore_attr);
243 #else
244 p_comp->semaphore_ID = osSemaphoreNew(1u, 0u, NULL);
245 #endif
246
247 return (p_comp->semaphore_ID == NULL ? SL_STATUS_FAIL : SL_STATUS_OK);
248 }
249
250 /***************************************************************************//**
251 * @brief Free a completion object.
252 *
253 * @param p_comp Pointer to an sli_psec_osal_completion_t object.
254 *
255 * @return Status code, @ref sl_status.h.
256 *****************************************************************************/
257 __STATIC_INLINE sl_status_t
sli_psec_osal_free_completion(sli_psec_osal_completion_t * p_comp)258 sli_psec_osal_free_completion(sli_psec_osal_completion_t *p_comp)
259 {
260 if (p_comp == NULL) {
261 return SL_STATUS_FAIL;
262 }
263
264 osStatus_t status = osSemaphoreDelete(p_comp->semaphore_ID);
265 return (status == osOK ? SL_STATUS_OK : SL_STATUS_FAIL);
266 }
267
268 /***************************************************************************//**
269 * @brief Wait for completion event.
270 *
271 * @param p_comp Pointer to completion object which must be initialized by
272 * calling sli_psec_osal_completion_init before calling this
273 * function.
274 *
275 * @param ticks Ticks to wait for the completion.
276 * Pass a value of SLI_PSEC_OSAL_WAIT_FOREVER in order to
277 * wait forever.
278 * Pass a value of SLI_PSEC_OSAL_NON_BLOCKING in order to
279 * return immediately.
280 *
281 * @return Status code, @ref sl_status.h. Typcally SL_STATUS_OK if success,
282 * or SL_STATUS_TIMEOUT if no completion within the given ticks.
283 *****************************************************************************/
284 __STATIC_INLINE sl_status_t
sli_psec_osal_wait_completion(sli_psec_osal_completion_t * p_comp,int ticks)285 sli_psec_osal_wait_completion(sli_psec_osal_completion_t *p_comp, int ticks)
286 {
287 if (p_comp == NULL) {
288 return SL_STATUS_FAIL;
289 }
290
291 osStatus_t status = osOK;
292 if (osKernelGetState() == osKernelRunning) {
293 status = osSemaphoreAcquire(p_comp->semaphore_ID,
294 (uint32_t)ticks);
295 }
296 return (status == osOK ? SL_STATUS_OK : SL_STATUS_FAIL);
297 }
298
299 /***************************************************************************//**
300 * @brief Signal completion.
301 *
302 * @param p_comp Pointer to completion object which must be initialized by
303 * calling sli_psec_osal_completion_init before calling this
304 * function.
305 *
306 * @return Status code, @ref sl_status.h.
307 *****************************************************************************/
308 __STATIC_INLINE
sli_psec_osal_complete(sli_psec_osal_completion_t * p_comp)309 sl_status_t sli_psec_osal_complete(sli_psec_osal_completion_t* p_comp)
310 {
311 if (p_comp == NULL) {
312 return SL_STATUS_FAIL;
313 }
314
315 osStatus_t status = osOK;
316 osKernelState_t state = osKernelGetState();
317 if ((state == osKernelRunning) || (state == osKernelLocked)) {
318 status = osSemaphoreRelease(p_comp->semaphore_ID);
319 }
320 return (status == osOK ? SL_STATUS_OK : SL_STATUS_FAIL);
321 }
322
323 /***************************************************************************//**
324 * @brief Lock the RTOS Kernel scheduler.
325 *
326 * @return Status code, @ref cmsis_os2.h
327 *****************************************************************************/
sli_psec_osal_kernel_lock(void)328 __STATIC_INLINE int32_t sli_psec_osal_kernel_lock(void)
329 {
330 return osKernelLock();
331 }
332
333 /***************************************************************************//**
334 * @brief Restore the RTOS Kernel scheduler lock state.
335 *
336 * @return Status code, @ref cmsis_os2.h
337 *****************************************************************************/
sli_psec_osal_kernel_restore_lock(int32_t lock)338 __STATIC_INLINE int32_t sli_psec_osal_kernel_restore_lock(int32_t lock)
339 {
340 return osKernelRestoreLock(lock);
341 }
342
343 /***************************************************************************//**
344 * @brief Get current RTOS kernel state.
345 *
346 * @return Status code, @ref cmsis_os2.h
347 *****************************************************************************/
348 __STATIC_INLINE osKernelState_t
sli_psec_osal_kernel_get_state(void)349 sli_psec_osal_kernel_get_state(void)
350 {
351 return osKernelGetState();
352 }
353
354 #ifdef __cplusplus
355 }
356 #endif
357
358 #endif // SLI_PSEC_OSAL_CMSIS_RTOS_H
359