firmware
IEM Firmware Documentation
Loading...
Searching...
No Matches
stm32_lock.h
Go to the documentation of this file.
1
63
64#ifndef __STM32_LOCK_H__
65#define __STM32_LOCK_H__
66
67/* Includes ------------------------------------------------------------------*/
68#include <stdint.h>
69#include <stddef.h>
70#include <cmsis_compiler.h>
71
72#ifndef STM32_THREAD_SAFE_STRATEGY
73 #define STM32_THREAD_SAFE_STRATEGY 2
74#endif /* STM32_THREAD_SAFE_STRATEGY */
75
76#ifdef __cplusplus
77extern "C" {
78#endif /* __cplusplus */
79
80/* Function prototypes -------------------------------------------------------*/
81void Error_Handler(void);
82
83/* Public macros -------------------------------------------------------------*/
85#define STM32_LOCK_BLOCK() \
86 do { \
87 __disable_irq(); \
88 Error_Handler(); \
89 while (1); \
90 } while (0)
91
93#define STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(x) \
94 do { \
95 if ((x) == NULL) { \
96 STM32_LOCK_BLOCK(); \
97 } \
98 } while (0)
99
101#define STM32_LOCK_BLOCK_IF_INTERRUPT_CONTEXT() \
102 do { \
103 if (__get_IPSR()) { \
104 STM32_LOCK_BLOCK(); \
105 } \
106 } while (0)
107
109#define STM32_LOCK_UNUSED(var) (void)var
110
112#define STM32_LOCK_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
113
114#if STM32_THREAD_SAFE_STRATEGY == 1
115 /*
116 * User defined thread-safe implementation.
117 */
118
119 /* Includes ----------------------------------------------------------------*/
121 #define STM32_LOCK_API 1
122 #include "stm32_lock_user.h"
123 #undef STM32_LOCK_API
124
125#elif STM32_THREAD_SAFE_STRATEGY == 2
126 /*
127 * Allow lock usage from interrupts.
128 */
129
130 /* Private defines ---------------------------------------------------------*/
132 #define LOCKING_DATA_INIT { 0, 0 }
133
134/* Private typedef ---------------------------------------------------------*/
135typedef struct {
136 uint8_t flag;
137 uint8_t counter;
139
140/* Private functions -------------------------------------------------------*/
141
146static inline void stm32_lock_init(LockingData_t *lock) {
148 lock->flag = 0;
149 lock->counter = 0;
150}
151
156static inline void stm32_lock_acquire(LockingData_t *lock) {
157 uint8_t flag = (uint8_t)(__get_PRIMASK() & 0x1); /* PRIMASK.PM */
158 __disable_irq();
159 __DSB();
160 __ISB();
162 if (lock->counter == 0) {
163 lock->flag = flag;
164 } else if (lock->counter == UINT8_MAX) {
166 }
167 lock->counter++;
168}
169
174static inline void stm32_lock_release(LockingData_t *lock) {
176 if (lock->counter == 0) {
178 }
179 lock->counter--;
180 if (lock->counter == 0 && lock->flag == 0) {
181 __enable_irq();
182 }
183}
184
185#elif STM32_THREAD_SAFE_STRATEGY == 3
186 /*
187 * Deny lock usage from interrupts.
188 */
189
190 /* Private defines ---------------------------------------------------------*/
192 #define LOCKING_DATA_INIT 0
193
194/* Private typedef ---------------------------------------------------------*/
195typedef uint8_t LockingData_t;
196
197/* Private functions -------------------------------------------------------*/
198
203static inline void stm32_lock_init(LockingData_t *lock) { STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock); }
204
209static inline void stm32_lock_acquire(LockingData_t *lock) {
212}
213
218static inline void stm32_lock_release(LockingData_t *lock) {
221}
222
223#elif STM32_THREAD_SAFE_STRATEGY == 4
224 /*
225 * Allow lock usage from interrupts. Implemented using FreeRTOS locks.
226 */
227
228 /* Includes ----------------------------------------------------------------*/
229 #include <FreeRTOS.h>
230 #include <task.h>
231
232 #if defined(__GNUC__) && !defined(__CC_ARM) && configUSE_NEWLIB_REENTRANT == 0
233 #warning Please set configUSE_NEWLIB_REENTRANT to 1 in FreeRTOSConfig.h, otherwise newlib will not be thread-safe
234 #endif /* defined (__GNUC__) && !defined (__CC_ARM) && configUSE_NEWLIB_REENTRANT == 0 */
235
236 /* Private defines ---------------------------------------------------------*/
238 #define LOCKING_DATA_INIT { { 0, 0 }, 0 }
239 #define STM32_LOCK_MAX_NESTED_LEVELS 2
240typedef struct {
241 uint32_t basepri[STM32_LOCK_MAX_NESTED_LEVELS];
242 uint8_t nesting_level;
244
245 /* Private macros ----------------------------------------------------------*/
247 #define STM32_LOCK_ASSERT_VALID_NESTING_LEVEL(lock) \
248 do { \
249 if (lock->nesting_level >= STM32_LOCK_ARRAY_SIZE(lock->basepri)) { \
250 STM32_LOCK_BLOCK(); \
251 } \
252 } while (0)
253
254/* Private functions -------------------------------------------------------*/
255
260static inline void stm32_lock_init(LockingData_t *lock) {
262 for (size_t i = 0; i < STM32_LOCK_ARRAY_SIZE(lock->basepri); i++) {
263 lock->basepri[i] = 0;
264 }
265 lock->nesting_level = 0;
266}
267
272static inline void stm32_lock_acquire(LockingData_t *lock) {
274 STM32_LOCK_ASSERT_VALID_NESTING_LEVEL(lock);
275 lock->basepri[lock->nesting_level++] = taskENTER_CRITICAL_FROM_ISR();
276}
277
282static inline void stm32_lock_release(LockingData_t *lock) {
284 lock->nesting_level--;
285 STM32_LOCK_ASSERT_VALID_NESTING_LEVEL(lock);
286 taskEXIT_CRITICAL_FROM_ISR(lock->basepri[lock->nesting_level]);
287}
288
289 #undef STM32_LOCK_ASSERT_VALID_NESTING_LEVEL
290 #undef STM32_LOCK_MAX_NESTED_LEVELS
291
292#elif STM32_THREAD_SAFE_STRATEGY == 5
293 /*
294 * Deny lock usage from interrupts. Implemented using FreeRTOS locks.
295 */
296
297 /* Includes ----------------------------------------------------------------*/
298 #include <FreeRTOS.h>
299 #include <task.h>
300 #if defined(__GNUC__) && !defined(__CC_ARM) && configUSE_NEWLIB_REENTRANT == 0
301 #warning Please set configUSE_NEWLIB_REENTRANT to 1 in FreeRTOSConfig.h, otherwise newlib will not be thread-safe
302 #endif /* defined (__GNUC__) && !defined (__CC_ARM) && configUSE_NEWLIB_REENTRANT == 0 */
303
304 /* Private defines ---------------------------------------------------------*/
306 #define LOCKING_DATA_INIT 0
307
308/* Private typedef ---------------------------------------------------------*/
309typedef uint8_t LockingData_t;
310
311/* Private functions -------------------------------------------------------*/
312
317static inline void stm32_lock_init(LockingData_t *lock) { STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock); }
318
323static inline void stm32_lock_acquire(LockingData_t *lock) {
327}
328
333static inline void stm32_lock_release(LockingData_t *lock) {
337}
338
339#else
340 #error Invalid STM32_THREAD_SAFE_STRATEGY specified
341#endif /* STM32_THREAD_SAFE_STRATEGY */
342
343#ifdef __cplusplus
344} /* extern "C" */
345#endif /* __cplusplus */
346
347#endif /* __STM32_LOCK_H__ */
void Error_Handler(void)
This function is executed in case of error occurrence.
Definition main.c:920
#define STM32_LOCK_ARRAY_SIZE(array)
Definition stm32_lock.h:112
#define STM32_LOCK_BLOCK_IF_INTERRUPT_CONTEXT()
Definition stm32_lock.h:101
#define STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(x)
Definition stm32_lock.h:93
#define STM32_LOCK_BLOCK()
Definition stm32_lock.h:85
User defined lock mechanisms.
static void stm32_lock_acquire(LockingData_t *lock)
Acquire STM32 lock.
Definition stm32_lock_user.h:80
static void stm32_lock_release(LockingData_t *lock)
Release STM32 lock.
Definition stm32_lock_user.h:91
static void stm32_lock_init(LockingData_t *lock)
Initialize STM32 lock.
Definition stm32_lock_user.h:70
Definition stm32_lock_user.h:59
uint8_t nesting_level
Definition stm32_lock_user.h:61
#define taskENTER_CRITICAL_FROM_ISR()
Definition task.h:231
#define taskEXIT_CRITICAL_FROM_ISR(x)
Definition task.h:250
void vTaskSuspendAll(void)
Definition tasks.c:3811
BaseType_t xTaskResumeAll(void)
Definition tasks.c:3956