aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios/os/common/ports
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios/os/common/ports')
-rw-r--r--lib/chibios/os/common/ports/ARM/chcore.c54
-rw-r--r--lib/chibios/os/common/ports/ARM/chcore.h607
-rw-r--r--lib/chibios/os/common/ports/ARM/chcore_timer.h126
-rw-r--r--lib/chibios/os/common/ports/ARM/compilers/GCC/chcoreasm.S167
-rw-r--r--lib/chibios/os/common/ports/ARM/compilers/GCC/chtypes.h115
-rw-r--r--lib/chibios/os/common/ports/ARM/compilers/GCC/mk/port_generic.mk12
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/chcore.c54
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/chcore.h208
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/chcore_timer.h133
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/chcore_v6m.c155
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/chcore_v6m.h466
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/chcore_v7m.c391
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/chcore_v7m.h790
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.S154
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.S242
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/compilers/GCC/chtypes.h97
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk13
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk13
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v6m.s156
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v7m.s169
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/compilers/IAR/chtypes.h115
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/compilers/RVCT/chcoreasm_v6m.s152
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/compilers/RVCT/chcoreasm_v7m.s167
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/compilers/RVCT/chtypes.h97
-rw-r--r--lib/chibios/os/common/ports/ARMCMx/mpu.h228
-rw-r--r--lib/chibios/os/common/ports/AVR/chcore.c159
-rw-r--r--lib/chibios/os/common/ports/AVR/chcore.h542
-rw-r--r--lib/chibios/os/common/ports/AVR/chcore_timer.h126
-rw-r--r--lib/chibios/os/common/ports/AVR/compilers/GCC/chtypes.h98
-rw-r--r--lib/chibios/os/common/ports/AVR/compilers/GCC/mk/port.mk12
-rw-r--r--lib/chibios/os/common/ports/AVR/compilers/GCC/rules.mk284
-rw-r--r--lib/chibios/os/common/ports/SIMIA32/chcore.c131
-rw-r--r--lib/chibios/os/common/ports/SIMIA32/chcore.h461
-rw-r--r--lib/chibios/os/common/ports/SIMIA32/compilers/GCC/chtypes.h109
-rw-r--r--lib/chibios/os/common/ports/SIMIA32/compilers/GCC/port.mk12
-rw-r--r--lib/chibios/os/common/ports/e200/chcore.c54
-rw-r--r--lib/chibios/os/common/ports/e200/chcore.h722
-rw-r--r--lib/chibios/os/common/ports/e200/compilers/CW/chcoreasm.s119
-rw-r--r--lib/chibios/os/common/ports/e200/compilers/CW/chtypes.h97
-rw-r--r--lib/chibios/os/common/ports/e200/compilers/CW/ivor.s205
-rw-r--r--lib/chibios/os/common/ports/e200/compilers/GCC/chcoreasm.S113
-rw-r--r--lib/chibios/os/common/ports/e200/compilers/GCC/chtypes.h97
-rw-r--r--lib/chibios/os/common/ports/e200/compilers/GCC/ivor.S263
-rw-r--r--lib/chibios/os/common/ports/e200/compilers/GCC/mk/port.mk13
-rw-r--r--lib/chibios/os/common/ports/e200/compilers/GHS/chcoreasm.s107
-rw-r--r--lib/chibios/os/common/ports/e200/compilers/GHS/chtypes.h97
-rw-r--r--lib/chibios/os/common/ports/e200/compilers/GHS/ivor.s265
-rw-r--r--lib/chibios/os/common/ports/e200/compilers/GHS/mk/port.mk13
-rw-r--r--lib/chibios/os/common/ports/readme.txt3
-rw-r--r--lib/chibios/os/common/ports/templates/chcore.c75
-rw-r--r--lib/chibios/os/common/ports/templates/chcore.dox33
-rw-r--r--lib/chibios/os/common/ports/templates/chcore.h460
-rw-r--r--lib/chibios/os/common/ports/templates/chtypes.h101
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 */
224typedef uint64_t stkalign_t;
225
226/**
227 * @brief Generic ARM register.
228 */
229typedef 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 */
236struct 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 */
252struct 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 */
270struct 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
393extern "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 */
415static 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 */
424static 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 */
446static 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 */
458static 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 */
477static 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 */
490static 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 */
503static 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 */
511static 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 */
521static 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 */
540static 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 */
553static 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 */
567static 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 */
588static 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 */
68static 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 */
79static 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 */
92static 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 */
105static 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 */
118static 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
105Irq_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 */
57typedef uint32_t rtcnt_t; /**< Realtime counter. */
58typedef uint64_t rttime_t; /**< Realtime accumulator. */
59typedef uint32_t syssts_t; /**< System status word. */
60typedef uint8_t tmode_t; /**< Thread flags. */
61typedef uint8_t tstate_t; /**< Thread state. */
62typedef uint8_t trefs_t; /**< Thread references counter. */
63typedef uint8_t tslices_t; /**< Thread time slices counter.*/
64typedef uint32_t tprio_t; /**< Thread priority. */
65typedef int32_t msg_t; /**< Inter-thread message. */
66typedef int32_t eventid_t; /**< Numeric event identifier. */
67typedef uint32_t eventmask_t; /**< Mask of event identifiers. */
68typedef uint32_t eventflags_t; /**< Mask of event flags. */
69typedef int32_t cnt_t; /**< Generic signed counter. */
70typedef 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.
2PORTSRC = ${CHIBIOS}/os/common/ports/ARM/chcore.c
3
4PORTASM = $(CHIBIOS)/os/common/ports/ARM/compilers/GCC/chcoreasm.S
5
6PORTINC = ${CHIBIOS}/os/common/ports/ARM \
7 ${CHIBIOS}/os/common/ports/ARM/compilers/GCC
8
9# Shared variables
10ALLXASMSRC += $(PORTASM)
11ALLCSRC += $(PORTSRC)
12ALLINC += $(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 */
104typedef 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 */
116struct port_extctx {};
117
118/**
119 * @brief System saved context.
120 * @details This structure represents the inner stack frame during a context
121 * switch.
122 */
123struct 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 */
131struct 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
56extern "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 */
80static 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 */
90static 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 */
102static 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 */
114static 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 */
126static 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.*/
61void 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.*/
86void 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 */
108void 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 */
118void _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__)
197struct 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
208struct 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
220struct 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
333extern "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 */
354static 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 */
368static 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 */
380static 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 */
389static 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 */
398static 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 */
408static 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 */
418static inline void port_unlock_from_isr(void) {
419
420 port_unlock();
421}
422
423/**
424 * @brief Disables all the interrupt sources.
425 */
426static inline void port_disable(void) {
427
428 __disable_irq();
429}
430
431/**
432 * @brief Disables the interrupt sources below kernel-level priority.
433 */
434static inline void port_suspend(void) {
435
436 __disable_irq();
437}
438
439/**
440 * @brief Enables all the interrupt sources.
441 */
442static 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 */
455static 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))
58void port_syslock_noinline(void) {
59
60 port_lock();
61 _stats_start_measure_crit_thd();
62 _dbg_check_lock();
63}
64
65uint32_t port_get_s_psp(void) {
66
67 return (uint32_t)currp->ctx.syscall.psp;
68}
69
70__attribute__((weak))
71void port_syscall(struct port_extctx *ctxp, uint32_t n) {
72
73 (void)ctxp;
74 (void)n;
75
76 chSysHalt("svc");
77}
78
79void 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.*/
123void 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.*/
216void 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 */
250void 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 */
298void _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 */
308void _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__)
345struct 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 */
383struct port_linkctx {
384 uint32_t control;
385 struct port_extctx *ectxp;
386};
387#endif
388
389struct 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
425struct 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
599extern "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 */
39typedef uint32_t rtcnt_t; /**< Realtime counter. */
40typedef uint64_t rttime_t; /**< Realtime accumulator. */
41typedef uint32_t syssts_t; /**< System status word. */
42typedef uint8_t tmode_t; /**< Thread flags. */
43typedef uint8_t tstate_t; /**< Thread state. */
44typedef uint8_t trefs_t; /**< Thread references counter. */
45typedef uint8_t tslices_t; /**< Thread time slices counter.*/
46typedef uint32_t tprio_t; /**< Thread priority. */
47typedef int32_t msg_t; /**< Inter-thread message. */
48typedef int32_t eventid_t; /**< Numeric event identifier. */
49typedef uint32_t eventmask_t; /**< Mask of event identifiers. */
50typedef uint32_t eventflags_t; /**< Mask of event flags. */
51typedef int32_t cnt_t; /**< Generic signed counter. */
52typedef 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.
2PORTSRC = $(CHIBIOS)/os/common/ports/ARMCMx/chcore.c \
3 $(CHIBIOS)/os/common/ports/ARMCMx/chcore_v6m.c
4
5PORTASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.S
6
7PORTINC = $(CHIBIOS)/os/common/ports/ARMCMx \
8 $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC
9
10# Shared variables
11ALLXASMSRC += $(PORTASM)
12ALLCSRC += $(PORTSRC)
13ALLINC += $(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.
2PORTSRC = $(CHIBIOS)/os/common/ports/ARMCMx/chcore.c \
3 $(CHIBIOS)/os/common/ports/ARMCMx/chcore_v7m.c
4
5PORTASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.S
6
7PORTINC = $(CHIBIOS)/os/common/ports/ARMCMx \
8 $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC
9
10# Shared variables
11ALLXASMSRC += $(PORTASM)
12ALLCSRC += $(PORTSRC)
13ALLINC += $(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