Select one of the symbols to view example projects that use it.
 
Outline
#include "freertos/FreeRTOS.h"
#include "spinlock.h"
#define OS_SPINLOCK
#define OS_SPINLOCK
esp_os_spinlock_t
#define DEFINE_CRIT_SECTION_LOCK_STATIC
#define DEFINE_CRIT_SECTION_LOCK_STATIC
#define DEFINE_CRIT_SECTION_LOCK
#define DEFINE_CRIT_SECTION_LOCK
#define INIT_CRIT_SECTION_LOCK_RUNTIME
#define INIT_CRIT_SECTION_LOCK_RUNTIME
#define DECLARE_CRIT_SECTION_LOCK_IN_STRUCT
#define DECLARE_CRIT_SECTION_LOCK_IN_STRUCT
#define INIT_CRIT_SECTION_LOCK_IN_STRUCT
#define INIT_CRIT_SECTION_LOCK_IN_STRUCT
#define esp_os_enter_critical
#define esp_os_enter_critical
#define esp_os_exit_critical
#define esp_os_exit_critical
#define esp_os_enter_critical_isr
#define esp_os_enter_critical_isr
#define esp_os_exit_critical_isr
#define esp_os_exit_critical_isr
#define esp_os_enter_critical_safe
#define esp_os_enter_critical_safe
#define esp_os_exit_critical_safe
#define esp_os_exit_critical_safe
Files
loading...
SourceVuESP-IDF Framework and ExamplesESP-IDFcomponents/esp_system/include/esp_private/critical_section.h
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/* * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 *//* ... */ /** * This file provides an abstract OS API for entering and exiting critical sections. * It furthermore provides macros to define and initialize an optional spinlock * if the used chip is a multi-core chip. If a single-core chip is used, just disabling interrupts * is sufficient to guarantee consecutive, non-interrupted execution of a critical section. * Hence, the spinlock is unneccessary and will be automatically ommitted by the macros. *//* ... */ #pragma once #include "freertos/FreeRTOS.h" #include "spinlock.h" #ifdef __cplusplus extern "C" { #endif #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32P4 /** * This macro also helps users switching between spinlock declarations/definitions for multi-/single core environments * if the macros below aren't sufficient. *//* ... */ #define OS_SPINLOCK 1/* ... */ #else #define OS_SPINLOCK 0 #endif #if OS_SPINLOCK == 1 typedef spinlock_t esp_os_spinlock_t; #endif /** * Define and initialize a static (internal linking) lock for entering critical sections. * * Use this when all the critical sections are local inside a file. * The lock will only be defined if built for a multi-core system, otherwise it is unnecessary. * * @note When using this macro, the critical section macros esp_os_enter_critical* and esp_os_exit_critical* * MUST be used, otherwise normal functions would be passed an undefined variable when build for single-core systems. * * @param lock_name Variable name of the lock. This will later be used to reference the declared lock. * @param optional_qualifiers Qualifiers such as DRAM_ATTR and other attributes. Can be omitted if no qualifiers are * required. * * Example usage: * @code{c} * ... * #include "os/critical_section.h" * ... * DEFINE_CRIT_SECTION_LOCK_STATIC(my_lock); // will have internal linking (static) * ... * esp_os_enter_critical(&my_lock); * ... * esp_os_exit_critical(&my_lock); * @endcode *//* ... */ #if OS_SPINLOCK == 1 #define DEFINE_CRIT_SECTION_LOCK_STATIC(lock_name, optional_qualifiers...) static optional_qualifiers esp_os_spinlock_t lock_name = SPINLOCK_INITIALIZER #else #define DEFINE_CRIT_SECTION_LOCK_STATIC(lock_name, optional_qualifiers...) #endif /** * Define and initialize a non-static (external linking) lock for entering critical sections. * * Locks defined by this macro can be linked among object files but this rather exceptional. * Prefer the static lock definition whenever possible. * The lock will only be defined if built for a multi-core system, otherwise it is unnecessary. * * @note When using this macro, the critical section macros esp_os_enter_critical* and esp_os_exit_critical* * MUST be used, otherwise normal functions would be passed an undefined variable when build for single-core systems. * * @param lock_name Variable name of the lock. This will later be used to reference the declared lock. * @param optional_qualifiers Qualifiers such as DRAM_ATTR and other attributes. Can be omitted if no qualifiers are * required. * * Example usage: * @code{c} * ... * #include "os/critical_section.h" * ... * DEFINE_CRIT_SECTION_LOCK(my_lock); // will have external linking (non-static) * ... * esp_os_enter_critical(&my_lock); * ... * esp_os_exit_critical(&my_lock); * @endcode *//* ... */ #if OS_SPINLOCK == 1 #define DEFINE_CRIT_SECTION_LOCK(lock_name, optional_qualifiers...) optional_qualifiers esp_os_spinlock_t lock_name = SPINLOCK_INITIALIZER #else #define DEFINE_CRIT_SECTION_LOCK(lock_name, optional_qualifiers...) #endif /** * @brief This macro initializes a critical section lock at runtime. * * This macro basically creates a member of the initialization list, including the trailing comma. * If the lock is unnecessary because the architecture is single-core, this macro will not do anything. * This is incompatible with a lock created by DEFINE_CRIT_SECTION_LOCK_STATIC from above. * * @param lock_name Pointer to the lock. * * @note When using this macro, the critical section macros esp_os_enter_critical* and esp_os_exit_critical* * MUST be used, otherwise normal functions would be passed an undefined variable when build for single-core * systems. * * Example usage: * @code{c} * ... * #include "os/critical_section.h" * ... * typedef struct protected_struct_t { * int member1; * DECLARE_CRIT_SECTION_LOCK_IN_STRUCT(my_lock) * int another_member; * }; * ... * protected_struct_t my_protected; * INIT_CRIT_SECTION_LOCK_IN_STRUCT(&(my_protected.my_lock)); * }; * @endcode *//* ... */ #if OS_SPINLOCK == 1 #define INIT_CRIT_SECTION_LOCK_RUNTIME(lock_name) spinlock_initialize(lock_name) #else #define INIT_CRIT_SECTION_LOCK_RUNTIME(lock_name) #endif /** * @brief This macro declares a critical section lock as a member of a struct. * * The critical section lock member is only declared if built for multi-core systems, otherwise it is omitted. * * @note When using this macro, the critical section macros esp_os_enter_critical* and esp_os_exit_critical* * MUST be used, otherwise normal functions would be passed an undefined variable when build for single-core * systems. * @note Do NOT add any semicolon after declaring the member with this macro. * The trailing semicolon is included in the macro, otherwise -Wpedantic would complain about * superfluous ";" if OS_SPINLOCK == 0. * * Example usage: * @code{c} * ... * #include "os/critical_section.h" * ... * typedef struct protected_struct_t { * int member1; * DECLARE_CRIT_SECTION_LOCK_IN_STRUCT(my_lock) // no semicolon! * int another_member; * }; * @endcode *//* ... */ #if OS_SPINLOCK == 1 #define DECLARE_CRIT_SECTION_LOCK_IN_STRUCT(lock_name) esp_os_spinlock_t lock_name; #else #define DECLARE_CRIT_SECTION_LOCK_IN_STRUCT(lock_name) #endif /** * @brief This macro initializes a critical section lock as a member of a struct when using an list initialization. * It has to be used together with \c DECLARE_CRIT_SECTION_LOCK_IN_STRUCT() to work. * * This macro basically creates a member of the initialization list, including the trailing comma. * If the lock is unnecessary because the architecture is single-core, this macro will not do anything. * This means that if \c lock_name is still a member of the struct, \c lock_name will be uninitialized. * Hence, this macro has to be used together with \c DECLARE_CRIT_SECTION_LOCK_IN_STRUCT() to correctly to declare * or omit the struct member \c lock_name. * * @param lock_name The field name of the lock inside the struct. * * @note When using this macro, the critical section macros esp_os_enter_critical* and esp_os_exit_critical* * MUST be used, otherwise normal functions would be passed an undefined variable when build for single-core * systems. * @note Do NOT add any comma in the initializer list after using this macro. * * Example usage: * @code{c} * ... * #include "os/critical_section.h" * ... * typedef struct protected_struct_t { * int member1; * DECLARE_CRIT_SECTION_LOCK_IN_STRUCT(my_lock) * int another_member; * }; * ... * protected_struct_t my_protected = { * .member1 = 0, * INIT_CRIT_SECTION_LOCK_IN_STRUCT(my_lock) // no comma! * another_member = 47, * }; * @endcode *//* ... */ #if OS_SPINLOCK == 1 #define INIT_CRIT_SECTION_LOCK_IN_STRUCT(lock_name) .lock_name = portMUX_INITIALIZER_UNLOCKED, #else #define INIT_CRIT_SECTION_LOCK_IN_STRUCT(lock_name) #endif /** * @brief Enter a critical section, i.e., a section that will not be interrupted by any other task or interrupt. * * On multi-core systems, this will disable interrupts and take the spinlock \c lock. On single core systems, a * spinlock is unncessary, hence \c lock is ignored and interrupts are disabled only. * * @note This macro MUST be used together with any of the initialization macros, e.g. * DEFINE_CRIT_SECTION_LOCK_STATIC. If not, there may be unused variables. * * @param lock Pointer to the critical section lock. Ignored if build for single core system. * * Example usage with static locks: * @code{c} * ... * #include "os/critical_section.h" * ... * DEFINE_CRIT_SECTION_LOCK_STATIC(my_lock); // will have internal linking (static) * ... * esp_os_enter_critical(&my_lock); * // code inside critical section * esp_os_exit_critical(&my_lock); * @endcode *//* ... */ #if OS_SPINLOCK == 1 #define esp_os_enter_critical(lock) portENTER_CRITICAL(lock) #else #define esp_os_enter_critical(lock) vPortEnterCritical() #endif /** * @brief Exit a critical section. * * On multi-core systems, this will enable interrupts and release the spinlock \c lock. On single core systems, a * spinlock is unncessary, hence \c lock is ignored and interrupts are enabled only. * * @note This macro MUST be used together with any of the initialization macros, e.g. * DEFINE_CRIT_SECTION_LOCK_STATIC. If not, there may be unused variables. * * @param lock Pointer to the critical section lock. Ignored if build for single core system. * * Example usage with static locks: * @code{c} * ... * #include "os/critical_section.h" * ... * DEFINE_CRIT_SECTION_LOCK_STATIC(my_lock); // will have internal linking (static) * ... * esp_os_enter_critical(&my_lock); * // code inside critical section * esp_os_exit_critical(&my_lock); * @endcode *//* ... */ #if OS_SPINLOCK == 1 #define esp_os_exit_critical(lock) portEXIT_CRITICAL(lock) #else #define esp_os_exit_critical(lock) vPortExitCritical() #endif /** * @brief Enter a critical section while from ISR. * * On multi-core systems, this will disable interrupts and take the spinlock \c lock. On single core systems, a * spinlock is unncessary, hence \c lock is ignored and interrupts are disabled only. * * @note This macro MUST be used together with any of the initialization macros, e.g. * DEFINE_CRIT_SECTION_LOCK_STATIC. If not, there may be unused variables. * * @param lock Pointer to the critical section lock. Ignored if build for single core system. * * Example usage with static locks: * @code{c} * ... * #include "os/critical_section.h" * ... * DEFINE_CRIT_SECTION_LOCK_STATIC(my_lock); // will have internal linking (static) * ... * esp_os_enter_critical(&my_lock); * // code inside critical section * esp_os_exit_critical(&my_lock); * @endcode *//* ... */ #if OS_SPINLOCK == 1 #define esp_os_enter_critical_isr(lock) portENTER_CRITICAL_ISR(lock) #else #define esp_os_enter_critical_isr(lock) vPortEnterCritical() #endif /** * @brief Exit a critical section after entering from ISR. * * On multi-core systems, this will enable interrupts and release the spinlock \c lock. On single core systems, a * spinlock is unncessary, hence \c lock is ignored and interrupts are enabled only. * * @note This macro MUST be used together with any of the initialization macros, e.g. * DEFINE_CRIT_SECTION_LOCK_STATIC. If not, there may be unused variables. * * @param lock Pointer to the critical section lock. Ignored if build for single core system. * * Example usage with static locks: * @code{c} * ... * #include "os/critical_section.h" * ... * DEFINE_CRIT_SECTION_LOCK_STATIC(my_lock); // will have internal linking (static) * ... * esp_os_enter_critical(&my_lock); * // code inside critical section * esp_os_exit_critical(&my_lock); * @endcode *//* ... */ #if OS_SPINLOCK == 1 #define esp_os_exit_critical_isr(lock) portEXIT_CRITICAL_ISR(lock) #else #define esp_os_exit_critical_isr(lock) vPortExitCritical() #endif /** * @brief Enter a critical section from normal task or ISR. This macro will check if the current CPU is processing * an ISR or not and enter the critical section accordingly. * * On multi-core systems, this will disable interrupts and take the spinlock \c lock. On single core systems, a * spinlock is unncessary, hence \c lock is ignored and interrupts are disabled only. * * @note This macro MUST be used together with any of the initialization macros, e.g. * DEFINE_CRIT_SECTION_LOCK_STATIC. If not, there may be unused variables. * * @param lock Pointer to the critical section lock. Ignored if build for single core system. * * Example usage with static locks: * @code{c} * ... * #include "os/critical_section.h" * ... * DEFINE_CRIT_SECTION_LOCK_STATIC(my_lock); // will have internal linking (static) * ... * esp_os_enter_critical(&my_lock); * // code inside critical section * esp_os_exit_critical(&my_lock); * @endcode *//* ... */ #if OS_SPINLOCK == 1 #define esp_os_enter_critical_safe(lock) portENTER_CRITICAL_SAFE(lock) #else #define esp_os_enter_critical_safe(lock) vPortEnterCritical() #endif /** * @brief Exit a critical section after entering via esp_os_enter_critical_safe. * * On multi-core systems, this will enable interrupts and release the spinlock \c lock. On single core systems, a * spinlock is unncessary, hence \c lock is ignored and interrupts are enabled only. * * @note This macro MUST be used together with any of the initialization macros, e.g. * DEFINE_CRIT_SECTION_LOCK_STATIC. If not, there may be unused variables. * * @param lock Pointer to the critical section lock. Ignored if build for single core system. * * Example usage with static locks: * @code{c} * ... * #include "os/critical_section.h" * ... * DEFINE_CRIT_SECTION_LOCK_STATIC(my_lock); // will have internal linking (static) * ... * esp_os_enter_critical(&my_lock); * // code inside critical section * esp_os_exit_critical(&my_lock); * @endcode *//* ... */ #if OS_SPINLOCK == 1 #define esp_os_exit_critical_safe(lock) portEXIT_CRITICAL_SAFE(lock) #else #define esp_os_exit_critical_safe(lock) vPortExitCritical() #endif #ifdef __cplusplus }{...} #endif
Details