TNeo
v1.09
arch
cortex_m
tn_arch_cortex_m.h
Go to the documentation of this file.
1
/*******************************************************************************
2
*
3
* TNeo: real-time kernel initially based on TNKernel
4
*
5
* TNKernel: copyright 2004, 2013 Yuri Tiomkin.
6
* PIC32-specific routines: copyright 2013, 2014 Anders Montonen.
7
* TNeo: copyright 2014 Dmitry Frank.
8
*
9
* TNeo was born as a thorough review and re-implementation of
10
* TNKernel. The new kernel has well-formed code, inherited bugs are fixed
11
* as well as new features being added, and it is tested carefully with
12
* unit-tests.
13
*
14
* API is changed somewhat, so it's not 100% compatible with TNKernel,
15
* hence the new name: TNeo.
16
*
17
* Permission to use, copy, modify, and distribute this software in source
18
* and binary forms and its documentation for any purpose and without fee
19
* is hereby granted, provided that the above copyright notice appear
20
* in all copies and that both that copyright notice and this permission
21
* notice appear in supporting documentation.
22
*
23
* THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS"
24
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE
27
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33
* THE POSSIBILITY OF SUCH DAMAGE.
34
*
35
******************************************************************************/
36
37
/**
38
*
39
* \file
40
*
41
* Cortex-M0/M0+/M3/M4/M4F architecture-dependent routines
42
*
43
*/
44
45
#ifndef _TN_ARCH_CORTEX_M_H
46
#define _TN_ARCH_CORTEX_M_H
47
48
49
/*******************************************************************************
50
* INCLUDED FILES
51
******************************************************************************/
52
53
#include "../tn_arch_detect.h"
54
#include "../../core/tn_cfg_dispatch.h"
55
56
57
58
59
#ifdef __cplusplus
60
extern
"C"
{
/*}*/
61
#endif
62
63
64
/*******************************************************************************
65
* ARCH-DEPENDENT DEFINITIONS
66
******************************************************************************/
67
68
69
70
71
72
73
74
#ifndef DOXYGEN_SHOULD_SKIP_THIS
75
76
#define _TN_CORTEX_INTSAVE_DATA_INVALID 0xffffffff
77
78
#if TN_DEBUG
79
# define _TN_CORTEX_INTSAVE_CHECK() \
80
{ \
81
if (TN_INTSAVE_VAR == _TN_CORTEX_INTSAVE_DATA_INVALID){ \
82
_TN_FATAL_ERROR(""); \
83
} \
84
}
85
#else
86
# define _TN_CORTEX_INTSAVE_CHECK()
/* nothing */
87
#endif
88
89
#if defined(__TN_ARCHFEAT_CORTEX_M_ARMv7M_ISA__)
90
/**
91
* FFS - find first set bit. Used in `_find_next_task_to_run()` function.
92
* Say, for `0xa8` it should return `3`.
93
*
94
* May be not defined: in this case, naive algorithm will be used.
95
*/
96
#define _TN_FFS(x) ffs_asm(x)
97
int
ffs_asm(
int
x);
98
#endif
99
100
/**
101
* Used by the kernel as a signal that something really bad happened.
102
* Indicates TNeo bugs as well as illegal kernel usage
103
* (e.g. sleeping in the idle task callback)
104
*
105
* Typically, set to assembler instruction that causes debugger to halt.
106
*/
107
108
#if defined(__TN_COMPILER_IAR__)
109
# define _TN_FATAL_ERRORF(error_msg, ...) \
110
{asm("bkpt #0");}
111
#else
112
# define _TN_FATAL_ERRORF(error_msg, ...) \
113
{__asm__ volatile("bkpt #0");}
114
#endif
115
116
117
118
/**
119
* \def TN_ARCH_STK_ATTR_BEFORE
120
*
121
* Compiler-specific attribute that should be placed **before** declaration of
122
* array used for stack. It is needed because there are often additional
123
* restrictions applied to alignment of stack, so, to meet them, stack arrays
124
* need to be declared with these macros.
125
*
126
* @see TN_ARCH_STK_ATTR_AFTER
127
*/
128
129
/**
130
* \def TN_ARCH_STK_ATTR_AFTER
131
*
132
* Compiler-specific attribute that should be placed **after** declaration of
133
* array used for stack. It is needed because there are often additional
134
* restrictions applied to alignment of stack, so, to meet them, stack arrays
135
* need to be declared with these macros.
136
*
137
* @see TN_ARCH_STK_ATTR_BEFORE
138
*/
139
140
#if defined(__TN_COMPILER_ARMCC__)
141
142
# define TN_ARCH_STK_ATTR_BEFORE __align(8)
143
# define TN_ARCH_STK_ATTR_AFTER
144
145
#elif defined(__TN_COMPILER_GCC__) || defined(__TN_COMPILER_CLANG__)
146
147
# define TN_ARCH_STK_ATTR_BEFORE
148
# define TN_ARCH_STK_ATTR_AFTER __attribute__((aligned(0x08)))
149
150
#elif defined(__TN_COMPILER_IAR__)
151
152
# define TN_ARCH_STK_ATTR_BEFORE
153
# define TN_ARCH_STK_ATTR_AFTER
154
155
#endif
156
157
158
#if defined(__TN_ARCHFEAT_CORTEX_M_FPU__)
159
# define _TN_CORTEX_FPU_CONTEXT_SIZE 32
/* FPU registers: S0 .. S31 */
160
#else
161
# define _TN_CORTEX_FPU_CONTEXT_SIZE 0
/* no FPU registers */
162
#endif
163
164
165
/**
166
* Minimum task's stack size, in words, not in bytes; includes a space for
167
* context plus for parameters passed to task's body function.
168
*/
169
#define TN_MIN_STACK_SIZE (17
/* context: 17 words */
\
170
+ _TN_STACK_OVERFLOW_SIZE_ADD \
171
+ _TN_CORTEX_FPU_CONTEXT_SIZE \
172
)
173
174
/**
175
* Width of `int` type.
176
*/
177
#define TN_INT_WIDTH 32
178
179
/**
180
* Unsigned integer type whose size is equal to the size of CPU register.
181
* Typically it's plain `unsigned int`.
182
*/
183
typedef
unsigned
int
TN_UWord
;
184
185
/**
186
* Unsigned integer type that is able to store pointers.
187
* We need it because some platforms don't define `uintptr_t`.
188
* Typically it's `unsigned int`.
189
*/
190
typedef
unsigned
int
TN_UIntPtr
;
191
192
/**
193
* Maximum number of priorities available, this value usually matches
194
* `#TN_INT_WIDTH`.
195
*
196
* @see TN_PRIORITIES_CNT
197
*/
198
#define TN_PRIORITIES_MAX_CNT TN_INT_WIDTH
199
200
/**
201
* Value for infinite waiting, usually matches `ULONG_MAX`,
202
* because `#TN_TickCnt` is declared as `unsigned long`.
203
*/
204
#define TN_WAIT_INFINITE (TN_TickCnt)0xFFFFFFFF
205
206
/**
207
* Value for initializing the task's stack
208
*/
209
#define TN_FILL_STACK_VAL 0xFEEDFACE
210
211
212
213
214
/**
215
* Variable name that is used for storing interrupts state
216
* by macros TN_INTSAVE_DATA and friends
217
*/
218
#define TN_INTSAVE_VAR tn_save_status_reg
219
220
/**
221
* Declares variable that is used by macros `TN_INT_DIS_SAVE()` and
222
* `TN_INT_RESTORE()` for storing status register value.
223
*
224
* It is good idea to initially set it to some invalid value,
225
* and if TN_DEBUG is non-zero, check it in TN_INT_RESTORE().
226
* Then, we can catch bugs if someone tries to restore interrupts status
227
* without saving it first.
228
*
229
* @see `TN_INT_DIS_SAVE()`
230
* @see `TN_INT_RESTORE()`
231
*/
232
#define TN_INTSAVE_DATA \
233
TN_UWord TN_INTSAVE_VAR = _TN_CORTEX_INTSAVE_DATA_INVALID;
234
235
/**
236
* The same as `#TN_INTSAVE_DATA` but for using in ISR together with
237
* `TN_INT_IDIS_SAVE()`, `TN_INT_IRESTORE()`.
238
*
239
* @see `TN_INT_IDIS_SAVE()`
240
* @see `TN_INT_IRESTORE()`
241
*/
242
#define TN_INTSAVE_DATA_INT TN_INTSAVE_DATA
243
244
/**
245
* \def TN_INT_DIS_SAVE()
246
*
247
* Disable interrupts and return previous value of status register,
248
* atomically. Similar `tn_arch_sr_save_int_dis()`, but implemented
249
* as a macro, so it is potentially faster.
250
*
251
* Uses `#TN_INTSAVE_DATA` as a temporary storage.
252
*
253
* @see `#TN_INTSAVE_DATA`
254
* @see `tn_arch_sr_save_int_dis()`
255
*/
256
257
/**
258
* \def TN_INT_RESTORE()
259
*
260
* Restore previously saved status register.
261
* Similar to `tn_arch_sr_restore()`, but implemented as a macro,
262
* so it is potentially faster.
263
*
264
* Uses `#TN_INTSAVE_DATA` as a temporary storage.
265
*
266
* @see `#TN_INTSAVE_DATA`
267
* @see `tn_arch_sr_save_int_dis()`
268
*/
269
270
#define TN_INT_DIS_SAVE() TN_INTSAVE_VAR = tn_arch_sr_save_int_dis()
271
#define TN_INT_RESTORE() _TN_CORTEX_INTSAVE_CHECK(); \
272
tn_arch_sr_restore(TN_INTSAVE_VAR)
273
274
/**
275
* The same as `TN_INT_DIS_SAVE()` but for using in ISR.
276
*
277
* Uses `#TN_INTSAVE_DATA_INT` as a temporary storage.
278
*
279
* @see `#TN_INTSAVE_DATA_INT`
280
*/
281
#define TN_INT_IDIS_SAVE() TN_INT_DIS_SAVE()
282
283
/**
284
* The same as `TN_INT_RESTORE()` but for using in ISR.
285
*
286
* Uses `#TN_INTSAVE_DATA_INT` as a temporary storage.
287
*
288
* @see `#TN_INTSAVE_DATA_INT`
289
*/
290
#define TN_INT_IRESTORE() TN_INT_RESTORE()
291
292
/**
293
* Returns nonzero if interrupts are disabled, zero otherwise.
294
*/
295
#define TN_IS_INT_DISABLED() (_tn_arch_is_int_disabled())
296
297
/**
298
* Pend context switch from interrupt.
299
*/
300
#define _TN_CONTEXT_SWITCH_IPEND_IF_NEEDED() \
301
_tn_context_switch_pend_if_needed()
302
303
/**
304
* Converts size in bytes to size in `#TN_UWord`.
305
* For 32-bit platforms, we should shift it by 2 bit to the right;
306
* for 16-bit platforms, we should shift it by 1 bit to the right.
307
*/
308
#define _TN_SIZE_BYTES_TO_UWORDS(size_in_bytes) ((size_in_bytes) >> 2)
309
310
#if defined(__TN_COMPILER_ARMCC__)
311
# if TN_FORCED_INLINE
312
# define _TN_INLINE __forceinline
313
# else
314
# define _TN_INLINE __inline
315
# endif
316
# define _TN_STATIC_INLINE static _TN_INLINE
317
# define _TN_VOLATILE_WORKAROUND
/* nothing */
318
#elif defined(__TN_COMPILER_GCC__) || defined(__TN_COMPILER_CLANG__)
319
# if TN_FORCED_INLINE
320
# define _TN_INLINE inline __attribute__ ((always_inline))
321
# else
322
# define _TN_INLINE inline
323
# endif
324
# define _TN_STATIC_INLINE static _TN_INLINE
325
# define _TN_VOLATILE_WORKAROUND
/* nothing */
326
#elif defined(__TN_COMPILER_IAR__)
327
# if TN_FORCED_INLINE
328
# define _TN_INLINE _Pragma("inline=forced")
329
# else
330
# define _TN_INLINE inline
331
# endif
332
/*
333
* NOTE: for IAR, `_TN_INLINE` should go before `static`, because
334
* when we use forced inline by _Pragma, and `static` is before _Pragma,
335
* then IAR compiler generates a warning that pragma should immediately
336
* precede the declaration.
337
*/
338
# define _TN_STATIC_INLINE _TN_INLINE static
339
# define _TN_VOLATILE_WORKAROUND volatile
340
#else
341
# error unknown Cortex compiler
342
#endif
343
344
#define _TN_ARCH_STACK_PT_TYPE _TN_ARCH_STACK_PT_TYPE__FULL
345
#define _TN_ARCH_STACK_DIR _TN_ARCH_STACK_DIR__DESC
346
347
#endif //-- DOXYGEN_SHOULD_SKIP_THIS
348
349
350
351
352
353
354
355
356
357
358
359
#ifdef __cplusplus
360
}
/* extern "C" */
361
#endif
362
363
#endif // _TN_ARCH_CORTEX_M_H
364
TN_UWord
unsigned int TN_UWord
Unsigned integer type whose size is equal to the size of CPU register.
Definition:
tn_arch_example.h:105
TN_UIntPtr
unsigned int TN_UIntPtr
Unsigned integer type that is able to store pointers.
Definition:
tn_arch_example.h:112
Generated on Sat Dec 28 2024 20:20:49 for TNeo by
1.8.17