F439_CPP_TX-RX_LoRa_Project

Loading...
Searching...
No Matches
stm32_lock.h
Go to the documentation of this file.
1
61#ifndef __STM32_LOCK_H__
62#define __STM32_LOCK_H__
63
64/* Includes ------------------------------------------------------------------*/
65#include <stdint.h>
66#include <stddef.h>
67#include <cmsis_compiler.h>
68
69#ifndef STM32_THREAD_SAFE_STRATEGY
70#define STM32_THREAD_SAFE_STRATEGY 2
71#endif /* STM32_THREAD_SAFE_STRATEGY */
72
73#ifdef __cplusplus
74 extern "C" {
75#endif /* __cplusplus */
76
77/* Function prototypes -------------------------------------------------------*/
78 void Error_Handler(void);
79
80/* Public macros -------------------------------------------------------------*/
82#define STM32_LOCK_BLOCK() \
83 do \
84 { \
85 __disable_irq(); \
86 Error_Handler(); \
87 while (1); \
88 } while (0)
89
91#define STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(x) \
92 do \
93 { \
94 if ((x) == NULL) \
95 { \
96 STM32_LOCK_BLOCK(); \
97 } \
98 } while (0)
99
101#define STM32_LOCK_BLOCK_IF_INTERRUPT_CONTEXT() \
102 do \
103 { \
104 if (__get_IPSR()) \
105 { \
106 STM32_LOCK_BLOCK(); \
107 } \
108 } while (0)
109
111#define STM32_LOCK_UNUSED(var) (void)var
112
114#define STM32_LOCK_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
115
116#if STM32_THREAD_SAFE_STRATEGY == 1
117/*
118 * User defined thread-safe implementation.
119 */
120
121/* Includes ----------------------------------------------------------------*/
123#define STM32_LOCK_API 1
124#include "stm32_lock_user.h"
125#undef STM32_LOCK_API
126
127#elif STM32_THREAD_SAFE_STRATEGY == 2
128/*
129 * Allow lock usage from interrupts.
130 */
131
132/* Private defines ---------------------------------------------------------*/
134#define LOCKING_DATA_INIT { 0, 0 }
135
136/* Private typedef ---------------------------------------------------------*/
137 typedef struct
138{
139 uint8_t flag;
140 uint8_t counter;
141} LockingData_t;
142
143/* Private functions -------------------------------------------------------*/
144
149 static inline void stm32_lock_init(LockingData_t *lock)
150{
151 STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
152 lock->flag = 0;
153 lock->counter = 0;
154}
155
160 static inline void stm32_lock_acquire(LockingData_t *lock)
161{
162 uint8_t flag = (uint8_t)(__get_PRIMASK() & 0x1); /* PRIMASK.PM */
163 __disable_irq();
164 __DSB();
165 __ISB();
166 STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
167 if (lock->counter == 0)
168 {
169 lock->flag = flag;
170 }
171 else if (lock->counter == UINT8_MAX)
172 {
173 STM32_LOCK_BLOCK();
174 }
175 lock->counter++;
176}
177
182 static inline void stm32_lock_release(LockingData_t *lock)
183{
184 STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
185 if (lock->counter == 0)
186 {
187 STM32_LOCK_BLOCK();
188 }
189 lock->counter--;
190 if (lock->counter == 0 && lock->flag == 0)
191 {
192 __enable_irq();
193 }
194}
195
196#elif STM32_THREAD_SAFE_STRATEGY == 3
197/*
198 * Deny lock usage from interrupts.
199 */
200
201/* Private defines ---------------------------------------------------------*/
203#define LOCKING_DATA_INIT 0
204
205/* Private typedef ---------------------------------------------------------*/
206 typedef uint8_t LockingData_t;
208/* Private functions -------------------------------------------------------*/
209
214 static inline void stm32_lock_init(LockingData_t *lock)
215{
216 STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
217}
218
223 static inline void stm32_lock_acquire(LockingData_t *lock)
224{
225 STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
226 STM32_LOCK_BLOCK_IF_INTERRUPT_CONTEXT();
227}
228
233 static inline void stm32_lock_release(LockingData_t *lock)
234{
235 STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
236 STM32_LOCK_BLOCK_IF_INTERRUPT_CONTEXT();
237}
238
239#elif STM32_THREAD_SAFE_STRATEGY == 4
240/*
241 * Allow lock usage from interrupts. Implemented using FreeRTOS locks.
242 */
243
244/* Includes ----------------------------------------------------------------*/
245#include <FreeRTOS.h>
246#include <task.h>
247
248#if defined (__GNUC__) && !defined (__CC_ARM) && configUSE_NEWLIB_REENTRANT == 0
249#warning Please set configUSE_NEWLIB_REENTRANT to 1 in FreeRTOSConfig.h, otherwise newlib will not be thread-safe
250#endif /* defined (__GNUC__) && !defined (__CC_ARM) && configUSE_NEWLIB_REENTRANT == 0 */
251
252/* Private defines ---------------------------------------------------------*/
254#define LOCKING_DATA_INIT { {0, 0}, 0 }
255#define STM32_LOCK_MAX_NESTED_LEVELS 2
256 typedef struct
257{
258 uint32_t basepri[STM32_LOCK_MAX_NESTED_LEVELS];
259 uint8_t nesting_level;
260} LockingData_t;
261
262/* Private macros ----------------------------------------------------------*/
264#define STM32_LOCK_ASSERT_VALID_NESTING_LEVEL(lock) \
265 do \
266 { \
267 if (lock->nesting_level >= STM32_LOCK_ARRAY_SIZE(lock->basepri)) \
268 { \
269 STM32_LOCK_BLOCK(); \
270 } \
271 } while (0)
272
273/* Private functions -------------------------------------------------------*/
274
279 static inline void stm32_lock_init(LockingData_t *lock)
280{
281 STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
282 for (size_t i = 0; i < STM32_LOCK_ARRAY_SIZE(lock->basepri); i++)
283 {
284 lock->basepri[i] = 0;
285 }
286 lock->nesting_level = 0;
287}
288
293 static inline void stm32_lock_acquire(LockingData_t *lock)
294{
295 STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
296 STM32_LOCK_ASSERT_VALID_NESTING_LEVEL(lock);
297 lock->basepri[lock->nesting_level++] = taskENTER_CRITICAL_FROM_ISR();
298}
299
304 static inline void stm32_lock_release(LockingData_t *lock)
305{
306 STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
307 lock->nesting_level--;
308 STM32_LOCK_ASSERT_VALID_NESTING_LEVEL(lock);
309 taskEXIT_CRITICAL_FROM_ISR(lock->basepri[lock->nesting_level]);
310}
311
312#undef STM32_LOCK_ASSERT_VALID_NESTING_LEVEL
313#undef STM32_LOCK_MAX_NESTED_LEVELS
314
315#elif STM32_THREAD_SAFE_STRATEGY == 5
316/*
317 * Deny lock usage from interrupts. Implemented using FreeRTOS locks.
318 */
319
320/* Includes ----------------------------------------------------------------*/
321#include <FreeRTOS.h>
322#include <task.h>
323#if defined (__GNUC__) && !defined (__CC_ARM) && configUSE_NEWLIB_REENTRANT == 0
324#warning Please set configUSE_NEWLIB_REENTRANT to 1 in FreeRTOSConfig.h, otherwise newlib will not be thread-safe
325#endif /* defined (__GNUC__) && !defined (__CC_ARM) && configUSE_NEWLIB_REENTRANT == 0 */
326
327/* Private defines ---------------------------------------------------------*/
329#define LOCKING_DATA_INIT 0
330
331/* Private typedef ---------------------------------------------------------*/
332 typedef uint8_t LockingData_t;
334/* Private functions -------------------------------------------------------*/
335
340 static inline void stm32_lock_init(LockingData_t *lock)
341{
342 STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
343}
344
349 static inline void stm32_lock_acquire(LockingData_t *lock)
350{
351 STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
352 STM32_LOCK_BLOCK_IF_INTERRUPT_CONTEXT();
353 vTaskSuspendAll();
354}
355
360 static inline void stm32_lock_release(LockingData_t *lock)
361{
362 STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
363 STM32_LOCK_BLOCK_IF_INTERRUPT_CONTEXT();
364 xTaskResumeAll();
365}
366
367#else
368#error Invalid STM32_THREAD_SAFE_STRATEGY specified
369#endif /* STM32_THREAD_SAFE_STRATEGY */
370
371#ifdef __cplusplus
372} /* extern "C" */
373#endif /* __cplusplus */
374
375#endif /* __STM32_LOCK_H__ */
Error_Handler
void Error_Handler(void)
Global Error_Handler.
Definition newlib_lock_glue.c:44
STM32_LOCK_ARRAY_SIZE
#define STM32_LOCK_ARRAY_SIZE(array)
Definition stm32_lock.h:114
STM32_LOCK_BLOCK_IF_INTERRUPT_CONTEXT
#define STM32_LOCK_BLOCK_IF_INTERRUPT_CONTEXT()
Definition stm32_lock.h:101
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT
#define STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(x)
Definition stm32_lock.h:91
STM32_LOCK_BLOCK
#define STM32_LOCK_BLOCK()
Definition stm32_lock.h:82
LockingData_t
Definition stm32_lock.h:138
LockingData_t::flag
uint8_t flag
Definition stm32_lock.h:139
LockingData_t::counter
uint8_t counter
Definition stm32_lock.h:140