diff options
Diffstat (limited to 'lib/chibios/os/common/ports')
53 files changed, 9652 insertions, 0 deletions
diff --git a/lib/chibios/os/common/ports/ARM/chcore.c b/lib/chibios/os/common/ports/ARM/chcore.c new file mode 100644 index 000000000..4375ba26b --- /dev/null +++ b/lib/chibios/os/common/ports/ARM/chcore.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file ARM/chcore.c | ||
22 | * @brief ARM port code. | ||
23 | * | ||
24 | * @addtogroup ARM_CORE | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #include "ch.h" | ||
29 | |||
30 | /*===========================================================================*/ | ||
31 | /* Module local definitions. */ | ||
32 | /*===========================================================================*/ | ||
33 | |||
34 | /*===========================================================================*/ | ||
35 | /* Module exported variables. */ | ||
36 | /*===========================================================================*/ | ||
37 | |||
38 | /*===========================================================================*/ | ||
39 | /* Module local types. */ | ||
40 | /*===========================================================================*/ | ||
41 | |||
42 | /*===========================================================================*/ | ||
43 | /* Module local variables. */ | ||
44 | /*===========================================================================*/ | ||
45 | |||
46 | /*===========================================================================*/ | ||
47 | /* Module local functions. */ | ||
48 | /*===========================================================================*/ | ||
49 | |||
50 | /*===========================================================================*/ | ||
51 | /* Module exported functions. */ | ||
52 | /*===========================================================================*/ | ||
53 | |||
54 | /** @} */ | ||
diff --git a/lib/chibios/os/common/ports/ARM/chcore.h b/lib/chibios/os/common/ports/ARM/chcore.h new file mode 100644 index 000000000..7518b5c68 --- /dev/null +++ b/lib/chibios/os/common/ports/ARM/chcore.h | |||
@@ -0,0 +1,607 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file ARM/chcore.h | ||
22 | * @brief ARM7/9 architecture port macros and structures. | ||
23 | * | ||
24 | * @addtogroup ARM_CORE | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #ifndef CHCORE_H | ||
29 | #define CHCORE_H | ||
30 | |||
31 | /*===========================================================================*/ | ||
32 | /* Module constants. */ | ||
33 | /*===========================================================================*/ | ||
34 | |||
35 | /** | ||
36 | * @name Port Capabilities and Constants | ||
37 | * @{ | ||
38 | */ | ||
39 | /** | ||
40 | * @brief This port supports a realtime counter. | ||
41 | */ | ||
42 | #define PORT_SUPPORTS_RT TRUE | ||
43 | |||
44 | /** | ||
45 | * @brief Natural alignment constant. | ||
46 | * @note It is the minimum alignment for pointer-size variables. | ||
47 | */ | ||
48 | #define PORT_NATURAL_ALIGN sizeof (void *) | ||
49 | |||
50 | /** | ||
51 | * @brief Stack alignment constant. | ||
52 | * @note It is the alignment required for the stack pointer. | ||
53 | */ | ||
54 | #define PORT_STACK_ALIGN sizeof (stkalign_t) | ||
55 | |||
56 | /** | ||
57 | * @brief Working Areas alignment constant. | ||
58 | * @note It is the alignment to be enforced for thread working areas. | ||
59 | */ | ||
60 | #define PORT_WORKING_AREA_ALIGN sizeof (stkalign_t) | ||
61 | /** @} */ | ||
62 | |||
63 | /** | ||
64 | * @name Architecture and Compiler | ||
65 | * @{ | ||
66 | */ | ||
67 | /** | ||
68 | * @brief Macro defining a generic ARM architecture. | ||
69 | */ | ||
70 | #define PORT_ARCHITECTURE_ARM | ||
71 | |||
72 | /* The following code is not processed when the file is included from an | ||
73 | asm module because those intrinsic macros are not necessarily defined | ||
74 | by the assembler too.*/ | ||
75 | #if !defined(_FROM_ASM_) | ||
76 | |||
77 | /** | ||
78 | * @brief Compiler name and version. | ||
79 | */ | ||
80 | #if defined(__GNUC__) || defined(__DOXYGEN__) | ||
81 | #define PORT_COMPILER_NAME "GCC " __VERSION__ | ||
82 | |||
83 | #else | ||
84 | #error "unsupported compiler" | ||
85 | #endif | ||
86 | |||
87 | #endif /* !defined(_FROM_ASM_) */ | ||
88 | /** @} */ | ||
89 | |||
90 | /** | ||
91 | * @name ARM variants | ||
92 | * @{ | ||
93 | */ | ||
94 | #define ARM_CORE_ARM7TDMI 7 | ||
95 | #define ARM_CORE_ARM9 9 | ||
96 | #define ARM_CORE_CORTEX_A5 105 | ||
97 | #define ARM_CORE_CORTEX_A7 107 | ||
98 | #define ARM_CORE_CORTEX_A8 108 | ||
99 | #define ARM_CORE_CORTEX_A9 109 | ||
100 | /** @} */ | ||
101 | |||
102 | /* Inclusion of the ARM implementation specific parameters.*/ | ||
103 | #include "armparams.h" | ||
104 | |||
105 | /*===========================================================================*/ | ||
106 | /* Module pre-compile time settings. */ | ||
107 | /*===========================================================================*/ | ||
108 | |||
109 | /** | ||
110 | * @brief Enables an alternative timer implementation. | ||
111 | * @details Usually the port uses a timer interface defined in the file | ||
112 | * @p chcore_timer.h, if this option is enabled then the file | ||
113 | * @p chcore_timer_alt.h is included instead. | ||
114 | */ | ||
115 | #if !defined(PORT_USE_ALT_TIMER) | ||
116 | #define PORT_USE_ALT_TIMER FALSE | ||
117 | #endif | ||
118 | |||
119 | /** | ||
120 | * @brief Stack size for the system idle thread. | ||
121 | * @details This size depends on the idle thread implementation, usually | ||
122 | * the idle thread should take no more space than those reserved | ||
123 | * by @p PORT_INT_REQUIRED_STACK. | ||
124 | * @note In this port it is set to 32 because the idle thread does have | ||
125 | * a stack frame when compiling without optimizations. You may | ||
126 | * reduce this value to zero when compiling with optimizations. | ||
127 | */ | ||
128 | #if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__) | ||
129 | #define PORT_IDLE_THREAD_STACK_SIZE 32 | ||
130 | #endif | ||
131 | |||
132 | /** | ||
133 | * @brief Per-thread stack overhead for interrupts servicing. | ||
134 | * @details This constant is used in the calculation of the correct working | ||
135 | * area size. | ||
136 | */ | ||
137 | #if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__) | ||
138 | #define PORT_INT_REQUIRED_STACK 32 | ||
139 | #endif | ||
140 | |||
141 | /** | ||
142 | * @brief If enabled allows the idle thread to enter a low power mode. | ||
143 | */ | ||
144 | #ifndef ARM_ENABLE_WFI_IDLE | ||
145 | #define ARM_ENABLE_WFI_IDLE FALSE | ||
146 | #endif | ||
147 | |||
148 | /*===========================================================================*/ | ||
149 | /* Derived constants and error checks. */ | ||
150 | /*===========================================================================*/ | ||
151 | |||
152 | #if ARM_CORE < 100 | ||
153 | #define ARM_CORE_CLASSIC 1 | ||
154 | #define ARM_CORE_CORTEX_A 0 | ||
155 | #elif ARM_CORE < 200 | ||
156 | #define ARM_CORE_CLASSIC 0 | ||
157 | #define ARM_CORE_CORTEX_A 1 | ||
158 | #else | ||
159 | #endif | ||
160 | |||
161 | /* The following code is not processed when the file is included from an | ||
162 | asm module.*/ | ||
163 | #if !defined(_FROM_ASM_) | ||
164 | |||
165 | /* ARM core check.*/ | ||
166 | #if (ARM_CORE == ARM_CORE_ARM7TDMI) || defined(__DOXYGEN__) | ||
167 | #define PORT_ARCHITECTURE_ARM_ARM7 | ||
168 | #define PORT_ARCHITECTURE_NAME "ARMv4T" | ||
169 | #define PORT_CORE_VARIANT_NAME "ARM7" | ||
170 | |||
171 | #elif ARM_CORE == ARM_CORE_ARM9 | ||
172 | #define PORT_ARCHITECTURE_ARM_ARM9 | ||
173 | #define PORT_ARCHITECTURE_NAME "ARMv5T" | ||
174 | #define PORT_CORE_VARIANT_NAME "ARM9" | ||
175 | |||
176 | #elif ARM_CORE == ARM_CORE_CORTEX_A5 | ||
177 | #define PORT_ARCHITECTURE_ARM_CORTEXA5 | ||
178 | #define PORT_ARCHITECTURE_NAME "ARMv7" | ||
179 | #define PORT_CORE_VARIANT_NAME "ARM Cortex-A5" | ||
180 | |||
181 | #elif ARM_CORE == ARM_CORE_CORTEX_A7 | ||
182 | #define PORT_ARCHITECTURE_ARM_CORTEXA5 | ||
183 | #define PORT_ARCHITECTURE_NAME "ARMv7" | ||
184 | #define PORT_CORE_VARIANT_NAME "ARM Cortex-A7" | ||
185 | |||
186 | #elif ARM_CORE == ARM_CORE_CORTEX_A8 | ||
187 | #define PORT_ARCHITECTURE_ARM_CORTEXA8 | ||
188 | #define PORT_ARCHITECTURE_NAME "ARMv7" | ||
189 | #define PORT_CORE_VARIANT_NAME "ARM Cortex-A8" | ||
190 | |||
191 | #elif ARM_CORE == ARM_CORE_CORTEX_A9 | ||
192 | #define PORT_ARCHITECTURE_ARM_CORTEXA9 | ||
193 | #define PORT_ARCHITECTURE_NAME "ARMv7" | ||
194 | #define PORT_CORE_VARIANT_NAME "ARM Cortex-A9" | ||
195 | |||
196 | #else | ||
197 | #error "unknown or unsupported ARM core" | ||
198 | #endif | ||
199 | |||
200 | #if defined(THUMB_PRESENT) | ||
201 | #if defined(THUMB_NO_INTERWORKING) | ||
202 | #define PORT_INFO "Pure THUMB mode" | ||
203 | #else | ||
204 | #define PORT_INFO "Interworking mode" | ||
205 | #endif | ||
206 | #else | ||
207 | #define PORT_INFO "Pure ARM mode" | ||
208 | #endif | ||
209 | |||
210 | #endif /* !defined(_FROM_ASM_) */ | ||
211 | |||
212 | /*===========================================================================*/ | ||
213 | /* Module data structures and types. */ | ||
214 | /*===========================================================================*/ | ||
215 | |||
216 | /* The following code is not processed when the file is included from an | ||
217 | asm module.*/ | ||
218 | #if !defined(_FROM_ASM_) | ||
219 | |||
220 | /** | ||
221 | * @brief Type of stack and memory alignment enforcement. | ||
222 | * @note In this architecture the stack alignment is enforced to 64 bits. | ||
223 | */ | ||
224 | typedef uint64_t stkalign_t; | ||
225 | |||
226 | /** | ||
227 | * @brief Generic ARM register. | ||
228 | */ | ||
229 | typedef void *regarm_t; | ||
230 | |||
231 | /** | ||
232 | * @brief Interrupt saved context. | ||
233 | * @details This structure represents the stack frame saved during an | ||
234 | * interrupt handler. | ||
235 | */ | ||
236 | struct port_extctx { | ||
237 | regarm_t spsr_irq; | ||
238 | regarm_t lr_irq; | ||
239 | regarm_t r0; | ||
240 | regarm_t r1; | ||
241 | regarm_t r2; | ||
242 | regarm_t r3; | ||
243 | regarm_t r12; | ||
244 | regarm_t lr_usr; | ||
245 | }; | ||
246 | |||
247 | /** | ||
248 | * @brief System saved context. | ||
249 | * @details This structure represents the inner stack frame during a context | ||
250 | * switch. | ||
251 | */ | ||
252 | struct port_intctx { | ||
253 | regarm_t r4; | ||
254 | regarm_t r5; | ||
255 | regarm_t r6; | ||
256 | regarm_t r7; | ||
257 | regarm_t r8; | ||
258 | regarm_t r9; | ||
259 | regarm_t r10; | ||
260 | regarm_t r11; | ||
261 | regarm_t lr; | ||
262 | }; | ||
263 | |||
264 | /** | ||
265 | * @brief Platform dependent part of the @p thread_t structure. | ||
266 | * @details In this port the structure just holds a pointer to the | ||
267 | * @p port_intctx structure representing the stack pointer | ||
268 | * at context switch time. | ||
269 | */ | ||
270 | struct port_context { | ||
271 | struct port_intctx *sp; | ||
272 | }; | ||
273 | |||
274 | /*===========================================================================*/ | ||
275 | /* Module macros. */ | ||
276 | /*===========================================================================*/ | ||
277 | |||
278 | /** | ||
279 | * @brief Platform dependent part of the @p chThdCreateI() API. | ||
280 | * @details This code usually setup the context switching frame represented | ||
281 | * by an @p port_intctx structure. | ||
282 | */ | ||
283 | #define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \ | ||
284 | (tp)->ctx.sp = (struct port_intctx *)((uint8_t *)(wtop) - \ | ||
285 | sizeof (struct port_intctx)); \ | ||
286 | (tp)->ctx.sp->r4 = (regarm_t)(pf); \ | ||
287 | (tp)->ctx.sp->r5 = (regarm_t)(arg); \ | ||
288 | (tp)->ctx.sp->lr = (regarm_t)(_port_thread_start); \ | ||
289 | } | ||
290 | |||
291 | /** | ||
292 | * @brief Computes the thread working area global size. | ||
293 | * @note There is no need to perform alignments in this macro. | ||
294 | */ | ||
295 | #define PORT_WA_SIZE(n) (sizeof(struct port_intctx) + \ | ||
296 | sizeof(struct port_extctx) + \ | ||
297 | ((size_t)(n)) + ((size_t)(PORT_INT_REQUIRED_STACK))) | ||
298 | |||
299 | /** | ||
300 | * @brief Static working area allocation. | ||
301 | * @details This macro is used to allocate a static thread working area | ||
302 | * aligned as both position and size. | ||
303 | * | ||
304 | * @param[in] s the name to be assigned to the stack array | ||
305 | * @param[in] n the stack size to be assigned to the thread | ||
306 | */ | ||
307 | #define PORT_WORKING_AREA(s, n) \ | ||
308 | stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)] | ||
309 | |||
310 | /** | ||
311 | * @brief Priority level verification macro. | ||
312 | * @todo Add the required parameters to armparams.h. | ||
313 | */ | ||
314 | #define PORT_IRQ_IS_VALID_PRIORITY(n) false | ||
315 | |||
316 | /** | ||
317 | * @brief IRQ prologue code. | ||
318 | * @details This macro must be inserted at the start of all IRQ handlers | ||
319 | * enabled to invoke system APIs. | ||
320 | */ | ||
321 | #define PORT_IRQ_PROLOGUE() | ||
322 | |||
323 | /** | ||
324 | * @brief IRQ epilogue code. | ||
325 | * @details This macro must be inserted at the end of all IRQ handlers | ||
326 | * enabled to invoke system APIs. | ||
327 | */ | ||
328 | #define PORT_IRQ_EPILOGUE() return chSchIsPreemptionRequired() | ||
329 | |||
330 | /** | ||
331 | * @brief IRQ handler function declaration. | ||
332 | * @note @p id can be a function name or a vector number depending on the | ||
333 | * port implementation. | ||
334 | */ | ||
335 | #ifdef __cplusplus | ||
336 | #define PORT_IRQ_HANDLER(id) extern "C" bool id(void) | ||
337 | #else | ||
338 | #define PORT_IRQ_HANDLER(id) bool id(void) | ||
339 | #endif | ||
340 | |||
341 | /** | ||
342 | * @brief Fast IRQ handler function declaration. | ||
343 | * @note @p id can be a function name or a vector number depending on the | ||
344 | * port implementation. | ||
345 | */ | ||
346 | #define PORT_FAST_IRQ_HANDLER(id) \ | ||
347 | __attribute__((interrupt("FIQ"))) void id(void) | ||
348 | |||
349 | /** | ||
350 | * @brief Performs a context switch between two threads. | ||
351 | * @details This is the most critical code in any port, this function | ||
352 | * is responsible for the context switch between 2 threads. | ||
353 | * @note The implementation of this code affects <b>directly</b> the context | ||
354 | * switch performance so optimize here as much as you can. | ||
355 | * @note Implemented as inlined code for performance reasons. | ||
356 | * | ||
357 | * @param[in] ntp the thread to be switched in | ||
358 | * @param[in] otp the thread to be switched out | ||
359 | */ | ||
360 | #if defined(THUMB) | ||
361 | |||
362 | #if CH_DBG_ENABLE_STACK_CHECK == TRUE | ||
363 | #define port_switch(ntp, otp) { \ | ||
364 | register struct port_intctx *r13 asm ("r13"); \ | ||
365 | if ((stkalign_t *)(r13 - 1) < otp->wabase) \ | ||
366 | chSysHalt("stack overflow"); \ | ||
367 | _port_switch_thumb(ntp, otp); \ | ||
368 | } | ||
369 | #else | ||
370 | #define port_switch(ntp, otp) _port_switch_thumb(ntp, otp) | ||
371 | #endif | ||
372 | |||
373 | #else /* !defined(THUMB) */ | ||
374 | |||
375 | #if CH_DBG_ENABLE_STACK_CHECK == TRUE | ||
376 | #define port_switch(ntp, otp) { \ | ||
377 | register struct port_intctx *r13 asm ("r13"); \ | ||
378 | if ((stkalign_t *)(r13 - 1) < otp->wabase) \ | ||
379 | chSysHalt("stack overflow"); \ | ||
380 | _port_switch_arm(ntp, otp); \ | ||
381 | } | ||
382 | #else | ||
383 | #define port_switch(ntp, otp) _port_switch_arm(ntp, otp) | ||
384 | #endif | ||
385 | |||
386 | #endif /* !defined(THUMB) */ | ||
387 | |||
388 | /*===========================================================================*/ | ||
389 | /* External declarations. */ | ||
390 | /*===========================================================================*/ | ||
391 | |||
392 | #ifdef __cplusplus | ||
393 | extern "C" { | ||
394 | #endif | ||
395 | #if defined(THUMB_PRESENT) | ||
396 | syssts_t _port_get_cpsr(void); | ||
397 | #endif | ||
398 | #if defined(THUMB) | ||
399 | void _port_switch_thumb(thread_t *ntp, thread_t *otp); | ||
400 | #else | ||
401 | void _port_switch_arm(thread_t *ntp, thread_t *otp); | ||
402 | #endif | ||
403 | void _port_thread_start(void); | ||
404 | #ifdef __cplusplus | ||
405 | } | ||
406 | #endif | ||
407 | |||
408 | /*===========================================================================*/ | ||
409 | /* Module inline functions. */ | ||
410 | /*===========================================================================*/ | ||
411 | |||
412 | /** | ||
413 | * @brief Port-related initialization code. | ||
414 | */ | ||
415 | static inline void port_init(void) { | ||
416 | |||
417 | } | ||
418 | |||
419 | /** | ||
420 | * @brief Returns a word encoding the current interrupts status. | ||
421 | * | ||
422 | * @return The interrupts status. | ||
423 | */ | ||
424 | static inline syssts_t port_get_irq_status(void) { | ||
425 | syssts_t sts; | ||
426 | |||
427 | #if defined(THUMB) | ||
428 | sts = _port_get_cpsr(); | ||
429 | #else | ||
430 | __asm volatile ("mrs %[p0], CPSR" : [p0] "=r" (sts) :); | ||
431 | #endif | ||
432 | /*lint -save -e530 [9.1] Asm instruction not seen by lint.*/ | ||
433 | return sts; | ||
434 | /*lint -restore*/ | ||
435 | } | ||
436 | |||
437 | /** | ||
438 | * @brief Checks the interrupt status. | ||
439 | * | ||
440 | * @param[in] sts the interrupt status word | ||
441 | * | ||
442 | * @return The interrupt status. | ||
443 | * @retval false the word specified a disabled interrupts status. | ||
444 | * @retval true the word specified an enabled interrupts status. | ||
445 | */ | ||
446 | static inline bool port_irq_enabled(syssts_t sts) { | ||
447 | |||
448 | return (sts & (syssts_t)0x80) == (syssts_t)0; | ||
449 | } | ||
450 | |||
451 | /** | ||
452 | * @brief Determines the current execution context. | ||
453 | * | ||
454 | * @return The execution context. | ||
455 | * @retval false not running in ISR mode. | ||
456 | * @retval true running in ISR mode. | ||
457 | */ | ||
458 | static inline bool port_is_isr_context(void) { | ||
459 | syssts_t sts; | ||
460 | |||
461 | #if defined(THUMB) | ||
462 | sts = _port_get_cpsr(); | ||
463 | #else | ||
464 | __asm volatile ("mrs %[p0], CPSR" : [p0] "=r" (sts) :); | ||
465 | #endif | ||
466 | |||
467 | /*lint -save -e530 [9.1] Asm instruction not seen by lint.*/ | ||
468 | return (sts & (syssts_t)0x1F) == (syssts_t)0x12; | ||
469 | /*lint -restore*/ | ||
470 | } | ||
471 | |||
472 | /** | ||
473 | * @brief Kernel-lock action. | ||
474 | * @details In this port it disables the IRQ sources and keeps FIQ sources | ||
475 | * enabled. | ||
476 | */ | ||
477 | static inline void port_lock(void) { | ||
478 | |||
479 | #if defined(THUMB) | ||
480 | __asm volatile ("bl _port_lock_thumb" : : : "r3", "lr", "memory"); | ||
481 | #else | ||
482 | __asm volatile ("msr CPSR_c, #0x9F" : : : "memory"); | ||
483 | #endif | ||
484 | } | ||
485 | |||
486 | /** | ||
487 | * @brief Kernel-unlock action. | ||
488 | * @details In this port it enables both the IRQ and FIQ sources. | ||
489 | */ | ||
490 | static inline void port_unlock(void) { | ||
491 | |||
492 | #if defined(THUMB) | ||
493 | __asm volatile ("bl _port_unlock_thumb" : : : "r3", "lr", "memory"); | ||
494 | #else | ||
495 | __asm volatile ("msr CPSR_c, #0x1F" : : : "memory"); | ||
496 | #endif | ||
497 | } | ||
498 | |||
499 | /** | ||
500 | * @brief Kernel-lock action from an interrupt handler. | ||
501 | * @note Empty in this port. | ||
502 | */ | ||
503 | static inline void port_lock_from_isr(void) { | ||
504 | |||
505 | } | ||
506 | |||
507 | /** | ||
508 | * @brief Kernel-unlock action from an interrupt handler. | ||
509 | * @note Empty in this port. | ||
510 | */ | ||
511 | static inline void port_unlock_from_isr(void) { | ||
512 | |||
513 | } | ||
514 | |||
515 | /** | ||
516 | * @brief Disables all the interrupt sources. | ||
517 | * @details In this port it disables both the IRQ and FIQ sources. | ||
518 | * @note Implements a workaround for spurious interrupts taken from the NXP | ||
519 | * LPC214x datasheet. | ||
520 | */ | ||
521 | static inline void port_disable(void) { | ||
522 | |||
523 | #if defined(THUMB) | ||
524 | __asm volatile ("bl _port_disable_thumb" : : : "r3", "lr", "memory"); | ||
525 | #else | ||
526 | __asm volatile ("mrs r3, CPSR \n\t" | ||
527 | "orr r3, #0x80 \n\t" | ||
528 | "msr CPSR_c, r3 \n\t" | ||
529 | "orr r3, #0x40 \n\t" | ||
530 | "msr CPSR_c, r3" : : : "r3", "memory"); | ||
531 | #endif | ||
532 | } | ||
533 | |||
534 | /** | ||
535 | * @brief Disables the interrupt sources below kernel-level priority. | ||
536 | * @note Interrupt sources above kernel level remains enabled. | ||
537 | * @note In this port it disables the IRQ sources and enables the | ||
538 | * FIQ sources. | ||
539 | */ | ||
540 | static inline void port_suspend(void) { | ||
541 | |||
542 | #if defined(THUMB) | ||
543 | __asm volatile ("bl _port_suspend_thumb" : : : "r3", "lr", "memory"); | ||
544 | #else | ||
545 | __asm volatile ("msr CPSR_c, #0x9F" : : : "memory"); | ||
546 | #endif | ||
547 | } | ||
548 | |||
549 | /** | ||
550 | * @brief Enables all the interrupt sources. | ||
551 | * @note In this port it enables both the IRQ and FIQ sources. | ||
552 | */ | ||
553 | static inline void port_enable(void) { | ||
554 | |||
555 | #if defined(THUMB) | ||
556 | __asm volatile ("bl _port_enable_thumb" : : : "r3", "lr", "memory"); | ||
557 | #else | ||
558 | __asm volatile ("msr CPSR_c, #0x1F" : : : "memory"); | ||
559 | #endif | ||
560 | } | ||
561 | |||
562 | /** | ||
563 | * @brief Returns the current value of the realtime counter. | ||
564 | * | ||
565 | * @return The realtime counter value. | ||
566 | */ | ||
567 | static inline rtcnt_t port_rt_get_counter_value(void) { | ||
568 | |||
569 | #if ARM_CORE_CORTEX_A | ||
570 | rtcnt_t cyc; | ||
571 | |||
572 | __asm volatile("mrc p15, 0, %[p0], c9, c13, 0" : [p0] "=r" (cyc) :); | ||
573 | |||
574 | return cyc; | ||
575 | #else | ||
576 | return 0; | ||
577 | #endif | ||
578 | } | ||
579 | |||
580 | /** | ||
581 | * @brief Enters an architecture-dependent IRQ-waiting mode. | ||
582 | * @details The function is meant to return when an interrupt becomes pending. | ||
583 | * The simplest implementation is an empty function or macro but this | ||
584 | * would not take advantage of architecture-specific power saving | ||
585 | * modes. | ||
586 | * @note Implemented as an inlined @p WFI instruction. | ||
587 | */ | ||
588 | static inline void port_wait_for_interrupt(void) { | ||
589 | |||
590 | #if ARM_ENABLE_WFI_IDLE == TRUE | ||
591 | ARM_WFI_IMPL; | ||
592 | #endif | ||
593 | } | ||
594 | |||
595 | #if CH_CFG_ST_TIMEDELTA > 0 | ||
596 | #if PORT_USE_ALT_TIMER == FALSE | ||
597 | #include "chcore_timer.h" | ||
598 | #else /* PORT_USE_ALT_TIMER */ | ||
599 | #include "chcore_timer_alt.h" | ||
600 | #endif /* PORT_USE_ALT_TIMER */ | ||
601 | #endif /* CH_CFG_ST_TIMEDELTA > 0 */ | ||
602 | |||
603 | #endif /* !defined(_FROM_ASM_) */ | ||
604 | |||
605 | #endif /* CHCORE_H */ | ||
606 | |||
607 | /** @} */ | ||
diff --git a/lib/chibios/os/common/ports/ARM/chcore_timer.h b/lib/chibios/os/common/ports/ARM/chcore_timer.h new file mode 100644 index 000000000..aad1cd1e8 --- /dev/null +++ b/lib/chibios/os/common/ports/ARM/chcore_timer.h | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file chcore_timer.h | ||
22 | * @brief System timer header file. | ||
23 | * | ||
24 | * @addtogroup ARM_TIMER | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #ifndef CHCORE_TIMER_H | ||
29 | #define CHCORE_TIMER_H | ||
30 | |||
31 | /*===========================================================================*/ | ||
32 | /* Module constants. */ | ||
33 | /*===========================================================================*/ | ||
34 | |||
35 | /*===========================================================================*/ | ||
36 | /* Module pre-compile time settings. */ | ||
37 | /*===========================================================================*/ | ||
38 | |||
39 | /*===========================================================================*/ | ||
40 | /* Derived constants and error checks. */ | ||
41 | /*===========================================================================*/ | ||
42 | |||
43 | /*===========================================================================*/ | ||
44 | /* Module data structures and types. */ | ||
45 | /*===========================================================================*/ | ||
46 | |||
47 | /*===========================================================================*/ | ||
48 | /* Module macros. */ | ||
49 | /*===========================================================================*/ | ||
50 | |||
51 | /*===========================================================================*/ | ||
52 | /* External declarations. */ | ||
53 | /*===========================================================================*/ | ||
54 | |||
55 | /*===========================================================================*/ | ||
56 | /* Module inline functions. */ | ||
57 | /*===========================================================================*/ | ||
58 | |||
59 | /** | ||
60 | * @brief Starts the alarm. | ||
61 | * @note Makes sure that no spurious alarms are triggered after | ||
62 | * this call. | ||
63 | * | ||
64 | * @param[in] time the time to be set for the first alarm | ||
65 | * | ||
66 | * @notapi | ||
67 | */ | ||
68 | static inline void port_timer_start_alarm(systime_t time) { | ||
69 | void stStartAlarm(systime_t time); | ||
70 | |||
71 | stStartAlarm(time); | ||
72 | } | ||
73 | |||
74 | /** | ||
75 | * @brief Stops the alarm interrupt. | ||
76 | * | ||
77 | * @notapi | ||
78 | */ | ||
79 | static inline void port_timer_stop_alarm(void) { | ||
80 | void stStopAlarm(void); | ||
81 | |||
82 | stStopAlarm(); | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * @brief Sets the alarm time. | ||
87 | * | ||
88 | * @param[in] time the time to be set for the next alarm | ||
89 | * | ||
90 | * @notapi | ||
91 | */ | ||
92 | static inline void port_timer_set_alarm(systime_t time) { | ||
93 | void stSetAlarm(systime_t time); | ||
94 | |||
95 | stSetAlarm(time); | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * @brief Returns the system time. | ||
100 | * | ||
101 | * @return The system time. | ||
102 | * | ||
103 | * @notapi | ||
104 | */ | ||
105 | static inline systime_t port_timer_get_time(void) { | ||
106 | systime_t stGetCounter(void); | ||
107 | |||
108 | return stGetCounter(); | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * @brief Returns the current alarm time. | ||
113 | * | ||
114 | * @return The currently set alarm time. | ||
115 | * | ||
116 | * @notapi | ||
117 | */ | ||
118 | static inline systime_t port_timer_get_alarm(void) { | ||
119 | systime_t stGetAlarm(void); | ||
120 | |||
121 | return stGetAlarm(); | ||
122 | } | ||
123 | |||
124 | #endif /* CHCORE_TIMER_H */ | ||
125 | |||
126 | /** @} */ | ||
diff --git a/lib/chibios/os/common/ports/ARM/compilers/GCC/chcoreasm.S b/lib/chibios/os/common/ports/ARM/compilers/GCC/chcoreasm.S new file mode 100644 index 000000000..5904d8ab3 --- /dev/null +++ b/lib/chibios/os/common/ports/ARM/compilers/GCC/chcoreasm.S | |||
@@ -0,0 +1,167 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file ARM/compilers/GCC/chcoreasm.S | ||
22 | * @brief ARM architecture port low level code. | ||
23 | * | ||
24 | * @addtogroup ARM_CORE | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #define _FROM_ASM_ | ||
29 | #include "chlicense.h" | ||
30 | #include "chconf.h" | ||
31 | #include "armparams.h" | ||
32 | |||
33 | #define FALSE 0 | ||
34 | #define TRUE 1 | ||
35 | |||
36 | #if !defined(__DOXYGEN__) | ||
37 | |||
38 | /* | ||
39 | * RTOS-specific context offset. | ||
40 | */ | ||
41 | #if defined(_CHIBIOS_RT_CONF_) | ||
42 | #define CONTEXT_OFFSET 12 | ||
43 | #elif defined(_CHIBIOS_NIL_CONF_) | ||
44 | #define CONTEXT_OFFSET 0 | ||
45 | #else | ||
46 | #error "invalid chconf.h" | ||
47 | #endif | ||
48 | |||
49 | .set MODE_USR, 0x10 | ||
50 | .set MODE_FIQ, 0x11 | ||
51 | .set MODE_IRQ, 0x12 | ||
52 | .set MODE_SVC, 0x13 | ||
53 | .set MODE_ABT, 0x17 | ||
54 | .set MODE_UND, 0x1B | ||
55 | .set MODE_SYS, 0x1F | ||
56 | |||
57 | .equ I_BIT, 0x80 | ||
58 | .equ F_BIT, 0x40 | ||
59 | |||
60 | .text | ||
61 | |||
62 | |||
63 | .balign 16 | ||
64 | |||
65 | .code 32 | ||
66 | .global _port_switch_arm | ||
67 | _port_switch_arm: | ||
68 | stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr} | ||
69 | str sp, [r1, #12] | ||
70 | ldr sp, [r0, #12] | ||
71 | ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc} | ||
72 | |||
73 | /* | ||
74 | * Common IRQ code. It expects a macro ARM_IRQ_VECTOR_REG with the address | ||
75 | * of a register holding the address of the ISR to be invoked, the ISR | ||
76 | * then returns in the common epilogue code where the context switch will | ||
77 | * be performed, if required. | ||
78 | * System stack frame structure after a context switch in the | ||
79 | * interrupt handler: | ||
80 | * | ||
81 | * High +------------+ | ||
82 | * | LR_USR | -+ | ||
83 | * | r12 | | | ||
84 | * | r3 | | | ||
85 | * | r2 | | External context: IRQ handler frame | ||
86 | * | r1 | | | ||
87 | * | r0 | | | ||
88 | * | LR_IRQ | | (user code return address) | ||
89 | * | PSR_USR | -+ (user code status) | ||
90 | * | .... | <- chSchDoReschedule() stack frame, optimize it for space | ||
91 | * | LR | -+ (system code return address) | ||
92 | * | r11 | | | ||
93 | * | r10 | | | ||
94 | * | r9 | | | ||
95 | * | r8 | | Internal context: chSysSwitch() frame | ||
96 | * | r7 | | | ||
97 | * | r6 | | | ||
98 | * | r5 | | | ||
99 | * SP-> | r4 | -+ | ||
100 | * Low +------------+ | ||
101 | */ | ||
102 | .balign 16 | ||
103 | .code 32 | ||
104 | .global Irq_Handler | ||
105 | Irq_Handler: | ||
106 | stmfd sp!, {r0-r3, r12, lr} | ||
107 | ldr r0, =ARM_IRQ_VECTOR_REG | ||
108 | ldr r0, [r0] | ||
109 | ldr lr, =_irq_ret_arm // ISR return point. | ||
110 | bx r0 // Calling the ISR. | ||
111 | _irq_ret_arm: | ||
112 | cmp r0, #0 | ||
113 | ldmfd sp!, {r0-r3, r12, lr} | ||
114 | subeqs pc, lr, #4 // No reschedule, returns. | ||
115 | |||
116 | // Now the frame is created in the system stack, the IRQ | ||
117 | // stack is empty. | ||
118 | msr CPSR_c, #MODE_SYS | I_BIT | ||
119 | stmfd sp!, {r0-r3, r12, lr} | ||
120 | msr CPSR_c, #MODE_IRQ | I_BIT | ||
121 | mrs r0, SPSR | ||
122 | mov r1, lr | ||
123 | msr CPSR_c, #MODE_SYS | I_BIT | ||
124 | stmfd sp!, {r0, r1} // Push R0=SPSR, R1=LR_IRQ. | ||
125 | |||
126 | // Context switch. | ||
127 | #if CH_DBG_SYSTEM_STATE_CHECK | ||
128 | bl _dbg_check_lock | ||
129 | #endif | ||
130 | bl chSchDoReschedule | ||
131 | #if CH_DBG_SYSTEM_STATE_CHECK | ||
132 | bl _dbg_check_unlock | ||
133 | #endif | ||
134 | |||
135 | // Re-establish the IRQ conditions again. | ||
136 | ldmfd sp!, {r0, r1} // Pop R0=SPSR, R1=LR_IRQ. | ||
137 | msr CPSR_c, #MODE_IRQ | I_BIT | ||
138 | msr SPSR_fsxc, r0 | ||
139 | mov lr, r1 | ||
140 | msr CPSR_c, #MODE_SYS | I_BIT | ||
141 | ldmfd sp!, {r0-r3, r12, lr} | ||
142 | msr CPSR_c, #MODE_IRQ | I_BIT | ||
143 | subs pc, lr, #4 | ||
144 | |||
145 | /* | ||
146 | * Threads trampoline code. | ||
147 | * NOTE: The threads always start in ARM mode and then switches to the | ||
148 | * thread-function mode. | ||
149 | */ | ||
150 | .balign 16 | ||
151 | .code 32 | ||
152 | .globl _port_thread_start | ||
153 | _port_thread_start: | ||
154 | #if CH_DBG_SYSTEM_STATE_CHECK | ||
155 | bl _dbg_check_unlock | ||
156 | #endif | ||
157 | msr CPSR_c, #MODE_SYS | ||
158 | mov r0, r5 | ||
159 | mov lr, pc | ||
160 | bx r4 | ||
161 | mov r0, #0 /* MSG_OK */ | ||
162 | bl chThdExit | ||
163 | _zombies: b _zombies | ||
164 | |||
165 | #endif /* !defined(__DOXYGEN__) */ | ||
166 | |||
167 | /** @} */ | ||
diff --git a/lib/chibios/os/common/ports/ARM/compilers/GCC/chtypes.h b/lib/chibios/os/common/ports/ARM/compilers/GCC/chtypes.h new file mode 100644 index 000000000..6aec31bf5 --- /dev/null +++ b/lib/chibios/os/common/ports/ARM/compilers/GCC/chtypes.h | |||
@@ -0,0 +1,115 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file ARM/compilers/GCC/chtypes.h | ||
22 | * @brief ARM port system types. | ||
23 | * | ||
24 | * @addtogroup ARM_GCC_CORE | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #ifndef CHTYPES_H | ||
29 | #define CHTYPES_H | ||
30 | |||
31 | #include <stddef.h> | ||
32 | #include <stdint.h> | ||
33 | #include <stdbool.h> | ||
34 | |||
35 | /** | ||
36 | * @name Common constants | ||
37 | */ | ||
38 | /** | ||
39 | * @brief Generic 'false' boolean constant. | ||
40 | */ | ||
41 | #if !defined(FALSE) || defined(__DOXYGEN__) | ||
42 | #define FALSE 0 | ||
43 | #endif | ||
44 | |||
45 | /** | ||
46 | * @brief Generic 'true' boolean constant. | ||
47 | */ | ||
48 | #if !defined(TRUE) || defined(__DOXYGEN__) | ||
49 | #define TRUE 1 | ||
50 | #endif | ||
51 | /** @} */ | ||
52 | |||
53 | /** | ||
54 | * @name Kernel types | ||
55 | * @{ | ||
56 | */ | ||
57 | typedef uint32_t rtcnt_t; /**< Realtime counter. */ | ||
58 | typedef uint64_t rttime_t; /**< Realtime accumulator. */ | ||
59 | typedef uint32_t syssts_t; /**< System status word. */ | ||
60 | typedef uint8_t tmode_t; /**< Thread flags. */ | ||
61 | typedef uint8_t tstate_t; /**< Thread state. */ | ||
62 | typedef uint8_t trefs_t; /**< Thread references counter. */ | ||
63 | typedef uint8_t tslices_t; /**< Thread time slices counter.*/ | ||
64 | typedef uint32_t tprio_t; /**< Thread priority. */ | ||
65 | typedef int32_t msg_t; /**< Inter-thread message. */ | ||
66 | typedef int32_t eventid_t; /**< Numeric event identifier. */ | ||
67 | typedef uint32_t eventmask_t; /**< Mask of event identifiers. */ | ||
68 | typedef uint32_t eventflags_t; /**< Mask of event flags. */ | ||
69 | typedef int32_t cnt_t; /**< Generic signed counter. */ | ||
70 | typedef uint32_t ucnt_t; /**< Generic unsigned counter. */ | ||
71 | /** @} */ | ||
72 | |||
73 | /** | ||
74 | * @brief ROM constant modifier. | ||
75 | * @note It is set to use the "const" keyword in this port. | ||
76 | */ | ||
77 | #define ROMCONST const | ||
78 | |||
79 | /** | ||
80 | * @brief Makes functions not inlineable. | ||
81 | * @note If the compiler does not support such attribute then some | ||
82 | * time-dependent services could be degraded. | ||
83 | */ | ||
84 | #define NOINLINE __attribute__((noinline)) | ||
85 | |||
86 | /** | ||
87 | * @brief Optimized thread function declaration macro. | ||
88 | */ | ||
89 | #define PORT_THD_FUNCTION(tname, arg) void tname(void *arg) | ||
90 | |||
91 | /** | ||
92 | * @brief Packed variable specifier. | ||
93 | */ | ||
94 | #define PACKED_VAR __attribute__((packed)) | ||
95 | |||
96 | /** | ||
97 | * @brief Memory alignment enforcement for variables. | ||
98 | */ | ||
99 | #define ALIGNED_VAR(n) __attribute__((aligned(n))) | ||
100 | |||
101 | /** | ||
102 | * @brief Size of a pointer. | ||
103 | * @note To be used where the sizeof operator cannot be used, preprocessor | ||
104 | * expressions for example. | ||
105 | */ | ||
106 | #define SIZEOF_PTR 4 | ||
107 | |||
108 | /** | ||
109 | * @brief True if alignment is low-high in current architecture. | ||
110 | */ | ||
111 | #define REVERSE_ORDER 1 | ||
112 | |||
113 | #endif /* CHTYPES_H */ | ||
114 | |||
115 | /** @} */ | ||
diff --git a/lib/chibios/os/common/ports/ARM/compilers/GCC/mk/port_generic.mk b/lib/chibios/os/common/ports/ARM/compilers/GCC/mk/port_generic.mk new file mode 100644 index 000000000..784632a58 --- /dev/null +++ b/lib/chibios/os/common/ports/ARM/compilers/GCC/mk/port_generic.mk | |||
@@ -0,0 +1,12 @@ | |||
1 | # List of the ChibiOS/RT ARM generic port files. | ||
2 | PORTSRC = ${CHIBIOS}/os/common/ports/ARM/chcore.c | ||
3 | |||
4 | PORTASM = $(CHIBIOS)/os/common/ports/ARM/compilers/GCC/chcoreasm.S | ||
5 | |||
6 | PORTINC = ${CHIBIOS}/os/common/ports/ARM \ | ||
7 | ${CHIBIOS}/os/common/ports/ARM/compilers/GCC | ||
8 | |||
9 | # Shared variables | ||
10 | ALLXASMSRC += $(PORTASM) | ||
11 | ALLCSRC += $(PORTSRC) | ||
12 | ALLINC += $(PORTINC) | ||
diff --git a/lib/chibios/os/common/ports/ARMCMx/chcore.c b/lib/chibios/os/common/ports/ARMCMx/chcore.c new file mode 100644 index 000000000..ba47579c0 --- /dev/null +++ b/lib/chibios/os/common/ports/ARMCMx/chcore.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file ARMCMx/chcore.c | ||
22 | * @brief ARM Cortex-Mx port code. | ||
23 | * | ||
24 | * @addtogroup ARMCMx_CORE | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #include "ch.h" | ||
29 | |||
30 | /*===========================================================================*/ | ||
31 | /* Module local definitions. */ | ||
32 | /*===========================================================================*/ | ||
33 | |||
34 | /*===========================================================================*/ | ||
35 | /* Module exported variables. */ | ||
36 | /*===========================================================================*/ | ||
37 | |||
38 | /*===========================================================================*/ | ||
39 | /* Module local types. */ | ||
40 | /*===========================================================================*/ | ||
41 | |||
42 | /*===========================================================================*/ | ||
43 | /* Module local variables. */ | ||
44 | /*===========================================================================*/ | ||
45 | |||
46 | /*===========================================================================*/ | ||
47 | /* Module local functions. */ | ||
48 | /*===========================================================================*/ | ||
49 | |||
50 | /*===========================================================================*/ | ||
51 | /* Module exported functions. */ | ||
52 | /*===========================================================================*/ | ||
53 | |||
54 | /** @} */ | ||
diff --git a/lib/chibios/os/common/ports/ARMCMx/chcore.h b/lib/chibios/os/common/ports/ARMCMx/chcore.h new file mode 100644 index 000000000..1db6f4164 --- /dev/null +++ b/lib/chibios/os/common/ports/ARMCMx/chcore.h | |||
@@ -0,0 +1,208 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file ARMCMx/chcore.h | ||
22 | * @brief ARM Cortex-Mx port macros and structures. | ||
23 | * | ||
24 | * @addtogroup ARMCMx_CORE | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #ifndef CHCORE_H | ||
29 | #define CHCORE_H | ||
30 | |||
31 | /*===========================================================================*/ | ||
32 | /* Module constants. */ | ||
33 | /*===========================================================================*/ | ||
34 | |||
35 | /** | ||
36 | * @name Architecture and Compiler | ||
37 | * @{ | ||
38 | */ | ||
39 | /** | ||
40 | * @brief Macro defining a generic ARM architecture. | ||
41 | */ | ||
42 | #define PORT_ARCHITECTURE_ARM | ||
43 | |||
44 | /* The following code is not processed when the file is included from an | ||
45 | asm module because those intrinsic macros are not necessarily defined | ||
46 | by the assembler too.*/ | ||
47 | #if !defined(_FROM_ASM_) | ||
48 | |||
49 | /** | ||
50 | * @brief Compiler name and version. | ||
51 | */ | ||
52 | #if defined(__GNUC__) || defined(__DOXYGEN__) | ||
53 | #define PORT_COMPILER_NAME "GCC " __VERSION__ | ||
54 | |||
55 | #elif defined(__ICCARM__) | ||
56 | #define PORT_COMPILER_NAME "IAR" | ||
57 | |||
58 | #elif defined(__CC_ARM) | ||
59 | #define PORT_COMPILER_NAME "RVCT" | ||
60 | |||
61 | #else | ||
62 | #error "unsupported compiler" | ||
63 | #endif | ||
64 | |||
65 | #endif /* !defined(_FROM_ASM_) */ | ||
66 | |||
67 | /** @} */ | ||
68 | |||
69 | /* Inclusion of the Cortex-Mx implementation specific parameters.*/ | ||
70 | #include "cmparams.h" | ||
71 | |||
72 | /*===========================================================================*/ | ||
73 | /* Module pre-compile time settings. */ | ||
74 | /*===========================================================================*/ | ||
75 | |||
76 | /** | ||
77 | * @brief Enables an alternative timer implementation. | ||
78 | * @details Usually the port uses a timer interface defined in the file | ||
79 | * @p chcore_timer.h, if this option is enabled then the file | ||
80 | * @p chcore_timer_alt.h is included instead. | ||
81 | */ | ||
82 | #if !defined(PORT_USE_ALT_TIMER) | ||
83 | #define PORT_USE_ALT_TIMER FALSE | ||
84 | #endif | ||
85 | |||
86 | /*===========================================================================*/ | ||
87 | /* Derived constants and error checks. */ | ||
88 | /*===========================================================================*/ | ||
89 | |||
90 | /*===========================================================================*/ | ||
91 | /* Module data structures and types. */ | ||
92 | /*===========================================================================*/ | ||
93 | |||
94 | /* The following code is not processed when the file is included from an | ||
95 | asm module.*/ | ||
96 | #if !defined(_FROM_ASM_) | ||
97 | |||
98 | /** | ||
99 | * @brief Type of stack and memory alignment enforcement. | ||
100 | * @note In this architecture the stack alignment is enforced to 64 bits, | ||
101 | * 32 bits alignment is supported by hardware but deprecated by ARM, | ||
102 | * the implementation choice is to not offer the option. | ||
103 | */ | ||
104 | typedef uint64_t stkalign_t; | ||
105 | |||
106 | /* The following declarations are there just for Doxygen documentation, the | ||
107 | real declarations are inside the sub-headers being specific for the | ||
108 | sub-architectures.*/ | ||
109 | #if defined(__DOXYGEN__) | ||
110 | /** | ||
111 | * @brief Interrupt saved context. | ||
112 | * @details This structure represents the stack frame saved during a | ||
113 | * preemption-capable interrupt handler. | ||
114 | * @note It is implemented to match the Cortex-Mx exception context. | ||
115 | */ | ||
116 | struct port_extctx {}; | ||
117 | |||
118 | /** | ||
119 | * @brief System saved context. | ||
120 | * @details This structure represents the inner stack frame during a context | ||
121 | * switch. | ||
122 | */ | ||
123 | struct port_intctx {}; | ||
124 | |||
125 | /** | ||
126 | * @brief Platform dependent part of the @p thread_t structure. | ||
127 | * @details In this port the structure just holds a pointer to the | ||
128 | * @p port_intctx structure representing the stack pointer | ||
129 | * at context switch time. | ||
130 | */ | ||
131 | struct port_context {}; | ||
132 | #endif /* defined(__DOXYGEN__) */ | ||
133 | |||
134 | #endif /* !defined(_FROM_ASM_) */ | ||
135 | |||
136 | /*===========================================================================*/ | ||
137 | /* Module macros. */ | ||
138 | /*===========================================================================*/ | ||
139 | |||
140 | /** | ||
141 | * @brief Total priority levels. | ||
142 | */ | ||
143 | #define CORTEX_PRIORITY_LEVELS (1U << CORTEX_PRIORITY_BITS) | ||
144 | |||
145 | /** | ||
146 | * @brief Minimum priority level. | ||
147 | * @details This minimum priority level is calculated from the number of | ||
148 | * priority bits supported by the specific Cortex-Mx implementation. | ||
149 | */ | ||
150 | #define CORTEX_MINIMUM_PRIORITY (CORTEX_PRIORITY_LEVELS - 1) | ||
151 | |||
152 | /** | ||
153 | * @brief Maximum priority level. | ||
154 | * @details The maximum allowed priority level is always zero. | ||
155 | */ | ||
156 | #define CORTEX_MAXIMUM_PRIORITY 0U | ||
157 | |||
158 | /** | ||
159 | * @brief Priority level to priority mask conversion macro. | ||
160 | */ | ||
161 | #define CORTEX_PRIO_MASK(n) \ | ||
162 | ((n) << (8U - (unsigned)CORTEX_PRIORITY_BITS)) | ||
163 | |||
164 | /** | ||
165 | * @brief Priority level verification macro. | ||
166 | */ | ||
167 | #define PORT_IRQ_IS_VALID_PRIORITY(n) \ | ||
168 | (((n) >= 0U) && ((n) < CORTEX_PRIORITY_LEVELS)) | ||
169 | |||
170 | /** | ||
171 | * @brief Priority level verification macro. | ||
172 | */ | ||
173 | #define PORT_IRQ_IS_VALID_KERNEL_PRIORITY(n) \ | ||
174 | (((n) >= CORTEX_MAX_KERNEL_PRIORITY) && ((n) < CORTEX_PRIORITY_LEVELS)) | ||
175 | |||
176 | /*===========================================================================*/ | ||
177 | /* External declarations. */ | ||
178 | /*===========================================================================*/ | ||
179 | |||
180 | /*===========================================================================*/ | ||
181 | /* Module inline functions. */ | ||
182 | /*===========================================================================*/ | ||
183 | |||
184 | /* Includes the sub-architecture-specific part.*/ | ||
185 | #if (CORTEX_MODEL == 0) || (CORTEX_MODEL == 1) | ||
186 | #include "chcore_v6m.h" | ||
187 | #elif (CORTEX_MODEL == 3) || (CORTEX_MODEL == 4) || (CORTEX_MODEL == 7) | ||
188 | #include "mpu.h" | ||
189 | #include "chcore_v7m.h" | ||
190 | #else | ||
191 | #error "unknown Cortex-M variant" | ||
192 | #endif | ||
193 | |||
194 | #if !defined(_FROM_ASM_) | ||
195 | |||
196 | #if CH_CFG_ST_TIMEDELTA > 0 | ||
197 | #if PORT_USE_ALT_TIMER == FALSE | ||
198 | #include "chcore_timer.h" | ||
199 | #else /* PORT_USE_ALT_TIMER != FALSE */ | ||
200 | #include "chcore_timer_alt.h" | ||
201 | #endif /* PORT_USE_ALT_TIMER != FALSE */ | ||
202 | #endif /* CH_CFG_ST_TIMEDELTA > 0 */ | ||
203 | |||
204 | #endif /* !defined(_FROM_ASM_) */ | ||
205 | |||
206 | #endif /* CHCORE_H */ | ||
207 | |||
208 | /** @} */ | ||
diff --git a/lib/chibios/os/common/ports/ARMCMx/chcore_timer.h b/lib/chibios/os/common/ports/ARMCMx/chcore_timer.h new file mode 100644 index 000000000..d03e52223 --- /dev/null +++ b/lib/chibios/os/common/ports/ARMCMx/chcore_timer.h | |||
@@ -0,0 +1,133 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file chcore_timer.h | ||
22 | * @brief System timer header file. | ||
23 | * | ||
24 | * @addtogroup ARMCMx_TIMER | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #ifndef CHCORE_TIMER_H | ||
29 | #define CHCORE_TIMER_H | ||
30 | |||
31 | /*===========================================================================*/ | ||
32 | /* Module constants. */ | ||
33 | /*===========================================================================*/ | ||
34 | |||
35 | /*===========================================================================*/ | ||
36 | /* Module pre-compile time settings. */ | ||
37 | /*===========================================================================*/ | ||
38 | |||
39 | /*===========================================================================*/ | ||
40 | /* Derived constants and error checks. */ | ||
41 | /*===========================================================================*/ | ||
42 | |||
43 | /*===========================================================================*/ | ||
44 | /* Module data structures and types. */ | ||
45 | /*===========================================================================*/ | ||
46 | |||
47 | /*===========================================================================*/ | ||
48 | /* Module macros. */ | ||
49 | /*===========================================================================*/ | ||
50 | |||
51 | /*===========================================================================*/ | ||
52 | /* External declarations. */ | ||
53 | /*===========================================================================*/ | ||
54 | |||
55 | #ifdef __cplusplus | ||
56 | extern "C" { | ||
57 | #endif | ||
58 | void stStartAlarm(systime_t time); | ||
59 | void stStopAlarm(void); | ||
60 | void stSetAlarm(systime_t time); | ||
61 | systime_t stGetCounter(void); | ||
62 | systime_t stGetAlarm(void); | ||
63 | #ifdef __cplusplus | ||
64 | } | ||
65 | #endif | ||
66 | |||
67 | /*===========================================================================*/ | ||
68 | /* Module inline functions. */ | ||
69 | /*===========================================================================*/ | ||
70 | |||
71 | /** | ||
72 | * @brief Starts the alarm. | ||
73 | * @note Makes sure that no spurious alarms are triggered after | ||
74 | * this call. | ||
75 | * | ||
76 | * @param[in] time the time to be set for the first alarm | ||
77 | * | ||
78 | * @notapi | ||
79 | */ | ||
80 | static inline void port_timer_start_alarm(systime_t time) { | ||
81 | |||
82 | stStartAlarm(time); | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * @brief Stops the alarm interrupt. | ||
87 | * | ||
88 | * @notapi | ||
89 | */ | ||
90 | static inline void port_timer_stop_alarm(void) { | ||
91 | |||
92 | stStopAlarm(); | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * @brief Sets the alarm time. | ||
97 | * | ||
98 | * @param[in] time the time to be set for the next alarm | ||
99 | * | ||
100 | * @notapi | ||
101 | */ | ||
102 | static inline void port_timer_set_alarm(systime_t time) { | ||
103 | |||
104 | stSetAlarm(time); | ||
105 | } | ||
106 | |||
107 | /** | ||
108 | * @brief Returns the system time. | ||
109 | * | ||
110 | * @return The system time. | ||
111 | * | ||
112 | * @notapi | ||
113 | */ | ||
114 | static inline systime_t port_timer_get_time(void) { | ||
115 | |||
116 | return stGetCounter(); | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * @brief Returns the current alarm time. | ||
121 | * | ||
122 | * @return The currently set alarm time. | ||
123 | * | ||
124 | * @notapi | ||
125 | */ | ||
126 | static inline systime_t port_timer_get_alarm(void) { | ||
127 | |||
128 | return stGetAlarm(); | ||
129 | } | ||
130 | |||
131 | #endif /* CHCORE_TIMER_H */ | ||
132 | |||
133 | /** @} */ | ||
diff --git a/lib/chibios/os/common/ports/ARMCMx/chcore_v6m.c b/lib/chibios/os/common/ports/ARMCMx/chcore_v6m.c new file mode 100644 index 000000000..620005809 --- /dev/null +++ b/lib/chibios/os/common/ports/ARMCMx/chcore_v6m.c | |||
@@ -0,0 +1,155 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file chcore_v6m.c | ||
22 | * @brief ARMv6-M architecture port code. | ||
23 | * | ||
24 | * @addtogroup ARMCMx_V6M_CORE | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #include "ch.h" | ||
29 | |||
30 | /*===========================================================================*/ | ||
31 | /* Module local definitions. */ | ||
32 | /*===========================================================================*/ | ||
33 | |||
34 | /*===========================================================================*/ | ||
35 | /* Module exported variables. */ | ||
36 | /*===========================================================================*/ | ||
37 | |||
38 | /*===========================================================================*/ | ||
39 | /* Module local types. */ | ||
40 | /*===========================================================================*/ | ||
41 | |||
42 | /*===========================================================================*/ | ||
43 | /* Module local variables. */ | ||
44 | /*===========================================================================*/ | ||
45 | |||
46 | /*===========================================================================*/ | ||
47 | /* Module local functions. */ | ||
48 | /*===========================================================================*/ | ||
49 | |||
50 | /*===========================================================================*/ | ||
51 | /* Module interrupt handlers. */ | ||
52 | /*===========================================================================*/ | ||
53 | |||
54 | #if (CORTEX_ALTERNATE_SWITCH == FALSE) || defined(__DOXYGEN__) | ||
55 | /** | ||
56 | * @brief NMI vector. | ||
57 | * @details The NMI vector is used for exception mode re-entering after a | ||
58 | * context switch. | ||
59 | */ | ||
60 | /*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ | ||
61 | void NMI_Handler(void) { | ||
62 | /*lint -restore*/ | ||
63 | |||
64 | /* The port_extctx structure is pointed by the PSP register.*/ | ||
65 | struct port_extctx *ctxp = (struct port_extctx *)__get_PSP(); | ||
66 | |||
67 | /* Discarding the current exception context and positioning the stack to | ||
68 | point to the real one.*/ | ||
69 | ctxp++; | ||
70 | |||
71 | /* Writing back the modified PSP value.*/ | ||
72 | __set_PSP((uint32_t)ctxp); | ||
73 | |||
74 | /* Restoring the normal interrupts status.*/ | ||
75 | port_unlock_from_isr(); | ||
76 | } | ||
77 | #endif /* !CORTEX_ALTERNATE_SWITCH */ | ||
78 | |||
79 | #if (CORTEX_ALTERNATE_SWITCH == TRUE) || defined(__DOXYGEN__) | ||
80 | /** | ||
81 | * @brief PendSV vector. | ||
82 | * @details The PendSV vector is used for exception mode re-entering after a | ||
83 | * context switch. | ||
84 | */ | ||
85 | /*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ | ||
86 | void PendSV_Handler(void) { | ||
87 | /*lint -restore*/ | ||
88 | |||
89 | /* The port_extctx structure is pointed by the PSP register.*/ | ||
90 | struct port_extctx *ctxp = (struct port_extctx *)__get_PSP(); | ||
91 | |||
92 | /* Discarding the current exception context and positioning the stack to | ||
93 | point to the real one.*/ | ||
94 | ctxp++; | ||
95 | |||
96 | /* Writing back the modified PSP value.*/ | ||
97 | __set_PSP((uint32_t)ctxp); | ||
98 | } | ||
99 | #endif /* CORTEX_ALTERNATE_SWITCH */ | ||
100 | |||
101 | /*===========================================================================*/ | ||
102 | /* Module exported functions. */ | ||
103 | /*===========================================================================*/ | ||
104 | |||
105 | /** | ||
106 | * @brief Port-related initialization code. | ||
107 | */ | ||
108 | void port_init(void) { | ||
109 | |||
110 | NVIC_SetPriority(PendSV_IRQn, CORTEX_PRIORITY_PENDSV); | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * @brief IRQ epilogue code. | ||
115 | * | ||
116 | * @param[in] lr value of the @p LR register on ISR entry | ||
117 | */ | ||
118 | void _port_irq_epilogue(uint32_t lr) { | ||
119 | |||
120 | if (lr != 0xFFFFFFF1U) { | ||
121 | struct port_extctx *ectxp; | ||
122 | |||
123 | port_lock_from_isr(); | ||
124 | |||
125 | /* The extctx structure is pointed by the PSP register.*/ | ||
126 | ectxp = (struct port_extctx *)__get_PSP(); | ||
127 | |||
128 | /* Adding an artificial exception return context, there is no need to | ||
129 | populate it fully.*/ | ||
130 | ectxp--; | ||
131 | |||
132 | /* Writing back the modified PSP value.*/ | ||
133 | __set_PSP((uint32_t)ectxp); | ||
134 | |||
135 | /* Setting up a fake XPSR register value.*/ | ||
136 | ectxp->xpsr = 0x01000000U; | ||
137 | |||
138 | /* The exit sequence is different depending on if a preemption is | ||
139 | required or not.*/ | ||
140 | if (chSchIsPreemptionRequired()) { | ||
141 | /* Preemption is required we need to enforce a context switch.*/ | ||
142 | ectxp->pc = (uint32_t)_port_switch_from_isr; | ||
143 | } | ||
144 | else { | ||
145 | /* Preemption not required, we just need to exit the exception | ||
146 | atomically.*/ | ||
147 | ectxp->pc = (uint32_t)_port_exit_from_isr; | ||
148 | } | ||
149 | |||
150 | /* Note, returning without unlocking is intentional, this is done in | ||
151 | order to keep the rest of the context switch atomic.*/ | ||
152 | } | ||
153 | } | ||
154 | |||
155 | /** @} */ | ||
diff --git a/lib/chibios/os/common/ports/ARMCMx/chcore_v6m.h b/lib/chibios/os/common/ports/ARMCMx/chcore_v6m.h new file mode 100644 index 000000000..8c80a9765 --- /dev/null +++ b/lib/chibios/os/common/ports/ARMCMx/chcore_v6m.h | |||
@@ -0,0 +1,466 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file chcore_v6m.h | ||
22 | * @brief ARMv6-M architecture port macros and structures. | ||
23 | * | ||
24 | * @addtogroup ARMCMx_V6M_CORE | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #ifndef CHCORE_V6M_H | ||
29 | #define CHCORE_V6M_H | ||
30 | |||
31 | /*===========================================================================*/ | ||
32 | /* Module constants. */ | ||
33 | /*===========================================================================*/ | ||
34 | |||
35 | /** | ||
36 | * @name Port Capabilities and Constants | ||
37 | * @{ | ||
38 | */ | ||
39 | /** | ||
40 | * @brief This port supports a realtime counter. | ||
41 | */ | ||
42 | #define PORT_SUPPORTS_RT FALSE | ||
43 | |||
44 | /** | ||
45 | * @brief Natural alignment constant. | ||
46 | * @note It is the minimum alignment for pointer-size variables. | ||
47 | */ | ||
48 | #define PORT_NATURAL_ALIGN sizeof (void *) | ||
49 | |||
50 | /** | ||
51 | * @brief Stack alignment constant. | ||
52 | * @note It is the alignment required for the stack pointer. | ||
53 | */ | ||
54 | #define PORT_STACK_ALIGN sizeof (stkalign_t) | ||
55 | |||
56 | /** | ||
57 | * @brief Working Areas alignment constant. | ||
58 | * @note It is the alignment to be enforced for thread working areas. | ||
59 | */ | ||
60 | #define PORT_WORKING_AREA_ALIGN PORT_STACK_ALIGN | ||
61 | /** @} */ | ||
62 | |||
63 | /** | ||
64 | * @brief PendSV priority level. | ||
65 | * @note This priority is enforced to be equal to @p 0, | ||
66 | * this handler always has the highest priority that cannot preempt | ||
67 | * the kernel. | ||
68 | */ | ||
69 | #define CORTEX_PRIORITY_PENDSV 0 | ||
70 | |||
71 | /*===========================================================================*/ | ||
72 | /* Module pre-compile time settings. */ | ||
73 | /*===========================================================================*/ | ||
74 | |||
75 | /** | ||
76 | * @brief Stack size for the system idle thread. | ||
77 | * @details This size depends on the idle thread implementation, usually | ||
78 | * the idle thread should take no more space than those reserved | ||
79 | * by @p PORT_INT_REQUIRED_STACK. | ||
80 | * @note In this port it is set to 16 because the idle thread does have | ||
81 | * a stack frame when compiling without optimizations. You may | ||
82 | * reduce this value to zero when compiling with optimizations. | ||
83 | */ | ||
84 | #if !defined(PORT_IDLE_THREAD_STACK_SIZE) | ||
85 | #define PORT_IDLE_THREAD_STACK_SIZE 16 | ||
86 | #endif | ||
87 | |||
88 | /** | ||
89 | * @brief Per-thread stack overhead for interrupts servicing. | ||
90 | * @details This constant is used in the calculation of the correct working | ||
91 | * area size. | ||
92 | * @note In this port this value is conservatively set to 64 because the | ||
93 | * function @p chSchDoReschedule() can have a stack frame, especially | ||
94 | * with compiler optimizations disabled. The value can be reduced | ||
95 | * when compiler optimizations are enabled. | ||
96 | */ | ||
97 | #if !defined(PORT_INT_REQUIRED_STACK) | ||
98 | #define PORT_INT_REQUIRED_STACK 64 | ||
99 | #endif | ||
100 | |||
101 | /** | ||
102 | * @brief Enables the use of the WFI instruction in the idle thread loop. | ||
103 | */ | ||
104 | #if !defined(CORTEX_ENABLE_WFI_IDLE) | ||
105 | #define CORTEX_ENABLE_WFI_IDLE FALSE | ||
106 | #endif | ||
107 | |||
108 | /** | ||
109 | * @brief Alternate preemption method. | ||
110 | * @details Activating this option will make the Kernel use the PendSV | ||
111 | * handler for preemption instead of the NMI handler. | ||
112 | */ | ||
113 | #ifndef CORTEX_ALTERNATE_SWITCH | ||
114 | #define CORTEX_ALTERNATE_SWITCH FALSE | ||
115 | #endif | ||
116 | |||
117 | /*===========================================================================*/ | ||
118 | /* Derived constants and error checks. */ | ||
119 | /*===========================================================================*/ | ||
120 | |||
121 | #if !defined(CH_CUSTOMER_LIC_PORT_CM0) | ||
122 | #error "CH_CUSTOMER_LIC_PORT_CM0 not defined" | ||
123 | #endif | ||
124 | |||
125 | #if CH_CUSTOMER_LIC_PORT_CM0 == FALSE | ||
126 | #error "ChibiOS Cortex-M0 port not licensed" | ||
127 | #endif | ||
128 | |||
129 | /* Handling a GCC problem impacting ARMv6-M.*/ | ||
130 | #if defined(__GNUC__) && !defined(PORT_IGNORE_GCC_VERSION_CHECK) | ||
131 | #if ( __GNUC__ > 5 ) && ( __GNUC__ < 10 ) | ||
132 | #define GCC_VERSION ( __GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ ) | ||
133 | #if ( __GNUC__ == 7 ) && ( GCC_VERSION >= 70500 ) | ||
134 | #elif ( __GNUC__ == 8 ) && ( GCC_VERSION >= 80400 ) | ||
135 | #elif ( __GNUC__ == 9 ) && ( GCC_VERSION >= 90300 ) | ||
136 | #else | ||
137 | #warning "This compiler has a know problem with Cortex-M0, see GCC bugs: 88167, 88656." | ||
138 | #endif | ||
139 | #endif | ||
140 | #endif | ||
141 | |||
142 | /** | ||
143 | * @name Architecture and Compiler | ||
144 | * @{ | ||
145 | */ | ||
146 | #if ((CORTEX_MODEL == 0) && !defined(__CORE_CM0PLUS_H_DEPENDANT)) || \ | ||
147 | defined(__DOXYGEN__) | ||
148 | /** | ||
149 | * @brief Macro defining the specific ARM architecture. | ||
150 | */ | ||
151 | #define PORT_ARCHITECTURE_ARM_v6M | ||
152 | |||
153 | /** | ||
154 | * @brief Name of the implemented architecture. | ||
155 | */ | ||
156 | #define PORT_ARCHITECTURE_NAME "ARMv6-M" | ||
157 | |||
158 | /** | ||
159 | * @brief Name of the architecture variant. | ||
160 | */ | ||
161 | #define PORT_CORE_VARIANT_NAME "Cortex-M0" | ||
162 | |||
163 | #elif (CORTEX_MODEL == 0) && defined(__CORE_CM0PLUS_H_DEPENDANT) | ||
164 | #define PORT_ARCHITECTURE_ARM_v6M | ||
165 | #define PORT_ARCHITECTURE_NAME "ARMv6-M" | ||
166 | #define PORT_CORE_VARIANT_NAME "Cortex-M0+" | ||
167 | #endif | ||
168 | |||
169 | /** | ||
170 | * @brief Port-specific information string. | ||
171 | */ | ||
172 | #if (CORTEX_ALTERNATE_SWITCH == FALSE) || defined(__DOXYGEN__) | ||
173 | #define PORT_INFO "Preemption through NMI" | ||
174 | #else | ||
175 | #define PORT_INFO "Preemption through PendSV" | ||
176 | #endif | ||
177 | /** @} */ | ||
178 | |||
179 | /** | ||
180 | * @brief Maximum usable priority for normal ISRs. | ||
181 | */ | ||
182 | #if (CORTEX_ALTERNATE_SWITCH == TRUE) || defined(__DOXYGEN__) | ||
183 | #define CORTEX_MAX_KERNEL_PRIORITY 1 | ||
184 | #else | ||
185 | #define CORTEX_MAX_KERNEL_PRIORITY 0 | ||
186 | #endif | ||
187 | |||
188 | /*===========================================================================*/ | ||
189 | /* Module data structures and types. */ | ||
190 | /*===========================================================================*/ | ||
191 | |||
192 | #if !defined(_FROM_ASM_) | ||
193 | |||
194 | /* The documentation of the following declarations is in chconf.h in order | ||
195 | to not have duplicated structure names into the documentation.*/ | ||
196 | #if !defined(__DOXYGEN__) | ||
197 | struct port_extctx { | ||
198 | uint32_t r0; | ||
199 | uint32_t r1; | ||
200 | uint32_t r2; | ||
201 | uint32_t r3; | ||
202 | uint32_t r12; | ||
203 | uint32_t lr_thd; | ||
204 | uint32_t pc; | ||
205 | uint32_t xpsr; | ||
206 | }; | ||
207 | |||
208 | struct port_intctx { | ||
209 | uint32_t r8; | ||
210 | uint32_t r9; | ||
211 | uint32_t r10; | ||
212 | uint32_t r11; | ||
213 | uint32_t r4; | ||
214 | uint32_t r5; | ||
215 | uint32_t r6; | ||
216 | uint32_t r7; | ||
217 | uint32_t lr; | ||
218 | }; | ||
219 | |||
220 | struct port_context { | ||
221 | struct port_intctx *sp; | ||
222 | }; | ||
223 | #endif /* !defined(__DOXYGEN__) */ | ||
224 | |||
225 | /*===========================================================================*/ | ||
226 | /* Module macros. */ | ||
227 | /*===========================================================================*/ | ||
228 | |||
229 | /** | ||
230 | * @brief Platform dependent part of the @p chThdCreateI() API. | ||
231 | * @details This code usually setup the context switching frame represented | ||
232 | * by an @p port_intctx structure. | ||
233 | */ | ||
234 | #define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \ | ||
235 | (tp)->ctx.sp = (struct port_intctx *)((uint8_t *)(wtop) - \ | ||
236 | sizeof (struct port_intctx)); \ | ||
237 | (tp)->ctx.sp->r4 = (uint32_t)(pf); \ | ||
238 | (tp)->ctx.sp->r5 = (uint32_t)(arg); \ | ||
239 | (tp)->ctx.sp->lr = (uint32_t)_port_thread_start; \ | ||
240 | } | ||
241 | |||
242 | /** | ||
243 | * @brief Computes the thread working area global size. | ||
244 | * @note There is no need to perform alignments in this macro. | ||
245 | */ | ||
246 | #define PORT_WA_SIZE(n) (sizeof (struct port_intctx) + \ | ||
247 | sizeof (struct port_extctx) + \ | ||
248 | ((size_t)(n)) + ((size_t)(PORT_INT_REQUIRED_STACK))) | ||
249 | |||
250 | /** | ||
251 | * @brief Static working area allocation. | ||
252 | * @details This macro is used to allocate a static thread working area | ||
253 | * aligned as both position and size. | ||
254 | * | ||
255 | * @param[in] s the name to be assigned to the stack array | ||
256 | * @param[in] n the stack size to be assigned to the thread | ||
257 | */ | ||
258 | #define PORT_WORKING_AREA(s, n) \ | ||
259 | stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)] | ||
260 | |||
261 | /** | ||
262 | * @brief IRQ prologue code. | ||
263 | * @details This macro must be inserted at the start of all IRQ handlers | ||
264 | * enabled to invoke system APIs. | ||
265 | */ | ||
266 | #if defined(__GNUC__) || defined(__DOXYGEN__) | ||
267 | #define PORT_IRQ_PROLOGUE() \ | ||
268 | uint32_t _saved_lr = (uint32_t)__builtin_return_address(0) | ||
269 | #elif defined(__ICCARM__) | ||
270 | #define PORT_IRQ_PROLOGUE() \ | ||
271 | uint32_t _saved_lr = (uint32_t)__get_LR() | ||
272 | #elif defined(__CC_ARM) | ||
273 | #define PORT_IRQ_PROLOGUE() \ | ||
274 | uint32_t _saved_lr = (uint32_t)__return_address() | ||
275 | #endif | ||
276 | |||
277 | /** | ||
278 | * @brief IRQ epilogue code. | ||
279 | * @details This macro must be inserted at the end of all IRQ handlers | ||
280 | * enabled to invoke system APIs. | ||
281 | */ | ||
282 | #define PORT_IRQ_EPILOGUE() _port_irq_epilogue(_saved_lr) | ||
283 | |||
284 | /** | ||
285 | * @brief IRQ handler function declaration. | ||
286 | * @note @p id can be a function name or a vector number depending on the | ||
287 | * port implementation. | ||
288 | */ | ||
289 | #ifdef __cplusplus | ||
290 | #define PORT_IRQ_HANDLER(id) extern "C" void id(void) | ||
291 | #else | ||
292 | #define PORT_IRQ_HANDLER(id) void id(void) | ||
293 | #endif | ||
294 | |||
295 | /** | ||
296 | * @brief Fast IRQ handler function declaration. | ||
297 | * @note @p id can be a function name or a vector number depending on the | ||
298 | * port implementation. | ||
299 | */ | ||
300 | #ifdef __cplusplus | ||
301 | #define PORT_FAST_IRQ_HANDLER(id) extern "C" void id(void) | ||
302 | #else | ||
303 | #define PORT_FAST_IRQ_HANDLER(id) void id(void) | ||
304 | #endif | ||
305 | |||
306 | /** | ||
307 | * @brief Performs a context switch between two threads. | ||
308 | * @details This is the most critical code in any port, this function | ||
309 | * is responsible for the context switch between 2 threads. | ||
310 | * @note The implementation of this code affects <b>directly</b> the context | ||
311 | * switch performance so optimize here as much as you can. | ||
312 | * | ||
313 | * @param[in] ntp the thread to be switched in | ||
314 | * @param[in] otp the thread to be switched out | ||
315 | */ | ||
316 | #if (CH_DBG_ENABLE_STACK_CHECK == FALSE) || defined(__DOXYGEN__) | ||
317 | #define port_switch(ntp, otp) _port_switch(ntp, otp) | ||
318 | #else | ||
319 | #define port_switch(ntp, otp) { \ | ||
320 | struct port_intctx *r13 = (struct port_intctx *)__get_PSP(); \ | ||
321 | if ((stkalign_t *)(r13 - 1) < (otp)->wabase) { \ | ||
322 | chSysHalt("stack overflow"); \ | ||
323 | } \ | ||
324 | _port_switch(ntp, otp); \ | ||
325 | } | ||
326 | #endif | ||
327 | |||
328 | /*===========================================================================*/ | ||
329 | /* External declarations. */ | ||
330 | /*===========================================================================*/ | ||
331 | |||
332 | #ifdef __cplusplus | ||
333 | extern "C" { | ||
334 | #endif | ||
335 | void port_init(void); | ||
336 | void _port_irq_epilogue(uint32_t lr); | ||
337 | void _port_switch(thread_t *ntp, thread_t *otp); | ||
338 | void _port_thread_start(void); | ||
339 | void _port_switch_from_isr(void); | ||
340 | void _port_exit_from_isr(void); | ||
341 | #ifdef __cplusplus | ||
342 | } | ||
343 | #endif | ||
344 | |||
345 | /*===========================================================================*/ | ||
346 | /* Module inline functions. */ | ||
347 | /*===========================================================================*/ | ||
348 | |||
349 | /** | ||
350 | * @brief Returns a word encoding the current interrupts status. | ||
351 | * | ||
352 | * @return The interrupts status. | ||
353 | */ | ||
354 | static inline syssts_t port_get_irq_status(void) { | ||
355 | |||
356 | return (syssts_t)__get_PRIMASK(); | ||
357 | } | ||
358 | |||
359 | /** | ||
360 | * @brief Checks the interrupt status. | ||
361 | * | ||
362 | * @param[in] sts the interrupt status word | ||
363 | * | ||
364 | * @return The interrupt status. | ||
365 | * @retval false the word specified a disabled interrupts status. | ||
366 | * @retval true the word specified an enabled interrupts status. | ||
367 | */ | ||
368 | static inline bool port_irq_enabled(syssts_t sts) { | ||
369 | |||
370 | return (sts & (syssts_t)1) == (syssts_t)0; | ||
371 | } | ||
372 | |||
373 | /** | ||
374 | * @brief Determines the current execution context. | ||
375 | * | ||
376 | * @return The execution context. | ||
377 | * @retval false not running in ISR mode. | ||
378 | * @retval true running in ISR mode. | ||
379 | */ | ||
380 | static inline bool port_is_isr_context(void) { | ||
381 | |||
382 | return (bool)((__get_IPSR() & 0x1FFU) != 0U); | ||
383 | } | ||
384 | |||
385 | /** | ||
386 | * @brief Kernel-lock action. | ||
387 | * @details In this port this function disables interrupts globally. | ||
388 | */ | ||
389 | static inline void port_lock(void) { | ||
390 | |||
391 | __disable_irq(); | ||
392 | } | ||
393 | |||
394 | /** | ||
395 | * @brief Kernel-unlock action. | ||
396 | * @details In this port this function enables interrupts globally. | ||
397 | */ | ||
398 | static inline void port_unlock(void) { | ||
399 | |||
400 | __enable_irq(); | ||
401 | } | ||
402 | |||
403 | /** | ||
404 | * @brief Kernel-lock action from an interrupt handler. | ||
405 | * @details In this port this function disables interrupts globally. | ||
406 | * @note Same as @p port_lock() in this port. | ||
407 | */ | ||
408 | static inline void port_lock_from_isr(void) { | ||
409 | |||
410 | port_lock(); | ||
411 | } | ||
412 | |||
413 | /** | ||
414 | * @brief Kernel-unlock action from an interrupt handler. | ||
415 | * @details In this port this function enables interrupts globally. | ||
416 | * @note Same as @p port_lock() in this port. | ||
417 | */ | ||
418 | static inline void port_unlock_from_isr(void) { | ||
419 | |||
420 | port_unlock(); | ||
421 | } | ||
422 | |||
423 | /** | ||
424 | * @brief Disables all the interrupt sources. | ||
425 | */ | ||
426 | static inline void port_disable(void) { | ||
427 | |||
428 | __disable_irq(); | ||
429 | } | ||
430 | |||
431 | /** | ||
432 | * @brief Disables the interrupt sources below kernel-level priority. | ||
433 | */ | ||
434 | static inline void port_suspend(void) { | ||
435 | |||
436 | __disable_irq(); | ||
437 | } | ||
438 | |||
439 | /** | ||
440 | * @brief Enables all the interrupt sources. | ||
441 | */ | ||
442 | static inline void port_enable(void) { | ||
443 | |||
444 | __enable_irq(); | ||
445 | } | ||
446 | |||
447 | /** | ||
448 | * @brief Enters an architecture-dependent IRQ-waiting mode. | ||
449 | * @details The function is meant to return when an interrupt becomes pending. | ||
450 | * The simplest implementation is an empty function or macro but this | ||
451 | * would not take advantage of architecture-specific power saving | ||
452 | * modes. | ||
453 | * @note Implemented as an inlined @p WFI instruction. | ||
454 | */ | ||
455 | static inline void port_wait_for_interrupt(void) { | ||
456 | |||
457 | #if CORTEX_ENABLE_WFI_IDLE == TRUE | ||
458 | __WFI(); | ||
459 | #endif | ||
460 | } | ||
461 | |||
462 | #endif /* _FROM_ASM_ */ | ||
463 | |||
464 | #endif /* CHCORE_V6M_H */ | ||
465 | |||
466 | /** @} */ | ||
diff --git a/lib/chibios/os/common/ports/ARMCMx/chcore_v7m.c b/lib/chibios/os/common/ports/ARMCMx/chcore_v7m.c new file mode 100644 index 000000000..f6b6bfb46 --- /dev/null +++ b/lib/chibios/os/common/ports/ARMCMx/chcore_v7m.c | |||
@@ -0,0 +1,391 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file chcore_v7m.c | ||
22 | * @brief ARMv7-M architecture port code. | ||
23 | * | ||
24 | * @addtogroup ARMCMx_V7M_CORE | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #include <string.h> | ||
29 | |||
30 | #include "ch.h" | ||
31 | |||
32 | /*===========================================================================*/ | ||
33 | /* Module local definitions. */ | ||
34 | /*===========================================================================*/ | ||
35 | |||
36 | /*===========================================================================*/ | ||
37 | /* Module exported variables. */ | ||
38 | /*===========================================================================*/ | ||
39 | |||
40 | /*===========================================================================*/ | ||
41 | /* Module local types. */ | ||
42 | /*===========================================================================*/ | ||
43 | |||
44 | /*===========================================================================*/ | ||
45 | /* Module local variables. */ | ||
46 | /*===========================================================================*/ | ||
47 | |||
48 | /*===========================================================================*/ | ||
49 | /* Module local functions. */ | ||
50 | /*===========================================================================*/ | ||
51 | |||
52 | /*===========================================================================*/ | ||
53 | /* Module interrupt handlers. */ | ||
54 | /*===========================================================================*/ | ||
55 | |||
56 | #if (PORT_USE_SYSCALL == TRUE) || defined(__DOXYGEN__) | ||
57 | __attribute__((noinline)) | ||
58 | void port_syslock_noinline(void) { | ||
59 | |||
60 | port_lock(); | ||
61 | _stats_start_measure_crit_thd(); | ||
62 | _dbg_check_lock(); | ||
63 | } | ||
64 | |||
65 | uint32_t port_get_s_psp(void) { | ||
66 | |||
67 | return (uint32_t)currp->ctx.syscall.psp; | ||
68 | } | ||
69 | |||
70 | __attribute__((weak)) | ||
71 | void port_syscall(struct port_extctx *ctxp, uint32_t n) { | ||
72 | |||
73 | (void)ctxp; | ||
74 | (void)n; | ||
75 | |||
76 | chSysHalt("svc"); | ||
77 | } | ||
78 | |||
79 | void port_unprivileged_jump(uint32_t pc, uint32_t psp) { | ||
80 | struct port_extctx *ectxp; | ||
81 | struct port_linkctx *lctxp; | ||
82 | uint32_t s_psp = __get_PSP(); | ||
83 | uint32_t control = __get_CONTROL(); | ||
84 | |||
85 | /* Creating a port_extctx context for user mode entry.*/ | ||
86 | psp -= sizeof (struct port_extctx); | ||
87 | ectxp = (struct port_extctx *)psp; | ||
88 | |||
89 | /* Initializing the user mode entry context.*/ | ||
90 | memset((void *)ectxp, 0, sizeof (struct port_extctx)); | ||
91 | ectxp->pc = pc; | ||
92 | ectxp->xpsr = 0x01000000U; | ||
93 | #if CORTEX_USE_FPU == TRUE | ||
94 | ectxp->fpscr = __get_FPSCR(); | ||
95 | #endif | ||
96 | |||
97 | /* Creating a middle context for user mode entry.*/ | ||
98 | s_psp -= sizeof (struct port_linkctx); | ||
99 | lctxp = (struct port_linkctx *)s_psp; | ||
100 | |||
101 | /* CONTROL and PSP values for user mode.*/ | ||
102 | lctxp->control = control | 1U; | ||
103 | lctxp->ectxp = ectxp; | ||
104 | |||
105 | /* PSP now points to the port_linkctx structure, it will be removed | ||
106 | by SVC.*/ | ||
107 | __set_PSP(s_psp); | ||
108 | |||
109 | asm volatile ("svc 0"); | ||
110 | |||
111 | chSysHalt("svc"); | ||
112 | } | ||
113 | #endif | ||
114 | |||
115 | #if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__) | ||
116 | /** | ||
117 | * @brief SVC vector. | ||
118 | * @details The SVC vector is used for exception mode re-entering after a | ||
119 | * context switch and, optionally, for system calls. | ||
120 | * @note The SVC vector is only used in advanced kernel mode. | ||
121 | */ | ||
122 | /*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ | ||
123 | void SVC_Handler(void) { | ||
124 | /*lint -restore*/ | ||
125 | uint32_t psp = __get_PSP(); | ||
126 | |||
127 | #if PORT_USE_SYSCALL == TRUE | ||
128 | uint32_t control; | ||
129 | /* Caller context.*/ | ||
130 | struct port_extctx *ectxp = (struct port_extctx *)psp; | ||
131 | |||
132 | #if defined(__GNUC__) | ||
133 | chDbgAssert(((uint32_t)__builtin_return_address(0) & 4U) != 0U, | ||
134 | "not process"); | ||
135 | #endif | ||
136 | |||
137 | /* Checking if the SVC instruction has been used from privileged or | ||
138 | non-privileged mode.*/ | ||
139 | control = __get_CONTROL(); | ||
140 | if ((control & 1U) != 0) { | ||
141 | /* From non-privileged mode, it must be handled as a syscall.*/ | ||
142 | uint32_t n, s_psp; | ||
143 | struct port_linkctx *lctxp; | ||
144 | struct port_extctx *newctxp; | ||
145 | |||
146 | /* Supervisor PSP from the thread context structure.*/ | ||
147 | s_psp = (uint32_t)currp->ctx.syscall.psp; | ||
148 | |||
149 | /* Pushing the port_linkctx into the supervisor stack.*/ | ||
150 | s_psp -= sizeof (struct port_linkctx); | ||
151 | lctxp = (struct port_linkctx *)s_psp; | ||
152 | lctxp->control = control; | ||
153 | lctxp->ectxp = ectxp; | ||
154 | |||
155 | /* Enforcing privileged mode before returning.*/ | ||
156 | __set_CONTROL(control & ~1U); | ||
157 | |||
158 | /* Number of the SVC instruction.*/ | ||
159 | n = (uint32_t)*(((const uint16_t *)ectxp->pc) - 1U) & 255U; | ||
160 | |||
161 | /* Building an artificial return context, we need to make this | ||
162 | return in the syscall dispatcher in privileged mode.*/ | ||
163 | s_psp -= sizeof (struct port_extctx); | ||
164 | __set_PSP(s_psp); | ||
165 | newctxp = (struct port_extctx *)s_psp; | ||
166 | newctxp->r0 = (uint32_t)ectxp; | ||
167 | newctxp->r1 = n; | ||
168 | newctxp->pc = (uint32_t)port_syscall; | ||
169 | newctxp->xpsr = 0x01000000U; | ||
170 | #if CORTEX_USE_FPU == TRUE | ||
171 | newctxp->fpscr = FPU->FPDSCR; | ||
172 | #endif | ||
173 | } | ||
174 | else | ||
175 | #endif | ||
176 | { | ||
177 | /* From privileged mode, it is used for context discarding in the | ||
178 | preemption code.*/ | ||
179 | |||
180 | /* Unstacking procedure, discarding the current exception context and | ||
181 | positioning the stack to point to the real one.*/ | ||
182 | psp += sizeof (struct port_extctx); | ||
183 | |||
184 | #if CORTEX_USE_FPU == TRUE | ||
185 | /* Enforcing unstacking of the FP part of the context.*/ | ||
186 | FPU->FPCCR &= ~FPU_FPCCR_LSPACT_Msk; | ||
187 | #endif | ||
188 | |||
189 | #if PORT_USE_SYSCALL == TRUE | ||
190 | { | ||
191 | /* Restoring CONTROL and the original PSP position.*/ | ||
192 | struct port_linkctx *lctxp = (struct port_linkctx *)psp; | ||
193 | __set_CONTROL((uint32_t)lctxp->control); | ||
194 | __set_PSP((uint32_t)lctxp->ectxp); | ||
195 | } | ||
196 | #else | ||
197 | |||
198 | /* Restoring real position of the original stack frame.*/ | ||
199 | __set_PSP(psp); | ||
200 | #endif | ||
201 | |||
202 | /* Restoring the normal interrupts status.*/ | ||
203 | port_unlock_from_isr(); | ||
204 | } | ||
205 | } | ||
206 | #endif /* CORTEX_SIMPLIFIED_PRIORITY == FALSE */ | ||
207 | |||
208 | #if (CORTEX_SIMPLIFIED_PRIORITY == TRUE) || defined(__DOXYGEN__) | ||
209 | /** | ||
210 | * @brief PendSV vector. | ||
211 | * @details The PendSV vector is used for exception mode re-entering after a | ||
212 | * context switch. | ||
213 | * @note The PendSV vector is only used in compact kernel mode. | ||
214 | */ | ||
215 | /*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ | ||
216 | void PendSV_Handler(void) { | ||
217 | /*lint -restore*/ | ||
218 | uint32_t psp = __get_PSP(); | ||
219 | |||
220 | #if CORTEX_USE_FPU | ||
221 | /* Enforcing unstacking of the FP part of the context.*/ | ||
222 | FPU->FPCCR &= ~FPU_FPCCR_LSPACT_Msk; | ||
223 | #endif | ||
224 | |||
225 | /* Discarding the current exception context and positioning the stack to | ||
226 | point to the real one.*/ | ||
227 | psp += sizeof (struct port_extctx); | ||
228 | |||
229 | #if PORT_USE_SYSCALL == TRUE | ||
230 | { | ||
231 | /* Restoring previous privileges by restoring CONTROL.*/ | ||
232 | struct port_linkctx *lctxp = (struct port_linkctx *)psp; | ||
233 | __set_CONTROL((uint32_t)lctxp->control); | ||
234 | psp += sizeof (struct port_linkctx); | ||
235 | } | ||
236 | #endif | ||
237 | |||
238 | /* Restoring real position of the original stack frame.*/ | ||
239 | __set_PSP(psp); | ||
240 | } | ||
241 | #endif /* CORTEX_SIMPLIFIED_PRIORITY == TRUE */ | ||
242 | |||
243 | /*===========================================================================*/ | ||
244 | /* Module exported functions. */ | ||
245 | /*===========================================================================*/ | ||
246 | |||
247 | /** | ||
248 | * @brief Port-related initialization code. | ||
249 | */ | ||
250 | void port_init(void) { | ||
251 | |||
252 | /* Starting in a known IRQ configuration.*/ | ||
253 | port_suspend(); | ||
254 | |||
255 | /* Initializing priority grouping.*/ | ||
256 | NVIC_SetPriorityGrouping(CORTEX_PRIGROUP_INIT); | ||
257 | |||
258 | /* DWT cycle counter enable, note, the M7 requires DWT unlocking.*/ | ||
259 | CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; | ||
260 | #if CORTEX_MODEL == 7 | ||
261 | DWT->LAR = 0xC5ACCE55U; | ||
262 | #endif | ||
263 | DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; | ||
264 | |||
265 | /* Initialization of the system vectors used by the port.*/ | ||
266 | #if CORTEX_SIMPLIFIED_PRIORITY == FALSE | ||
267 | NVIC_SetPriority(SVCall_IRQn, CORTEX_PRIORITY_SVCALL); | ||
268 | #endif | ||
269 | NVIC_SetPriority(PendSV_IRQn, CORTEX_PRIORITY_PENDSV); | ||
270 | |||
271 | #if PORT_ENABLE_GUARD_PAGES == TRUE | ||
272 | { | ||
273 | extern stkalign_t __main_thread_stack_base__; | ||
274 | |||
275 | /* Setting up the guard page on the main() function stack base | ||
276 | initially.*/ | ||
277 | mpuConfigureRegion(PORT_USE_GUARD_MPU_REGION, | ||
278 | &__main_thread_stack_base__, | ||
279 | MPU_RASR_ATTR_AP_NA_NA | | ||
280 | MPU_RASR_ATTR_NON_CACHEABLE | | ||
281 | MPU_RASR_SIZE_32 | | ||
282 | MPU_RASR_ENABLE); | ||
283 | } | ||
284 | #endif | ||
285 | |||
286 | #if (PORT_ENABLE_GUARD_PAGES == TRUE) || (PORT_USE_SYSCALL == TRUE) | ||
287 | /* MPU is enabled.*/ | ||
288 | mpuEnable(MPU_CTRL_PRIVDEFENA); | ||
289 | #endif | ||
290 | } | ||
291 | |||
292 | #if ((CH_DBG_ENABLE_STACK_CHECK == TRUE) && \ | ||
293 | (PORT_ENABLE_GUARD_PAGES == TRUE)) || \ | ||
294 | defined(__DOXYGEN__) | ||
295 | /** | ||
296 | * @brief Setting up MPU region for the current thread. | ||
297 | */ | ||
298 | void _port_set_region(void) { | ||
299 | |||
300 | mpuSetRegionAddress(PORT_USE_GUARD_MPU_REGION, | ||
301 | chThdGetSelfX()->wabase); | ||
302 | } | ||
303 | #endif | ||
304 | |||
305 | /** | ||
306 | * @brief Exception exit redirection to _port_switch_from_isr(). | ||
307 | */ | ||
308 | void _port_irq_epilogue(void) { | ||
309 | |||
310 | port_lock_from_isr(); | ||
311 | if ((SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) != 0U) { | ||
312 | struct port_extctx *ectxp; | ||
313 | uint32_t s_psp; | ||
314 | |||
315 | #if CORTEX_USE_FPU == TRUE | ||
316 | /* Enforcing a lazy FPU state save by accessing the FPCSR register.*/ | ||
317 | (void) __get_FPSCR(); | ||
318 | #endif | ||
319 | |||
320 | #if PORT_USE_SYSCALL == TRUE | ||
321 | { | ||
322 | struct port_linkctx *lctxp; | ||
323 | uint32_t control = __get_CONTROL(); | ||
324 | |||
325 | /* Checking if the IRQ has been served in unprivileged mode.*/ | ||
326 | if ((control & 1U) != 0U) { | ||
327 | /* Unprivileged mode, switching to privileged mode.*/ | ||
328 | __set_CONTROL(control & ~1U); | ||
329 | |||
330 | /* Switching to S-PSP taking it from the thread context.*/ | ||
331 | s_psp = (uint32_t)currp->ctx.syscall.psp; | ||
332 | |||
333 | /* Pushing the middle context for returning to the original frame | ||
334 | and mode.*/ | ||
335 | s_psp = s_psp - sizeof (struct port_linkctx); | ||
336 | lctxp = (struct port_linkctx *)s_psp; | ||
337 | lctxp->control = control; | ||
338 | lctxp->ectxp = (struct port_extctx *)__get_PSP(); | ||
339 | } | ||
340 | else { | ||
341 | /* Privileged mode, we are already on S-PSP.*/ | ||
342 | uint32_t psp = __get_PSP(); | ||
343 | |||
344 | /* Pushing the middle context for returning to the original frame | ||
345 | and mode.*/ | ||
346 | s_psp = psp - sizeof (struct port_linkctx); | ||
347 | lctxp = (struct port_linkctx *)s_psp; | ||
348 | lctxp->control = control; | ||
349 | lctxp->ectxp = (struct port_extctx *)psp; | ||
350 | } | ||
351 | } | ||
352 | #else | ||
353 | s_psp = __get_PSP(); | ||
354 | #endif | ||
355 | |||
356 | /* Adding an artificial exception return context, there is no need to | ||
357 | populate it fully.*/ | ||
358 | s_psp -= sizeof (struct port_extctx); | ||
359 | |||
360 | /* The port_extctx structure is pointed by the S-PSP register.*/ | ||
361 | ectxp = (struct port_extctx *)s_psp; | ||
362 | |||
363 | /* Setting up a fake XPSR register value.*/ | ||
364 | ectxp->xpsr = 0x01000000U; | ||
365 | #if CORTEX_USE_FPU == TRUE | ||
366 | ectxp->fpscr = FPU->FPDSCR; | ||
367 | #endif | ||
368 | |||
369 | /* Writing back the modified S-PSP value.*/ | ||
370 | __set_PSP(s_psp); | ||
371 | |||
372 | /* The exit sequence is different depending on if a preemption is | ||
373 | required or not.*/ | ||
374 | if (chSchIsPreemptionRequired()) { | ||
375 | /* Preemption is required we need to enforce a context switch.*/ | ||
376 | ectxp->pc = (uint32_t)_port_switch_from_isr; | ||
377 | } | ||
378 | else { | ||
379 | /* Preemption not required, we just need to exit the exception | ||
380 | atomically.*/ | ||
381 | ectxp->pc = (uint32_t)_port_exit_from_isr; | ||
382 | } | ||
383 | |||
384 | /* Note, returning without unlocking is intentional, this is done in | ||
385 | order to keep the rest of the context switch atomic.*/ | ||
386 | return; | ||
387 | } | ||
388 | port_unlock_from_isr(); | ||
389 | } | ||
390 | |||
391 | /** @} */ | ||
diff --git a/lib/chibios/os/common/ports/ARMCMx/chcore_v7m.h b/lib/chibios/os/common/ports/ARMCMx/chcore_v7m.h new file mode 100644 index 000000000..48618efd2 --- /dev/null +++ b/lib/chibios/os/common/ports/ARMCMx/chcore_v7m.h | |||
@@ -0,0 +1,790 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file chcore_v7m.h | ||
22 | * @brief ARMv7-M architecture port macros and structures. | ||
23 | * | ||
24 | * @addtogroup ARMCMx_V7M_CORE | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #ifndef CHCORE_V7M_H | ||
29 | #define CHCORE_V7M_H | ||
30 | |||
31 | /*===========================================================================*/ | ||
32 | /* Module constants. */ | ||
33 | /*===========================================================================*/ | ||
34 | |||
35 | /** | ||
36 | * @name Port Capabilities and Constants | ||
37 | * @{ | ||
38 | */ | ||
39 | /** | ||
40 | * @brief This port supports a realtime counter. | ||
41 | */ | ||
42 | #define PORT_SUPPORTS_RT TRUE | ||
43 | |||
44 | /** | ||
45 | * @brief Natural alignment constant. | ||
46 | * @note It is the minimum alignment for pointer-size variables. | ||
47 | */ | ||
48 | #define PORT_NATURAL_ALIGN sizeof (void *) | ||
49 | |||
50 | /** | ||
51 | * @brief Stack alignment constant. | ||
52 | * @note It is the alignment required for the stack pointer. | ||
53 | */ | ||
54 | #define PORT_STACK_ALIGN sizeof (stkalign_t) | ||
55 | |||
56 | /** | ||
57 | * @brief Working Areas alignment constant. | ||
58 | * @note It is the alignment to be enforced for thread working areas. | ||
59 | */ | ||
60 | #define PORT_WORKING_AREA_ALIGN ((PORT_ENABLE_GUARD_PAGES == TRUE) ?\ | ||
61 | 32U : PORT_STACK_ALIGN) | ||
62 | /** @} */ | ||
63 | |||
64 | /** | ||
65 | * @brief Disabled value for BASEPRI register. | ||
66 | */ | ||
67 | #define CORTEX_BASEPRI_DISABLED 0U | ||
68 | |||
69 | /*===========================================================================*/ | ||
70 | /* Module pre-compile time settings. */ | ||
71 | /*===========================================================================*/ | ||
72 | |||
73 | /** | ||
74 | * @brief Implements a syscall interface on SVC. | ||
75 | */ | ||
76 | #if !defined(PORT_USE_SYSCALL) || defined(__DOXYGEN__) | ||
77 | #define PORT_USE_SYSCALL FALSE | ||
78 | #endif | ||
79 | |||
80 | /** | ||
81 | * @brief Number of MPU regions to be saved/restored during context switch. | ||
82 | * @note The first region is always region zero. | ||
83 | * @note The use of this option has an overhead of 8 bytes for each | ||
84 | * region for each thread. | ||
85 | * @note Allowed values are 0..4, zero means none. | ||
86 | */ | ||
87 | #if !defined(PORT_SWITCHED_REGIONS_NUMBER) || defined(__DOXYGEN__) | ||
88 | #define PORT_SWITCHED_REGIONS_NUMBER 0 | ||
89 | #endif | ||
90 | |||
91 | /** | ||
92 | * @brief Enables stack overflow guard pages using MPU. | ||
93 | * @note This option can only be enabled if also option | ||
94 | * @p CH_DBG_ENABLE_STACK_CHECK is enabled. | ||
95 | * @note The use of this option has an overhead of 32 bytes for each | ||
96 | * thread. | ||
97 | */ | ||
98 | #if !defined(PORT_ENABLE_GUARD_PAGES) || defined(__DOXYGEN__) | ||
99 | #define PORT_ENABLE_GUARD_PAGES FALSE | ||
100 | #endif | ||
101 | |||
102 | /** | ||
103 | * @brief MPU region to be used to stack guards. | ||
104 | * @note Make sure this region is not included in the | ||
105 | * @p PORT_SWITCHED_REGIONS_NUMBER regions range. | ||
106 | */ | ||
107 | #if !defined(PORT_USE_GUARD_MPU_REGION) || defined(__DOXYGEN__) | ||
108 | #define PORT_USE_GUARD_MPU_REGION MPU_REGION_7 | ||
109 | #endif | ||
110 | |||
111 | /** | ||
112 | * @brief Stack size for the system idle thread. | ||
113 | * @details This size depends on the idle thread implementation, usually | ||
114 | * the idle thread should take no more space than those reserved | ||
115 | * by @p PORT_INT_REQUIRED_STACK. | ||
116 | * @note In this port it is set to 16 because the idle thread does have | ||
117 | * a stack frame when compiling without optimizations. You may | ||
118 | * reduce this value to zero when compiling with optimizations. | ||
119 | */ | ||
120 | #if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__) | ||
121 | #define PORT_IDLE_THREAD_STACK_SIZE 16 | ||
122 | #endif | ||
123 | |||
124 | /** | ||
125 | * @brief Per-thread stack overhead for interrupts servicing. | ||
126 | * @details This constant is used in the calculation of the correct working | ||
127 | * area size. | ||
128 | * @note In this port this value is conservatively set to 64 because the | ||
129 | * function @p chSchDoReschedule() can have a stack frame, especially | ||
130 | * with compiler optimizations disabled. The value can be reduced | ||
131 | * when compiler optimizations are enabled. | ||
132 | */ | ||
133 | #if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__) | ||
134 | #define PORT_INT_REQUIRED_STACK 64 | ||
135 | #endif | ||
136 | |||
137 | /** | ||
138 | * @brief Enables the use of the WFI instruction in the idle thread loop. | ||
139 | */ | ||
140 | #if !defined(CORTEX_ENABLE_WFI_IDLE) | ||
141 | #define CORTEX_ENABLE_WFI_IDLE FALSE | ||
142 | #endif | ||
143 | |||
144 | /** | ||
145 | * @brief FPU support in context switch. | ||
146 | * @details Activating this option activates the FPU support in the kernel. | ||
147 | */ | ||
148 | #if !defined(CORTEX_USE_FPU) | ||
149 | #define CORTEX_USE_FPU CORTEX_HAS_FPU | ||
150 | #elif (CORTEX_USE_FPU == TRUE) && (CORTEX_HAS_FPU == FALSE) | ||
151 | /* This setting requires an FPU presence check in case it is externally | ||
152 | redefined.*/ | ||
153 | #error "the selected core does not have an FPU" | ||
154 | #endif | ||
155 | |||
156 | /** | ||
157 | * @brief Simplified priority handling flag. | ||
158 | * @details Activating this option makes the Kernel work in compact mode. | ||
159 | * In compact mode interrupts are disabled globally instead of | ||
160 | * raising the priority mask to some intermediate level. | ||
161 | */ | ||
162 | #if !defined(CORTEX_SIMPLIFIED_PRIORITY) | ||
163 | #define CORTEX_SIMPLIFIED_PRIORITY FALSE | ||
164 | #endif | ||
165 | |||
166 | /** | ||
167 | * @brief SVCALL handler priority. | ||
168 | * @note The default SVCALL handler priority is defaulted to | ||
169 | * @p CORTEX_MAXIMUM_PRIORITY+1, this reserves the | ||
170 | * @p CORTEX_MAXIMUM_PRIORITY priority level as fast interrupts | ||
171 | * priority level. | ||
172 | */ | ||
173 | #if !defined(CORTEX_PRIORITY_SVCALL) | ||
174 | #define CORTEX_PRIORITY_SVCALL (CORTEX_MAXIMUM_PRIORITY + 1U) | ||
175 | #elif !PORT_IRQ_IS_VALID_PRIORITY(CORTEX_PRIORITY_SVCALL) | ||
176 | /* If it is externally redefined then better perform a validity check on it.*/ | ||
177 | #error "invalid priority level specified for CORTEX_PRIORITY_SVCALL" | ||
178 | #endif | ||
179 | |||
180 | /** | ||
181 | * @brief NVIC PRIGROUP initialization expression. | ||
182 | * @details The default assigns all available priority bits as preemption | ||
183 | * priority with no sub-priority. | ||
184 | */ | ||
185 | #if !defined(CORTEX_PRIGROUP_INIT) || defined(__DOXYGEN__) | ||
186 | #define CORTEX_PRIGROUP_INIT (7 - CORTEX_PRIORITY_BITS) | ||
187 | #endif | ||
188 | |||
189 | /*===========================================================================*/ | ||
190 | /* Derived constants and error checks. */ | ||
191 | /*===========================================================================*/ | ||
192 | |||
193 | #if (PORT_SWITCHED_REGIONS_NUMBER < 0) || (PORT_SWITCHED_REGIONS_NUMBER > 4) | ||
194 | #error "invalid PORT_SWITCHED_REGIONS_NUMBER value" | ||
195 | #endif | ||
196 | |||
197 | #if !defined(_FROM_ASM_) | ||
198 | /** | ||
199 | * @brief MPU guard page size. | ||
200 | */ | ||
201 | #if (PORT_ENABLE_GUARD_PAGES == TRUE) || defined(__DOXYGEN__) | ||
202 | #if CH_DBG_ENABLE_STACK_CHECK == FALSE | ||
203 | #error "PORT_ENABLE_GUARD_PAGES requires CH_DBG_ENABLE_STACK_CHECK" | ||
204 | #endif | ||
205 | #if __MPU_PRESENT == 0 | ||
206 | #error "MPU not present in current device" | ||
207 | #endif | ||
208 | #define PORT_GUARD_PAGE_SIZE 32U | ||
209 | #else | ||
210 | #define PORT_GUARD_PAGE_SIZE 0U | ||
211 | #endif | ||
212 | #endif /* !defined(_FROM_ASM_) */ | ||
213 | |||
214 | /** | ||
215 | * @name Architecture and Compiler | ||
216 | * @{ | ||
217 | */ | ||
218 | #if (CORTEX_MODEL == 3) || defined(__DOXYGEN__) | ||
219 | |||
220 | #if !defined(CH_CUSTOMER_LIC_PORT_CM3) | ||
221 | #error "CH_CUSTOMER_LIC_PORT_CM3 not defined" | ||
222 | #endif | ||
223 | |||
224 | #if CH_CUSTOMER_LIC_PORT_CM3 == FALSE | ||
225 | #error "ChibiOS Cortex-M3 port not licensed" | ||
226 | #endif | ||
227 | |||
228 | /** | ||
229 | * @brief Macro defining the specific ARM architecture. | ||
230 | */ | ||
231 | #define PORT_ARCHITECTURE_ARM_v7M | ||
232 | |||
233 | /** | ||
234 | * @brief Name of the implemented architecture. | ||
235 | */ | ||
236 | #define PORT_ARCHITECTURE_NAME "ARMv7-M" | ||
237 | |||
238 | /** | ||
239 | * @brief Name of the architecture variant. | ||
240 | */ | ||
241 | #if (PORT_ENABLE_GUARD_PAGES == FALSE) || defined(__DOXYGEN__) | ||
242 | #define PORT_CORE_VARIANT_NAME "Cortex-M3" | ||
243 | #else | ||
244 | #define PORT_CORE_VARIANT_NAME "Cortex-M3 (MPU)" | ||
245 | #endif | ||
246 | |||
247 | #elif (CORTEX_MODEL == 4) | ||
248 | |||
249 | #if !defined(CH_CUSTOMER_LIC_PORT_CM4) | ||
250 | #error "CH_CUSTOMER_LIC_PORT_CM4 not defined" | ||
251 | #endif | ||
252 | |||
253 | #if CH_CUSTOMER_LIC_PORT_CM4 == FALSE | ||
254 | #error "ChibiOS Cortex-M4 port not licensed" | ||
255 | #endif | ||
256 | |||
257 | #define PORT_ARCHITECTURE_ARM_v7ME | ||
258 | #define PORT_ARCHITECTURE_NAME "ARMv7E-M" | ||
259 | #if CORTEX_USE_FPU | ||
260 | #if PORT_ENABLE_GUARD_PAGES == FALSE | ||
261 | #define PORT_CORE_VARIANT_NAME "Cortex-M4F" | ||
262 | #else | ||
263 | #define PORT_CORE_VARIANT_NAME "Cortex-M4F (MPU)" | ||
264 | #endif | ||
265 | #else | ||
266 | #if PORT_ENABLE_GUARD_PAGES == FALSE | ||
267 | #define PORT_CORE_VARIANT_NAME "Cortex-M4" | ||
268 | #else | ||
269 | #define PORT_CORE_VARIANT_NAME "Cortex-M4 (MPU)" | ||
270 | #endif | ||
271 | #endif | ||
272 | |||
273 | #elif (CORTEX_MODEL == 7) | ||
274 | |||
275 | #if !defined(CH_CUSTOMER_LIC_PORT_CM7) | ||
276 | #error "CH_CUSTOMER_LIC_PORT_CM7 not defined" | ||
277 | #endif | ||
278 | |||
279 | #if CH_CUSTOMER_LIC_PORT_CM7 == FALSE | ||
280 | #error "ChibiOS Cortex-M7 port not licensed" | ||
281 | #endif | ||
282 | |||
283 | #define PORT_ARCHITECTURE_ARM_v7ME | ||
284 | #define PORT_ARCHITECTURE_NAME "ARMv7E-M" | ||
285 | #if CORTEX_USE_FPU | ||
286 | #if PORT_ENABLE_GUARD_PAGES == FALSE | ||
287 | #define PORT_CORE_VARIANT_NAME "Cortex-M7F" | ||
288 | #else | ||
289 | #define PORT_CORE_VARIANT_NAME "Cortex-M7F (MPU)" | ||
290 | #endif | ||
291 | #else | ||
292 | #if PORT_ENABLE_GUARD_PAGES == FALSE | ||
293 | #define PORT_CORE_VARIANT_NAME "Cortex-M7" | ||
294 | #else | ||
295 | #define PORT_CORE_VARIANT_NAME "Cortex-M7 (MPU)" | ||
296 | #endif | ||
297 | #endif | ||
298 | #endif | ||
299 | |||
300 | /** | ||
301 | * @brief Port-specific information string. | ||
302 | */ | ||
303 | #if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__) | ||
304 | #define PORT_INFO "Advanced kernel mode" | ||
305 | #else | ||
306 | #define PORT_INFO "Compact kernel mode" | ||
307 | #endif | ||
308 | /** @} */ | ||
309 | |||
310 | #if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__) | ||
311 | /** | ||
312 | * @brief Maximum usable priority for normal ISRs. | ||
313 | */ | ||
314 | #define CORTEX_MAX_KERNEL_PRIORITY (CORTEX_PRIORITY_SVCALL + 1U) | ||
315 | |||
316 | /** | ||
317 | * @brief BASEPRI level within kernel lock. | ||
318 | */ | ||
319 | #define CORTEX_BASEPRI_KERNEL \ | ||
320 | CORTEX_PRIO_MASK(CORTEX_MAX_KERNEL_PRIORITY) | ||
321 | #else | ||
322 | |||
323 | #define CORTEX_MAX_KERNEL_PRIORITY 0U | ||
324 | #endif | ||
325 | |||
326 | /** | ||
327 | * @brief PendSV priority level. | ||
328 | * @note This priority is enforced to be equal to | ||
329 | * @p CORTEX_MAX_KERNEL_PRIORITY, this handler always have the | ||
330 | * highest priority that cannot preempt the kernel. | ||
331 | */ | ||
332 | #define CORTEX_PRIORITY_PENDSV CORTEX_MAX_KERNEL_PRIORITY | ||
333 | |||
334 | /*===========================================================================*/ | ||
335 | /* Module data structures and types. */ | ||
336 | /*===========================================================================*/ | ||
337 | |||
338 | /* The following code is not processed when the file is included from an | ||
339 | asm module.*/ | ||
340 | #if !defined(_FROM_ASM_) | ||
341 | |||
342 | /* The documentation of the following declarations is in chconf.h in order | ||
343 | to not have duplicated structure names into the documentation.*/ | ||
344 | #if !defined(__DOXYGEN__) | ||
345 | struct port_extctx { | ||
346 | uint32_t r0; | ||
347 | uint32_t r1; | ||
348 | uint32_t r2; | ||
349 | uint32_t r3; | ||
350 | uint32_t r12; | ||
351 | uint32_t lr_thd; | ||
352 | uint32_t pc; | ||
353 | uint32_t xpsr; | ||
354 | #if CORTEX_USE_FPU | ||
355 | uint32_t s0; | ||
356 | uint32_t s1; | ||
357 | uint32_t s2; | ||
358 | uint32_t s3; | ||
359 | uint32_t s4; | ||
360 | uint32_t s5; | ||
361 | uint32_t s6; | ||
362 | uint32_t s7; | ||
363 | uint32_t s8; | ||
364 | uint32_t s9; | ||
365 | uint32_t s10; | ||
366 | uint32_t s11; | ||
367 | uint32_t s12; | ||
368 | uint32_t s13; | ||
369 | uint32_t s14; | ||
370 | uint32_t s15; | ||
371 | uint32_t fpscr; | ||
372 | uint32_t reserved; | ||
373 | #endif /* CORTEX_USE_FPU */ | ||
374 | }; | ||
375 | |||
376 | #if (PORT_USE_SYSCALL == TRUE) || defined(__DOXYGEN__) | ||
377 | /** | ||
378 | * @brief Link context structure. | ||
379 | * @details This structure is used when there is the need to save extra | ||
380 | * context information that is not part of the registers stacked | ||
381 | * in HW. | ||
382 | */ | ||
383 | struct port_linkctx { | ||
384 | uint32_t control; | ||
385 | struct port_extctx *ectxp; | ||
386 | }; | ||
387 | #endif | ||
388 | |||
389 | struct port_intctx { | ||
390 | #if (PORT_SWITCHED_REGIONS_NUMBER > 0) || defined(__DOXYGEN__) | ||
391 | struct { | ||
392 | uint32_t rbar; | ||
393 | uint32_t rasr; | ||
394 | } regions[PORT_SWITCHED_REGIONS_NUMBER]; | ||
395 | #endif | ||
396 | #if CORTEX_USE_FPU | ||
397 | uint32_t s16; | ||
398 | uint32_t s17; | ||
399 | uint32_t s18; | ||
400 | uint32_t s19; | ||
401 | uint32_t s20; | ||
402 | uint32_t s21; | ||
403 | uint32_t s22; | ||
404 | uint32_t s23; | ||
405 | uint32_t s24; | ||
406 | uint32_t s25; | ||
407 | uint32_t s26; | ||
408 | uint32_t s27; | ||
409 | uint32_t s28; | ||
410 | uint32_t s29; | ||
411 | uint32_t s30; | ||
412 | uint32_t s31; | ||
413 | #endif /* CORTEX_USE_FPU */ | ||
414 | uint32_t r4; | ||
415 | uint32_t r5; | ||
416 | uint32_t r6; | ||
417 | uint32_t r7; | ||
418 | uint32_t r8; | ||
419 | uint32_t r9; | ||
420 | uint32_t r10; | ||
421 | uint32_t r11; | ||
422 | uint32_t lr; | ||
423 | }; | ||
424 | |||
425 | struct port_context { | ||
426 | struct port_intctx *sp; | ||
427 | #if (PORT_USE_SYSCALL == TRUE) || defined(__DOXYGEN__) | ||
428 | struct { | ||
429 | uint32_t psp; | ||
430 | const void *p; | ||
431 | } syscall; | ||
432 | #endif | ||
433 | }; | ||
434 | #endif /* !defined(__DOXYGEN__) */ | ||
435 | |||
436 | /*===========================================================================*/ | ||
437 | /* Module macros. */ | ||
438 | /*===========================================================================*/ | ||
439 | |||
440 | /* By default threads have no syscall context information.*/ | ||
441 | #if (PORT_USE_SYSCALL == TRUE) || defined(__DOXYGEN__) | ||
442 | #define __PORT_SETUP_CONTEXT_SYSCALL(tp, wtop) \ | ||
443 | (tp)->ctx.syscall.psp = (uint32_t)(wtop); \ | ||
444 | (tp)->ctx.syscall.p = NULL; | ||
445 | #else | ||
446 | #define __PORT_SETUP_CONTEXT_SYSCALL(tp, wtop) | ||
447 | #endif | ||
448 | |||
449 | /* By default threads have all regions disabled.*/ | ||
450 | #if (PORT_SWITCHED_REGIONS_NUMBER == 0) || defined(__DOXYGEN__) | ||
451 | #define __PORT_SETUP_CONTEXT_MPU(tp) | ||
452 | #elif (PORT_SWITCHED_REGIONS_NUMBER == 1) || defined(__DOXYGEN__) | ||
453 | #define __PORT_SETUP_CONTEXT_MPU(tp) \ | ||
454 | (tp)->ctx.sp->regions[0].rbar = 0U; \ | ||
455 | (tp)->ctx.sp->regions[0].rasr = 0U | ||
456 | #elif (PORT_SWITCHED_REGIONS_NUMBER == 2) || defined(__DOXYGEN__) | ||
457 | #define __PORT_SETUP_CONTEXT_MPU(tp) \ | ||
458 | (tp)->ctx.sp->regions[0].rbar = 0U; \ | ||
459 | (tp)->ctx.sp->regions[0].rasr = 0U; \ | ||
460 | (tp)->ctx.sp->regions[1].rbar = 0U; \ | ||
461 | (tp)->ctx.sp->regions[1].rasr = 0U | ||
462 | #elif (PORT_SWITCHED_REGIONS_NUMBER == 3) || defined(__DOXYGEN__) | ||
463 | #define __PORT_SETUP_CONTEXT_MPU(tp) \ | ||
464 | (tp)->ctx.sp->regions[0].rbar = 0U; \ | ||
465 | (tp)->ctx.sp->regions[0].rasr = 0U; \ | ||
466 | (tp)->ctx.sp->regions[1].rbar = 0U; \ | ||
467 | (tp)->ctx.sp->regions[1].rasr = 0U; \ | ||
468 | (tp)->ctx.sp->regions[2].rbar = 0U; \ | ||
469 | (tp)->ctx.sp->regions[2].rasr = 0U | ||
470 | #elif (PORT_SWITCHED_REGIONS_NUMBER == 4) || defined(__DOXYGEN__) | ||
471 | #define __PORT_SETUP_CONTEXT_MPU(tp) \ | ||
472 | (tp)->ctx.sp->regions[0].rbar = 0U; \ | ||
473 | (tp)->ctx.sp->regions[0].rasr = 0U; \ | ||
474 | (tp)->ctx.sp->regions[1].rbar = 0U; \ | ||
475 | (tp)->ctx.sp->regions[1].rasr = 0U; \ | ||
476 | (tp)->ctx.sp->regions[2].rbar = 0U; \ | ||
477 | (tp)->ctx.sp->regions[2].rasr = 0U; \ | ||
478 | (tp)->ctx.sp->regions[3].rbar = 0U; \ | ||
479 | (tp)->ctx.sp->regions[3].rasr = 0U | ||
480 | #else | ||
481 | #endif | ||
482 | |||
483 | /** | ||
484 | * @brief Platform dependent part of the @p chThdCreateI() API. | ||
485 | * @details This code usually setup the context switching frame represented | ||
486 | * by an @p port_intctx structure. | ||
487 | */ | ||
488 | #define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \ | ||
489 | (tp)->ctx.sp = (struct port_intctx *)((uint8_t *)(wtop) - \ | ||
490 | sizeof (struct port_intctx)); \ | ||
491 | (tp)->ctx.sp->r4 = (uint32_t)(pf); \ | ||
492 | (tp)->ctx.sp->r5 = (uint32_t)(arg); \ | ||
493 | (tp)->ctx.sp->lr = (uint32_t)_port_thread_start; \ | ||
494 | __PORT_SETUP_CONTEXT_MPU(tp); \ | ||
495 | __PORT_SETUP_CONTEXT_SYSCALL(tp, wtop); \ | ||
496 | } | ||
497 | |||
498 | // __PORT_SETUP_CONTEXT_MPU(tp) | ||
499 | |||
500 | /** | ||
501 | * @brief Computes the thread working area global size. | ||
502 | * @note There is no need to perform alignments in this macro. | ||
503 | */ | ||
504 | #define PORT_WA_SIZE(n) ((size_t)PORT_GUARD_PAGE_SIZE + \ | ||
505 | sizeof (struct port_intctx) + \ | ||
506 | sizeof (struct port_extctx) + \ | ||
507 | (size_t)(n) + \ | ||
508 | (size_t)PORT_INT_REQUIRED_STACK) | ||
509 | |||
510 | /** | ||
511 | * @brief Static working area allocation. | ||
512 | * @details This macro is used to allocate a static thread working area | ||
513 | * aligned as both position and size. | ||
514 | * | ||
515 | * @param[in] s the name to be assigned to the stack array | ||
516 | * @param[in] n the stack size to be assigned to the thread | ||
517 | */ | ||
518 | #if (PORT_ENABLE_GUARD_PAGES == FALSE) || defined(__DOXYGEN__) | ||
519 | #define PORT_WORKING_AREA(s, n) \ | ||
520 | stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)] | ||
521 | #else | ||
522 | #define PORT_WORKING_AREA(s, n) \ | ||
523 | ALIGNED_VAR(32) stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)] | ||
524 | #endif | ||
525 | |||
526 | /** | ||
527 | * @brief IRQ prologue code. | ||
528 | * @details This macro must be inserted at the start of all IRQ handlers | ||
529 | * enabled to invoke system APIs. | ||
530 | */ | ||
531 | #define PORT_IRQ_PROLOGUE() | ||
532 | |||
533 | /** | ||
534 | * @brief IRQ epilogue code. | ||
535 | * @details This macro must be inserted at the end of all IRQ handlers | ||
536 | * enabled to invoke system APIs. | ||
537 | */ | ||
538 | #define PORT_IRQ_EPILOGUE() _port_irq_epilogue() | ||
539 | |||
540 | /** | ||
541 | * @brief IRQ handler function declaration. | ||
542 | * @note @p id can be a function name or a vector number depending on the | ||
543 | * port implementation. | ||
544 | */ | ||
545 | #ifdef __cplusplus | ||
546 | #define PORT_IRQ_HANDLER(id) extern "C" void id(void) | ||
547 | #else | ||
548 | #define PORT_IRQ_HANDLER(id) void id(void) | ||
549 | #endif | ||
550 | |||
551 | /** | ||
552 | * @brief Fast IRQ handler function declaration. | ||
553 | * @note @p id can be a function name or a vector number depending on the | ||
554 | * port implementation. | ||
555 | */ | ||
556 | #ifdef __cplusplus | ||
557 | #define PORT_FAST_IRQ_HANDLER(id) extern "C" void id(void) | ||
558 | #else | ||
559 | #define PORT_FAST_IRQ_HANDLER(id) void id(void) | ||
560 | #endif | ||
561 | |||
562 | /** | ||
563 | * @brief Performs a context switch between two threads. | ||
564 | * @details This is the most critical code in any port, this function | ||
565 | * is responsible for the context switch between 2 threads. | ||
566 | * @note The implementation of this code affects <b>directly</b> the context | ||
567 | * switch performance so optimize here as much as you can. | ||
568 | * | ||
569 | * @param[in] ntp the thread to be switched in | ||
570 | * @param[in] otp the thread to be switched out | ||
571 | */ | ||
572 | #if (CH_DBG_ENABLE_STACK_CHECK == FALSE) || defined(__DOXYGEN__) | ||
573 | #define port_switch(ntp, otp) _port_switch(ntp, otp) | ||
574 | #else | ||
575 | #if PORT_ENABLE_GUARD_PAGES == FALSE | ||
576 | #define port_switch(ntp, otp) { \ | ||
577 | struct port_intctx *r13 = (struct port_intctx *)__get_PSP(); \ | ||
578 | if ((stkalign_t *)(r13 - 1) < (otp)->wabase) { \ | ||
579 | chSysHalt("stack overflow"); \ | ||
580 | } \ | ||
581 | _port_switch(ntp, otp); \ | ||
582 | } | ||
583 | #else | ||
584 | #define port_switch(ntp, otp) { \ | ||
585 | _port_switch(ntp, otp); \ | ||
586 | \ | ||
587 | /* Setting up the guard page for the switched-in thread.*/ \ | ||
588 | mpuSetRegionAddress(PORT_USE_GUARD_MPU_REGION, \ | ||
589 | chThdGetSelfX()->wabase); \ | ||
590 | } | ||
591 | #endif | ||
592 | #endif | ||
593 | |||
594 | /*===========================================================================*/ | ||
595 | /* External declarations. */ | ||
596 | /*===========================================================================*/ | ||
597 | |||
598 | #ifdef __cplusplus | ||
599 | extern "C" { | ||
600 | #endif | ||
601 | void port_init(void); | ||
602 | void _port_irq_epilogue(void); | ||
603 | void _port_switch(thread_t *ntp, thread_t *otp); | ||
604 | void _port_thread_start(void); | ||
605 | void _port_switch_from_isr(void); | ||
606 | void _port_exit_from_isr(void); | ||
607 | #if PORT_USE_SYSCALL == TRUE | ||
608 | void port_unprivileged_jump(uint32_t pc, uint32_t psp); | ||
609 | #endif | ||
610 | #ifdef __cplusplus | ||
611 | } | ||
612 | #endif | ||
613 | |||
614 | /*===========================================================================*/ | ||
615 | /* Module inline functions. */ | ||
616 | /*===========================================================================*/ | ||
617 | |||
618 | /** | ||
619 | * @brief Returns a word encoding the current interrupts status. | ||
620 | * | ||
621 | * @return The interrupts status. | ||
622 | */ | ||
623 | __STATIC_FORCEINLINE syssts_t port_get_irq_status(void) { | ||
624 | syssts_t sts; | ||
625 | |||
626 | #if CORTEX_SIMPLIFIED_PRIORITY == FALSE | ||
627 | sts = (syssts_t)__get_BASEPRI(); | ||
628 | #else /* CORTEX_SIMPLIFIED_PRIORITY */ | ||
629 | sts = (syssts_t)__get_PRIMASK(); | ||
630 | #endif /* CORTEX_SIMPLIFIED_PRIORITY */ | ||
631 | return sts; | ||
632 | } | ||
633 | |||
634 | /** | ||
635 | * @brief Checks the interrupt status. | ||
636 | * | ||
637 | * @param[in] sts the interrupt status word | ||
638 | * | ||
639 | * @return The interrupt status. | ||
640 | * @retval false the word specified a disabled interrupts status. | ||
641 | * @retval true the word specified an enabled interrupts status. | ||
642 | */ | ||
643 | __STATIC_FORCEINLINE bool port_irq_enabled(syssts_t sts) { | ||
644 | |||
645 | #if CORTEX_SIMPLIFIED_PRIORITY == FALSE | ||
646 | return sts == (syssts_t)CORTEX_BASEPRI_DISABLED; | ||
647 | #else /* CORTEX_SIMPLIFIED_PRIORITY */ | ||
648 | return (sts & (syssts_t)1) == (syssts_t)0; | ||
649 | #endif /* CORTEX_SIMPLIFIED_PRIORITY */ | ||
650 | } | ||
651 | |||
652 | /** | ||
653 | * @brief Determines the current execution context. | ||
654 | * | ||
655 | * @return The execution context. | ||
656 | * @retval false not running in ISR mode. | ||
657 | * @retval true running in ISR mode. | ||
658 | */ | ||
659 | __STATIC_FORCEINLINE bool port_is_isr_context(void) { | ||
660 | |||
661 | return (bool)((__get_IPSR() & 0x1FFU) != 0U); | ||
662 | } | ||
663 | |||
664 | /** | ||
665 | * @brief Kernel-lock action. | ||
666 | * @details In this port this function raises the base priority to kernel | ||
667 | * level. | ||
668 | */ | ||
669 | __STATIC_FORCEINLINE void port_lock(void) { | ||
670 | |||
671 | #if CORTEX_SIMPLIFIED_PRIORITY == FALSE | ||
672 | #if defined(__CM7_REV) | ||
673 | #if __CM7_REV <= 1 | ||
674 | __disable_irq(); | ||
675 | #endif | ||
676 | #endif | ||
677 | __set_BASEPRI(CORTEX_BASEPRI_KERNEL); | ||
678 | #if defined(__CM7_REV) | ||
679 | #if __CM7_REV <= 1 | ||
680 | __enable_irq(); | ||
681 | #endif | ||
682 | #endif | ||
683 | #else /* CORTEX_SIMPLIFIED_PRIORITY */ | ||
684 | __disable_irq(); | ||
685 | #endif /* CORTEX_SIMPLIFIED_PRIORITY */ | ||
686 | } | ||
687 | |||
688 | /** | ||
689 | * @brief Kernel-unlock action. | ||
690 | * @details In this port this function lowers the base priority to user | ||
691 | * level. | ||
692 | */ | ||
693 | __STATIC_FORCEINLINE void port_unlock(void) { | ||
694 | |||
695 | #if CORTEX_SIMPLIFIED_PRIORITY == FALSE | ||
696 | __set_BASEPRI(CORTEX_BASEPRI_DISABLED); | ||
697 | #else /* CORTEX_SIMPLIFIED_PRIORITY */ | ||
698 | __enable_irq(); | ||
699 | #endif /* CORTEX_SIMPLIFIED_PRIORITY */ | ||
700 | } | ||
701 | |||
702 | /** | ||
703 | * @brief Kernel-lock action from an interrupt handler. | ||
704 | * @details In this port this function raises the base priority to kernel | ||
705 | * level. | ||
706 | * @note Same as @p port_lock() in this port. | ||
707 | */ | ||
708 | __STATIC_FORCEINLINE void port_lock_from_isr(void) { | ||
709 | |||
710 | port_lock(); | ||
711 | } | ||
712 | |||
713 | /** | ||
714 | * @brief Kernel-unlock action from an interrupt handler. | ||
715 | * @details In this port this function lowers the base priority to user | ||
716 | * level. | ||
717 | * @note Same as @p port_unlock() in this port. | ||
718 | */ | ||
719 | __STATIC_FORCEINLINE void port_unlock_from_isr(void) { | ||
720 | |||
721 | port_unlock(); | ||
722 | } | ||
723 | |||
724 | /** | ||
725 | * @brief Disables all the interrupt sources. | ||
726 | * @note In this port it disables all the interrupt sources by raising | ||
727 | * the priority mask to level 0. | ||
728 | */ | ||
729 | __STATIC_FORCEINLINE void port_disable(void) { | ||
730 | |||
731 | __disable_irq(); | ||
732 | } | ||
733 | |||
734 | /** | ||
735 | * @brief Disables the interrupt sources below kernel-level priority. | ||
736 | * @note Interrupt sources above kernel level remains enabled. | ||
737 | * @note In this port it raises/lowers the base priority to kernel level. | ||
738 | */ | ||
739 | __STATIC_FORCEINLINE void port_suspend(void) { | ||
740 | |||
741 | #if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__) | ||
742 | __set_BASEPRI(CORTEX_BASEPRI_KERNEL); | ||
743 | __enable_irq(); | ||
744 | #else | ||
745 | __disable_irq(); | ||
746 | #endif | ||
747 | } | ||
748 | |||
749 | /** | ||
750 | * @brief Enables all the interrupt sources. | ||
751 | * @note In this port it lowers the base priority to user level. | ||
752 | */ | ||
753 | __STATIC_FORCEINLINE void port_enable(void) { | ||
754 | |||
755 | #if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__) | ||
756 | __set_BASEPRI(CORTEX_BASEPRI_DISABLED); | ||
757 | #endif | ||
758 | __enable_irq(); | ||
759 | } | ||
760 | |||
761 | /** | ||
762 | * @brief Enters an architecture-dependent IRQ-waiting mode. | ||
763 | * @details The function is meant to return when an interrupt becomes pending. | ||
764 | * The simplest implementation is an empty function or macro but this | ||
765 | * would not take advantage of architecture-specific power saving | ||
766 | * modes. | ||
767 | * @note Implemented as an inlined @p WFI instruction. | ||
768 | */ | ||
769 | __STATIC_FORCEINLINE void port_wait_for_interrupt(void) { | ||
770 | |||
771 | #if CORTEX_ENABLE_WFI_IDLE == TRUE | ||
772 | __WFI(); | ||
773 | #endif | ||
774 | } | ||
775 | |||
776 | /** | ||
777 | * @brief Returns the current value of the realtime counter. | ||
778 | * | ||
779 | * @return The realtime counter value. | ||
780 | */ | ||
781 | __STATIC_FORCEINLINE rtcnt_t port_rt_get_counter_value(void) { | ||
782 | |||
783 | return DWT->CYCCNT; | ||
784 | } | ||
785 | |||
786 | #endif /* !defined(_FROM_ASM_) */ | ||
787 | |||
788 | #endif /* CHCORE_V7M_H */ | ||
789 | |||
790 | /** @} */ | ||
diff --git a/lib/chibios/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.S b/lib/chibios/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.S new file mode 100644 index 000000000..dec9122e6 --- /dev/null +++ b/lib/chibios/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.S | |||
@@ -0,0 +1,154 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file compilers/GCC/chcoreasm_v6m.S | ||
22 | * @brief ARMv6-M architecture port low level code. | ||
23 | * | ||
24 | * @addtogroup ARMCMx_GCC_CORE | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #if !defined(FALSE) || defined(__DOXYGEN__) | ||
29 | #define FALSE 0 | ||
30 | #endif | ||
31 | |||
32 | #if !defined(TRUE) || defined(__DOXYGEN__) | ||
33 | #define TRUE 1 | ||
34 | #endif | ||
35 | |||
36 | #define _FROM_ASM_ | ||
37 | #include "chlicense.h" | ||
38 | #include "chconf.h" | ||
39 | #include "chcore.h" | ||
40 | |||
41 | #if !defined(__DOXYGEN__) | ||
42 | |||
43 | /* | ||
44 | * RTOS-specific context offset. | ||
45 | */ | ||
46 | #if defined(_CHIBIOS_RT_CONF_) | ||
47 | #define CONTEXT_OFFSET 12 | ||
48 | #elif defined(_CHIBIOS_NIL_CONF_) | ||
49 | #define CONTEXT_OFFSET 0 | ||
50 | #else | ||
51 | #error "invalid chconf.h" | ||
52 | #endif | ||
53 | |||
54 | .set SCB_ICSR, 0xE000ED04 | ||
55 | .set ICSR_PENDSVSET, 0x10000000 | ||
56 | .set ICSR_NMIPENDSET, 0x80000000 | ||
57 | |||
58 | .cpu cortex-m0 | ||
59 | .fpu softvfp | ||
60 | |||
61 | .thumb | ||
62 | .text | ||
63 | |||
64 | /*--------------------------------------------------------------------------* | ||
65 | * Performs a context switch between two threads. | ||
66 | *--------------------------------------------------------------------------*/ | ||
67 | .thumb_func | ||
68 | .globl _port_switch | ||
69 | _port_switch: | ||
70 | push {r4, r5, r6, r7, lr} | ||
71 | mov r4, r8 | ||
72 | mov r5, r9 | ||
73 | mov r6, r10 | ||
74 | mov r7, r11 | ||
75 | push {r4, r5, r6, r7} | ||
76 | |||
77 | mov r3, sp | ||
78 | str r3, [r1, #CONTEXT_OFFSET] | ||
79 | ldr r3, [r0, #CONTEXT_OFFSET] | ||
80 | mov sp, r3 | ||
81 | |||
82 | pop {r4, r5, r6, r7} | ||
83 | mov r8, r4 | ||
84 | mov r9, r5 | ||
85 | mov r10, r6 | ||
86 | mov r11, r7 | ||
87 | pop {r4, r5, r6, r7, pc} | ||
88 | |||
89 | /*--------------------------------------------------------------------------* | ||
90 | * Start a thread by invoking its work function. | ||
91 | * | ||
92 | * Threads execution starts here, the code leaves the system critical zone | ||
93 | * and then jumps into the thread function passed in register R4. The | ||
94 | * register R5 contains the thread parameter. The function chThdExit() is | ||
95 | * called on thread function return. | ||
96 | *--------------------------------------------------------------------------*/ | ||
97 | .thumb_func | ||
98 | .globl _port_thread_start | ||
99 | _port_thread_start: | ||
100 | #if CH_DBG_SYSTEM_STATE_CHECK | ||
101 | bl _dbg_check_unlock | ||
102 | #endif | ||
103 | #if CH_DBG_STATISTICS | ||
104 | bl _stats_stop_measure_crit_thd | ||
105 | #endif | ||
106 | cpsie i | ||
107 | mov r0, r5 | ||
108 | blx r4 | ||
109 | movs r0, #0 /* MSG_OK */ | ||
110 | bl chThdExit | ||
111 | _zombies: b _zombies | ||
112 | |||
113 | /*--------------------------------------------------------------------------* | ||
114 | * Post-IRQ switch code. | ||
115 | * | ||
116 | * Exception handlers return here for context switching. | ||
117 | *--------------------------------------------------------------------------*/ | ||
118 | .thumb_func | ||
119 | .globl _port_switch_from_isr | ||
120 | _port_switch_from_isr: | ||
121 | #if CH_DBG_STATISTICS | ||
122 | bl _stats_start_measure_crit_thd | ||
123 | #endif | ||
124 | #if CH_DBG_SYSTEM_STATE_CHECK | ||
125 | bl _dbg_check_lock | ||
126 | #endif | ||
127 | bl chSchDoReschedule | ||
128 | #if CH_DBG_SYSTEM_STATE_CHECK | ||
129 | bl _dbg_check_unlock | ||
130 | #endif | ||
131 | #if CH_DBG_STATISTICS | ||
132 | bl _stats_stop_measure_crit_thd | ||
133 | #endif | ||
134 | .globl _port_exit_from_isr | ||
135 | _port_exit_from_isr: | ||
136 | ldr r2, .L2 | ||
137 | ldr r3, .L3 | ||
138 | str r3, [r2, #0] | ||
139 | #if CORTEX_ALTERNATE_SWITCH | ||
140 | cpsie i | ||
141 | #endif | ||
142 | .L1: b .L1 | ||
143 | |||
144 | .align 2 | ||
145 | .L2: .word SCB_ICSR | ||
146 | #if CORTEX_ALTERNATE_SWITCH | ||
147 | .L3: .word ICSR_PENDSVSET | ||
148 | #else | ||
149 | .L3: .word ICSR_NMIPENDSET | ||
150 | #endif | ||
151 | |||
152 | #endif /* !defined(__DOXYGEN__) */ | ||
153 | |||
154 | /** @} */ | ||
diff --git a/lib/chibios/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.S b/lib/chibios/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.S new file mode 100644 index 000000000..c2b9fc777 --- /dev/null +++ b/lib/chibios/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.S | |||
@@ -0,0 +1,242 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file compilers/GCC/chcoreasm_v7m.S | ||
22 | * @brief ARMv7-M architecture port low level code. | ||
23 | * | ||
24 | * @addtogroup ARMCMx_GCC_CORE | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #if !defined(FALSE) || defined(__DOXYGEN__) | ||
29 | #define FALSE 0 | ||
30 | #endif | ||
31 | |||
32 | #if !defined(TRUE) || defined(__DOXYGEN__) | ||
33 | #define TRUE 1 | ||
34 | #endif | ||
35 | |||
36 | #define _FROM_ASM_ | ||
37 | #include "chlicense.h" | ||
38 | #include "chconf.h" | ||
39 | #include "chcore.h" | ||
40 | |||
41 | #if !defined(__DOXYGEN__) | ||
42 | |||
43 | /* | ||
44 | * RTOS-specific context offset. | ||
45 | */ | ||
46 | #if defined(_CHIBIOS_RT_CONF_) | ||
47 | #define CONTEXT_OFFSET 12 | ||
48 | #elif defined(_CHIBIOS_NIL_CONF_) | ||
49 | #define CONTEXT_OFFSET 0 | ||
50 | #else | ||
51 | #error "invalid chconf.h" | ||
52 | #endif | ||
53 | |||
54 | /* MPU-related constants.*/ | ||
55 | #define MPU_RBAR 0xE000ED9C | ||
56 | |||
57 | /* Other constants.*/ | ||
58 | #define SCB_ICSR 0xE000ED04 | ||
59 | #define ICSR_PENDSVSET 0x10000000 | ||
60 | |||
61 | .syntax unified | ||
62 | .cpu cortex-m4 | ||
63 | #if CORTEX_USE_FPU | ||
64 | .fpu fpv4-sp-d16 | ||
65 | #else | ||
66 | .fpu softvfp | ||
67 | #endif | ||
68 | |||
69 | .thumb | ||
70 | .text | ||
71 | |||
72 | /*--------------------------------------------------------------------------* | ||
73 | * Performs a context switch between two threads. | ||
74 | *--------------------------------------------------------------------------*/ | ||
75 | .thumb_func | ||
76 | .globl _port_switch | ||
77 | _port_switch: | ||
78 | push {r4, r5, r6, r7, r8, r9, r10, r11, lr} | ||
79 | #if CORTEX_USE_FPU | ||
80 | /* Saving FPU context.*/ | ||
81 | vpush {s16-s31} | ||
82 | #endif | ||
83 | |||
84 | #if PORT_SWITCHED_REGIONS_NUMBER > 0 | ||
85 | /* Saving MPU context.*/ | ||
86 | ldr r2, =MPU_RBAR | ||
87 | #if PORT_SWITCHED_REGIONS_NUMBER >= 1 | ||
88 | mov r3, #0 | ||
89 | str r3, [r2, #-4] /* RNR */ | ||
90 | ldm r2, {r4, r5} /* RBAR, RASR */ | ||
91 | #endif | ||
92 | #if PORT_SWITCHED_REGIONS_NUMBER >= 2 | ||
93 | add r3, #1 | ||
94 | str r3, [r2, #-4] /* RNR */ | ||
95 | ldm r2, {r6, r7} /* RBAR, RASR */ | ||
96 | #endif | ||
97 | #if PORT_SWITCHED_REGIONS_NUMBER >= 3 | ||
98 | add r3, #1 | ||
99 | str r3, [r2, #-4] /* RNR */ | ||
100 | ldm r2, {r8, r9} /* RBAR, RASR */ | ||
101 | #endif | ||
102 | #if PORT_SWITCHED_REGIONS_NUMBER >= 4 | ||
103 | add r3, #1 | ||
104 | str r3, [r2, #-4] /* RNR */ | ||
105 | ldm r2, {r10, r11} /* RBAR, RASR */ | ||
106 | #endif | ||
107 | #if PORT_SWITCHED_REGIONS_NUMBER == 1 | ||
108 | push {r4, r5} | ||
109 | #endif | ||
110 | #if PORT_SWITCHED_REGIONS_NUMBER == 2 | ||
111 | push {r4, r5, r6, r7} | ||
112 | #endif | ||
113 | #if PORT_SWITCHED_REGIONS_NUMBER == 3 | ||
114 | push {r4, r5, r6, r7, r8, r9} | ||
115 | #endif | ||
116 | #if PORT_SWITCHED_REGIONS_NUMBER == 4 | ||
117 | push {r4, r5, r6, r7, r8, r9, r10, r11} | ||
118 | #endif | ||
119 | #endif | ||
120 | |||
121 | str sp, [r1, #CONTEXT_OFFSET] | ||
122 | #if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) && \ | ||
123 | ((CORTEX_MODEL == 3) || (CORTEX_MODEL == 4)) | ||
124 | /* Workaround for ARM errata 752419, only applied if | ||
125 | condition exists for it to be triggered.*/ | ||
126 | ldr r3, [r0, #CONTEXT_OFFSET] | ||
127 | mov sp, r3 | ||
128 | #else | ||
129 | ldr sp, [r0, #CONTEXT_OFFSET] | ||
130 | #endif | ||
131 | |||
132 | #if PORT_SWITCHED_REGIONS_NUMBER > 0 | ||
133 | /* Restoring MPU context.*/ | ||
134 | #if PORT_SWITCHED_REGIONS_NUMBER == 1 | ||
135 | pop {r4, r5} | ||
136 | #endif | ||
137 | #if PORT_SWITCHED_REGIONS_NUMBER == 2 | ||
138 | pop {r4, r5, r6, r7} | ||
139 | #endif | ||
140 | #if PORT_SWITCHED_REGIONS_NUMBER == 3 | ||
141 | pop {r4, r5, r6, r7, r8, r9} | ||
142 | #endif | ||
143 | #if PORT_SWITCHED_REGIONS_NUMBER == 4 | ||
144 | pop {r4, r5, r6, r7, r8, r9, r10, r11} | ||
145 | #endif | ||
146 | #if PORT_SWITCHED_REGIONS_NUMBER >= 1 | ||
147 | mov r3, #0 | ||
148 | str r3, [r2, #-4] /* RNR */ | ||
149 | stm r2, {r4, r5} /* RBAR, RASR */ | ||
150 | #endif | ||
151 | #if PORT_SWITCHED_REGIONS_NUMBER >= 2 | ||
152 | add r3, #1 | ||
153 | str r3, [r2, #-4] /* RNR */ | ||
154 | stm r2, {r6, r7} /* RBAR, RASR */ | ||
155 | #endif | ||
156 | #if PORT_SWITCHED_REGIONS_NUMBER >= 3 | ||
157 | add r3, #1 | ||
158 | str r3, [r2, #-4] /* RNR */ | ||
159 | stm r2, {r8, r9} /* RBAR, RASR */ | ||
160 | #endif | ||
161 | #if PORT_SWITCHED_REGIONS_NUMBER >= 4 | ||
162 | add r3, #1 | ||
163 | str r3, [r2, #-4] /* RNR */ | ||
164 | stm r2, {r10, r11} /* RBAR, RASR */ | ||
165 | #endif | ||
166 | #endif | ||
167 | |||
168 | #if CORTEX_USE_FPU | ||
169 | /* Restoring FPU context.*/ | ||
170 | vpop {s16-s31} | ||
171 | #endif | ||
172 | pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} | ||
173 | |||
174 | /*--------------------------------------------------------------------------* | ||
175 | * Start a thread by invoking its work function. | ||
176 | * | ||
177 | * Threads execution starts here, the code leaves the system critical zone | ||
178 | * and then jumps into the thread function passed in register R4. The | ||
179 | * register R5 contains the thread parameter. The function chThdExit() is | ||
180 | * called on thread function return. | ||
181 | *--------------------------------------------------------------------------*/ | ||
182 | .thumb_func | ||
183 | .globl _port_thread_start | ||
184 | _port_thread_start: | ||
185 | #if CH_DBG_ENABLE_STACK_CHECK && PORT_ENABLE_GUARD_PAGES | ||
186 | bl _port_set_region | ||
187 | #endif | ||
188 | #if CH_DBG_SYSTEM_STATE_CHECK | ||
189 | bl _dbg_check_unlock | ||
190 | #endif | ||
191 | #if CH_DBG_STATISTICS | ||
192 | bl _stats_stop_measure_crit_thd | ||
193 | #endif | ||
194 | #if CORTEX_SIMPLIFIED_PRIORITY | ||
195 | cpsie i | ||
196 | #else | ||
197 | movs r3, #0 /* CORTEX_BASEPRI_DISABLED */ | ||
198 | msr BASEPRI, r3 | ||
199 | #endif | ||
200 | mov r0, r5 | ||
201 | blx r4 | ||
202 | movs r0, #0 /* MSG_OK */ | ||
203 | bl chThdExit | ||
204 | _zombies: b _zombies | ||
205 | |||
206 | /*--------------------------------------------------------------------------* | ||
207 | * Post-IRQ switch code. | ||
208 | * | ||
209 | * Exception handlers return here for context switching. | ||
210 | *--------------------------------------------------------------------------*/ | ||
211 | .thumb_func | ||
212 | .globl _port_switch_from_isr | ||
213 | _port_switch_from_isr: | ||
214 | #if CH_DBG_STATISTICS | ||
215 | bl _stats_start_measure_crit_thd | ||
216 | #endif | ||
217 | #if CH_DBG_SYSTEM_STATE_CHECK | ||
218 | bl _dbg_check_lock | ||
219 | #endif | ||
220 | bl chSchDoReschedule | ||
221 | #if CH_DBG_SYSTEM_STATE_CHECK | ||
222 | bl _dbg_check_unlock | ||
223 | #endif | ||
224 | #if CH_DBG_STATISTICS | ||
225 | bl _stats_stop_measure_crit_thd | ||
226 | #endif | ||
227 | .globl _port_exit_from_isr | ||
228 | _port_exit_from_isr: | ||
229 | #if CORTEX_SIMPLIFIED_PRIORITY | ||
230 | movw r3, #:lower16:SCB_ICSR | ||
231 | movt r3, #:upper16:SCB_ICSR | ||
232 | mov r2, ICSR_PENDSVSET | ||
233 | str r2, [r3, #0] | ||
234 | cpsie i | ||
235 | #else /* !CORTEX_SIMPLIFIED_PRIORITY */ | ||
236 | svc #0 | ||
237 | #endif /* !CORTEX_SIMPLIFIED_PRIORITY */ | ||
238 | .L1: b .L1 | ||
239 | |||
240 | #endif /* !defined(__DOXYGEN__) */ | ||
241 | |||
242 | /** @} */ | ||
diff --git a/lib/chibios/os/common/ports/ARMCMx/compilers/GCC/chtypes.h b/lib/chibios/os/common/ports/ARMCMx/compilers/GCC/chtypes.h new file mode 100644 index 000000000..40ef1e986 --- /dev/null +++ b/lib/chibios/os/common/ports/ARMCMx/compilers/GCC/chtypes.h | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file ARMCMx/compilers/GCC/chtypes.h | ||
22 | * @brief ARM Cortex-Mx port system types. | ||
23 | * | ||
24 | * @addtogroup ARMCMx_GCC_CORE | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #ifndef CHTYPES_H | ||
29 | #define CHTYPES_H | ||
30 | |||
31 | #include <stddef.h> | ||
32 | #include <stdint.h> | ||
33 | #include <stdbool.h> | ||
34 | |||
35 | /** | ||
36 | * @name Kernel types | ||
37 | * @{ | ||
38 | */ | ||
39 | typedef uint32_t rtcnt_t; /**< Realtime counter. */ | ||
40 | typedef uint64_t rttime_t; /**< Realtime accumulator. */ | ||
41 | typedef uint32_t syssts_t; /**< System status word. */ | ||
42 | typedef uint8_t tmode_t; /**< Thread flags. */ | ||
43 | typedef uint8_t tstate_t; /**< Thread state. */ | ||
44 | typedef uint8_t trefs_t; /**< Thread references counter. */ | ||
45 | typedef uint8_t tslices_t; /**< Thread time slices counter.*/ | ||
46 | typedef uint32_t tprio_t; /**< Thread priority. */ | ||
47 | typedef int32_t msg_t; /**< Inter-thread message. */ | ||
48 | typedef int32_t eventid_t; /**< Numeric event identifier. */ | ||
49 | typedef uint32_t eventmask_t; /**< Mask of event identifiers. */ | ||
50 | typedef uint32_t eventflags_t; /**< Mask of event flags. */ | ||
51 | typedef int32_t cnt_t; /**< Generic signed counter. */ | ||
52 | typedef uint32_t ucnt_t; /**< Generic unsigned counter. */ | ||
53 | /** @} */ | ||
54 | |||
55 | /** | ||
56 | * @brief ROM constant modifier. | ||
57 | * @note It is set to use the "const" keyword in this port. | ||
58 | */ | ||
59 | #define ROMCONST const | ||
60 | |||
61 | /** | ||
62 | * @brief Makes functions not inlineable. | ||
63 | * @note If the compiler does not support such attribute then some | ||
64 | * time-dependent services could be degraded. | ||
65 | */ | ||
66 | #define NOINLINE __attribute__((noinline)) | ||
67 | |||
68 | /** | ||
69 | * @brief Optimized thread function declaration macro. | ||
70 | */ | ||
71 | #define PORT_THD_FUNCTION(tname, arg) void tname(void *arg) | ||
72 | |||
73 | /** | ||
74 | * @brief Packed variable specifier. | ||
75 | */ | ||
76 | #define PACKED_VAR __attribute__((packed)) | ||
77 | |||
78 | /** | ||
79 | * @brief Memory alignment enforcement for variables. | ||
80 | */ | ||
81 | #define ALIGNED_VAR(n) __attribute__((aligned(n))) | ||
82 | |||
83 | /** | ||
84 | * @brief Size of a pointer. | ||
85 | * @note To be used where the sizeof operator cannot be used, preprocessor | ||
86 | * expressions for example. | ||
87 | */ | ||
88 | #define SIZEOF_PTR 4 | ||
89 | |||
90 | /** | ||
91 | * @brief True if alignment is low-high in current architecture. | ||
92 | */ | ||
93 | #define REVERSE_ORDER 1 | ||
94 | |||
95 | #endif /* CHTYPES_H */ | ||
96 | |||
97 | /** @} */ | ||
diff --git a/lib/chibios/os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk b/lib/chibios/os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk new file mode 100644 index 000000000..12ff9ddf5 --- /dev/null +++ b/lib/chibios/os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk | |||
@@ -0,0 +1,13 @@ | |||
1 | # List of the ChibiOS/RT Cortex-M0 STM32F0xx port files. | ||
2 | PORTSRC = $(CHIBIOS)/os/common/ports/ARMCMx/chcore.c \ | ||
3 | $(CHIBIOS)/os/common/ports/ARMCMx/chcore_v6m.c | ||
4 | |||
5 | PORTASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.S | ||
6 | |||
7 | PORTINC = $(CHIBIOS)/os/common/ports/ARMCMx \ | ||
8 | $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC | ||
9 | |||
10 | # Shared variables | ||
11 | ALLXASMSRC += $(PORTASM) | ||
12 | ALLCSRC += $(PORTSRC) | ||
13 | ALLINC += $(PORTINC) | ||
diff --git a/lib/chibios/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk b/lib/chibios/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk new file mode 100644 index 000000000..a5ffa679c --- /dev/null +++ b/lib/chibios/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk | |||
@@ -0,0 +1,13 @@ | |||
1 | # List of the ChibiOS/RT ARMv7M generic port files. | ||
2 | PORTSRC = $(CHIBIOS)/os/common/ports/ARMCMx/chcore.c \ | ||
3 | $(CHIBIOS)/os/common/ports/ARMCMx/chcore_v7m.c | ||
4 | |||
5 | PORTASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.S | ||
6 | |||
7 | PORTINC = $(CHIBIOS)/os/common/ports/ARMCMx \ | ||
8 | $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC | ||
9 | |||
10 | # Shared variables | ||
11 | ALLXASMSRC += $(PORTASM) | ||
12 | ALLCSRC += $(PORTSRC) | ||
13 | ALLINC += $(PORTINC) | ||
diff --git a/lib/chibios/os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v6m.s b/lib/chibios/os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v6m.s new file mode 100644 index 000000000..595dc2341 --- /dev/null +++ b/lib/chibios/os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v6m.s | |||
@@ -0,0 +1,156 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file compilers/IAR/chcoreasm_v6m.s | ||
22 | * @brief ARMv6-M architecture port low level code. | ||
23 | * | ||
24 | * @addtogroup ARMCMx_IAR_CORE | ||
25 | * @{ | ||
26 | */ | ||
27 | |||
28 | #if !defined(FALSE) || defined(__DOXYGEN__) | ||
29 | #define FALSE 0 | ||
30 | #endif | ||
31 | |||
32 | #if !defined(TRUE) || defined(__DOXYGEN__) | ||
33 | #define TRUE 1 | ||
34 | #endif | ||
35 | |||
36 | #define _FROM_ASM_ | ||
37 | #include "chlicense.h" | ||
38 | #include "chconf.h" | ||
39 | #include "chcore.h" | ||
40 | |||
41 | #if !defined(__DOXYGEN__) | ||
42 | |||
43 | /* | ||
44 | * RTOS-specific context offset. | ||
45 | */ | ||
46 | #if defined(_CHIBIOS_RT_CONF_) | ||
47 | #define CONTEXT_OFFSET 12 | ||
48 | #elif defined(_CHIBIOS_NIL_CONF_) | ||
49 | #define CONTEXT_OFFSET 0 | ||
50 | #else | ||
51 | #error "invalid chconf.h" | ||
52 | #endif | ||