1 /**************************************************************************/ /**
2  * @file
3  * @brief OS abstraction layer primitives for SE manager on CMSIS RTOS2
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2021 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 SE_MANAGER_OSAL_CMSIS_RTOS_H
32 #define SE_MANAGER_OSAL_CMSIS_RTOS_H
33 
34 #include "cmsis_os2.h"
35 
36 #if defined (SL_COMPONENT_CATALOG_PRESENT)
37   #include "sl_component_catalog.h"
38 #endif
39 
40 #if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)
41   #include "FreeRTOSConfig.h"
42   #if (configSUPPORT_STATIC_ALLOCATION == 1)
43     #include "FreeRTOS.h"  // StaticSemaphore_t
44     #include <string.h>
45   #endif
46 #else
47   #include "em_core.h"
48 #endif
49 
50 #ifdef __cplusplus
51 extern "C" {
52 #endif
53 
54 // -----------------------------------------------------------------------------
55 // Defines
56 
57 /// In order to wait forever in blocking functions the user can pass the
58 /// following value.
59 #define SE_MANAGER_OSAL_WAIT_FOREVER  (osWaitForever)
60 /// In order to return immediately in blocking functions the user can pass the
61 /// following value.
62 #define SE_MANAGER_OSAL_NON_BLOCKING  (0)
63 
64 /// Priority to use for SEMBRX IRQ
65 #if defined(SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY)
66   #if (SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY >= (1U << __NVIC_PRIO_BITS) )
67       #error Illegal SEMBRX priority level.
68   #endif
69   #if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)
70     #if (SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY < (configMAX_SYSCALL_INTERRUPT_PRIORITY >> (8U - __NVIC_PRIO_BITS) ) )
71       #error Illegal SEMBRX priority level.
72     #endif
73   #else
74     #if (SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY < CORE_ATOMIC_BASE_PRIORITY_LEVEL)
75       #error Illegal SEMBRX priority level.
76     #endif
77   #endif
78   #define SE_MANAGER_SEMBRX_IRQ_PRIORITY SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY
79 #else
80   #if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)
81     #define SE_MANAGER_SEMBRX_IRQ_PRIORITY (configMAX_SYSCALL_INTERRUPT_PRIORITY >> (8U - __NVIC_PRIO_BITS) )
82   #else
83     #define SE_MANAGER_SEMBRX_IRQ_PRIORITY (CORE_ATOMIC_BASE_PRIORITY_LEVEL)
84   #endif
85 #endif
86 
87 /// Determine if executing at interrupt level on ARM Cortex-M.
88 #define RUNNING_AT_INTERRUPT_LEVEL (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk)
89 
90 // -----------------------------------------------------------------------------
91 // Typedefs
92 
93 /// Completion object used to wait for and signal end of an operation.
94 typedef struct se_manager_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 } se_manager_osal_completion_t;
101 
102 /// SE manager mutex definition for CMSIS RTOS2.
103 typedef struct se_manager_osal_mutex {
104 #if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT) && (configSUPPORT_STATIC_ALLOCATION == 1)
105   osMutexAttr_t mutex_attr;
106   StaticSemaphore_t static_sem_object;
107 #endif
108   osMutexId_t   mutex_ID;
109 } se_manager_osal_mutex_t;
110 
111 // -----------------------------------------------------------------------------
112 // Functions
113 
114 /// Initialize a mutex object.
115 __STATIC_INLINE
se_manager_osal_init_mutex(se_manager_osal_mutex_t * mutex)116 sl_status_t se_manager_osal_init_mutex(se_manager_osal_mutex_t *mutex)
117 {
118   if (mutex == NULL) {
119     return SL_STATUS_FAIL;
120   }
121 
122 #if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT) && (configSUPPORT_STATIC_ALLOCATION == 1)
123   // Zeroize all members of the mutex attributes object and setup the static control block.
124   memset(&mutex->mutex_attr, 0, sizeof(mutex->mutex_attr));
125   mutex->mutex_attr.cb_mem = &mutex->static_sem_object;
126   mutex->mutex_attr.cb_size = sizeof(mutex->static_sem_object);
127   mutex->mutex_ID = osMutexNew(&mutex->mutex_attr);
128 #else
129   mutex->mutex_ID = osMutexNew(NULL);
130 #endif
131 
132   return (mutex->mutex_ID == NULL ? SL_STATUS_FAIL : SL_STATUS_OK);
133 }
134 
135 /// Free a mutex object.
136 __STATIC_INLINE
se_manager_osal_free_mutex(se_manager_osal_mutex_t * mutex)137 sl_status_t se_manager_osal_free_mutex(se_manager_osal_mutex_t *mutex)
138 {
139   if (mutex == NULL) {
140     return SL_STATUS_FAIL;
141   }
142 
143   osStatus_t status = osMutexDelete(mutex->mutex_ID);
144   return (status == osOK ? SL_STATUS_OK : SL_STATUS_FAIL);
145 }
146 
147 /// Acquire ownership of a mutex. If busy, wait until available.
148 __STATIC_INLINE
se_manager_osal_take_mutex(se_manager_osal_mutex_t * mutex)149 sl_status_t se_manager_osal_take_mutex(se_manager_osal_mutex_t *mutex)
150 {
151   if (mutex == NULL) {
152     return SL_STATUS_FAIL;
153   }
154 
155   osStatus_t status = osOK;
156   if (osKernelGetState() == osKernelRunning) {
157     status = osMutexAcquire(mutex->mutex_ID, SE_MANAGER_OSAL_WAIT_FOREVER);
158   }
159   return (status == osOK ? SL_STATUS_OK : SL_STATUS_FAIL);
160 }
161 
162 /// Try to acquire ownership of a mutex without waiting.
163 __STATIC_INLINE
se_manager_osal_take_mutex_non_blocking(se_manager_osal_mutex_t * mutex)164 sl_status_t se_manager_osal_take_mutex_non_blocking(se_manager_osal_mutex_t *mutex)
165 {
166   if (mutex == NULL) {
167     return SL_STATUS_FAIL;
168   }
169 
170   osStatus_t status = osOK;
171   if (osKernelGetState() == osKernelRunning) {
172     status = osMutexAcquire(mutex->mutex_ID, SE_MANAGER_OSAL_NON_BLOCKING);
173   }
174   return (status == osOK ? SL_STATUS_OK : SL_STATUS_FAIL);
175 }
176 
177 /// Release ownership of a mutex.
178 __STATIC_INLINE
se_manager_osal_give_mutex(se_manager_osal_mutex_t * mutex)179 sl_status_t se_manager_osal_give_mutex(se_manager_osal_mutex_t *mutex)
180 {
181   if (mutex == NULL) {
182     return SL_STATUS_FAIL;
183   }
184 
185   osStatus_t status = osOK;
186   if (osKernelGetState() == osKernelRunning) {
187     status = osMutexRelease(mutex->mutex_ID);
188   }
189   return (status == osOK ? SL_STATUS_OK : SL_STATUS_FAIL);
190 }
191 
192 /// Initialize a completion object.
193 __STATIC_INLINE sl_status_t
se_manager_osal_init_completion(se_manager_osal_completion_t * p_comp)194 se_manager_osal_init_completion(se_manager_osal_completion_t *p_comp)
195 {
196   if (p_comp == NULL) {
197     return SL_STATUS_FAIL;
198   }
199 
200 #if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT) && (configSUPPORT_STATIC_ALLOCATION == 1)
201   // Zeroize all members of the semaphore attributes object and setup the static control block.
202   memset(&p_comp->semaphore_attr, 0, sizeof(p_comp->semaphore_attr));
203   p_comp->semaphore_attr.cb_mem = &p_comp->static_sem_object;
204   p_comp->semaphore_attr.cb_size = sizeof(p_comp->static_sem_object);
205   p_comp->semaphore_ID = osSemaphoreNew(1u, 0u, &p_comp->semaphore_attr);
206 #else
207   p_comp->semaphore_ID = osSemaphoreNew(1u, 0u, NULL);
208 #endif
209 
210   return (p_comp->semaphore_ID == NULL ? SL_STATUS_FAIL : SL_STATUS_OK);
211 }
212 
213 /// Free a completion object.
214 __STATIC_INLINE sl_status_t
se_manager_osal_free_completion(se_manager_osal_completion_t * p_comp)215 se_manager_osal_free_completion(se_manager_osal_completion_t *p_comp)
216 {
217   if (p_comp == NULL) {
218     return SL_STATUS_FAIL;
219   }
220 
221   osStatus_t status = osSemaphoreDelete(p_comp->semaphore_ID);
222   return (status == osOK ? SL_STATUS_OK : SL_STATUS_FAIL);
223 }
224 
225 // Wait for a completion object to be completed.
226 __STATIC_INLINE sl_status_t
se_manager_osal_wait_completion(se_manager_osal_completion_t * p_comp,int ticks)227 se_manager_osal_wait_completion(se_manager_osal_completion_t *p_comp, int ticks)
228 {
229   if (p_comp == NULL) {
230     return SL_STATUS_FAIL;
231   }
232 
233   osStatus_t status = osOK;
234   if (osKernelGetState() == osKernelRunning) {
235     status = osSemaphoreAcquire(p_comp->semaphore_ID,
236                                 (uint32_t)ticks);
237   }
238   return (status == osOK ? SL_STATUS_OK : SL_STATUS_FAIL);
239 }
240 
241 // Complete a completion object.
242 __STATIC_INLINE sl_status_t
se_manager_osal_complete(se_manager_osal_completion_t * p_comp)243 se_manager_osal_complete(se_manager_osal_completion_t* p_comp)
244 {
245   if (p_comp == NULL) {
246     return SL_STATUS_FAIL;
247   }
248 
249   osStatus_t status = osOK;
250   osKernelState_t state = osKernelGetState();
251   if ((state == osKernelRunning) || (state == osKernelLocked)) {
252     status = osSemaphoreRelease(p_comp->semaphore_ID);
253   }
254   return (status == osOK ? SL_STATUS_OK : SL_STATUS_FAIL);
255 }
256 
257 // Lock the RTOS Kernel scheduler.
258 __STATIC_INLINE int32_t
se_manager_osal_kernel_lock(void)259 se_manager_osal_kernel_lock(void)
260 {
261   return osKernelLock();
262 }
263 
264 // Restore the RTOS Kernel scheduler lock state.
265 __STATIC_INLINE int32_t
se_manager_osal_kernel_restore_lock(int32_t lock)266 se_manager_osal_kernel_restore_lock(int32_t lock)
267 {
268   return osKernelRestoreLock(lock);
269 }
270 
271 // Current RTOS kernel state.
272 __STATIC_INLINE osKernelState_t
se_manager_osal_kernel_get_state(void)273 se_manager_osal_kernel_get_state(void)
274 {
275   return osKernelGetState();
276 }
277 
278 #ifdef __cplusplus
279 }
280 #endif
281 
282 #endif // SE_MANAGER_OSAL_CMSIS_RTOS_H
283