SuperTinyKernel™ RTOS 1.08.x
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
stk_arch_arm-cortex-m.h
Go to the documentation of this file.
1/*
2 * SuperTinyKernel(TM) RTOS: Lightweight High-Performance Deterministic C++ RTOS for Embedded Systems.
3 *
4 * Source: https://github.com/SuperTinyKernel-RTOS
5 *
6 * Copyright (c) 2022-2026 Neutron Code Limited <stk@neutroncode.com>. All Rights Reserved.
7 * License: MIT License, see LICENSE for a full text.
8 */
9
10#ifndef STK_ARCH_ARM_CORTEX_M_H_
11#define STK_ARCH_ARM_CORTEX_M_H_
12
13#include "stk_common.h"
14#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE != 0)
15 #include <arm_cmse.h> // for ARM TrustZone
16#endif
17
21#ifndef STK_ARCH_ARMV6_M
22 #if defined(__ARM_ARCH_6M__)
23 #define STK_ARCH_ARMV6_M (1)
24 #else
25 #define STK_ARCH_ARMV6_M (0)
26 #endif
27#else
28 #if (STK_ARCH_ARMV6_M == 0) && defined(__ARM_ARCH_6M__)
29 #error "STK_ARCH_ARMV6_M must be defined as 1 on ARMv6-M platform!"
30 #endif
31#endif
32
36#ifndef STK_ARCH_ARMV7_M
37 #if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
38 #define STK_ARCH_ARMV7_M (1)
39 #else
40 #define STK_ARCH_ARMV7_M (0)
41 #endif
42#else
43 #if (STK_ARCH_ARMV7_M == 0) && (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__))
44 #error "STK_ARCH_ARMV7_M must be defined as 1 on ARMv7-M platform!"
45 #endif
46#endif
47
51#ifndef STK_ARCH_ARMV8_M
52 #if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__)
53 #define STK_ARCH_ARMV8_M (1)
54 #else
55 #define STK_ARCH_ARMV8_M (0)
56 #endif
57#else
58 #if (STK_ARCH_ARMV8_M == 0) && (defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__))
59 #error "STK_ARCH_ARMV8_M must be defined as 1 on ARMv8-M platform!"
60 #endif
61#endif
62
63// Expect at least one supported target architecture.
64#if !STK_ARCH_ARMV6_M && !STK_ARCH_ARMV7_M && !STK_ARCH_ARMV8_M
65 #error "Unsupported ARM architecture target!"
66#endif
67
68// Enforce single active target architecture state.
69#if (STK_ARCH_ARMV6_M + STK_ARCH_ARMV7_M + STK_ARCH_ARMV8_M) > 1
70 #error "Multiple STK_ARCH_ARMvX flags active simultaneously! Check build environment definitions."
71#endif
72
77#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)
78 #define __stk_tz_nsc_entry __attribute__((cmse_nonsecure_entry))
79#else
80 #define __stk_tz_nsc_entry
81#endif
82
86#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)
87 #define __stk_tz_ns_call __attribute__((cmse_nonsecure_call))
88#else
89 #define __stk_tz_ns_call
90#endif
91
95#define STK_TZ_NSC_GATEWAY extern "C" __stk_tz_nsc_entry
96
97// ARM TrustZone Non-Secure binary configuration validation.
98#ifdef _STK_CORTEX_M_TRUSTZONE_NON_SECURE
99#if !STK_TZ_NON_SECURE
100 #error "Do not use -cmse compiler flag for Non-Secure binary compilation!"
101#endif
102#endif
103
104// Task MPU is supported only when MPU is enabled globally.
105#if STK_MPU_STACK_GUARD && !STK_MPU
106 #error "Enable MPU support (STK_MPU=1) to use per-task MPU feature (STK_MPU_STACK_GUARD=1)!"
107#endif
108
112#ifndef STK_CORTEX_M_MPU_REGIONS_MAX
113 #define STK_CORTEX_M_MPU_REGIONS_MAX (8U)
114#endif
115
120#ifndef STK_CORTEX_M_SVCALL_ISR_PRIORITY
121 #define STK_CORTEX_M_SVCALL_ISR_PRIORITY (0U)
122#endif
123
126static __stk_forceinline void __stk_dmb() { __asm volatile("dmb sy" ::: "memory"); }
127
131
132namespace stk {
133
137class PlatformArmCortexM final : public IPlatform
138{
139public:
144
145 void Initialize(IEventHandler *event_handler, IKernelService *service, uint32_t resolution_us, Stack *exit_trap) override;
146 void Start() override;
147 void Stop() override;
148 void InitStack(EStackType stack_type, Stack *stack, IStackMemory *stack_memory, ITask *user_task) override;
149 uint32_t GetTickResolution() const override;
150 Cycles GetSysTimerCount() const override;
151 uint32_t GetSysTimerFrequency() const override;
152 void SwitchToNext() override;
153 void ForceContextSwitch(TId id) override;
154 void Sleep(Timeout ticks) override;
155 bool SleepUntil(Ticks timestamp) override;
156 EWaitResult Wait(ISyncObject *sync_obj, IMutex *mutex, Timeout timeout) override;
157 void ProcessTick() override;
158 void ProcessHardFault() override;
159 void SetEventOverrider(IEventOverrider *overrider, bool non_secure) override;
160 Word GetCallerSP() const override;
161 TId GetTid() const override;
162 Timeout Suspend() override;
163 void Resume(Timeout elapsed_ticks) override;
164 void SetCpuFrequency(uint8_t core_id, uint32_t frequency) override;
165};
166
171
172// Inline TLS via r9. Active when both STK_TLS and STK_TLS_PREFER_REGISTER are
173// enabled. Requires -ffixed-r9 on all translation units containing task code
174// (see GetTls/SetTls warnings below). If -ffixed-r9 is unavailable or
175// undesirable, leave STK_TLS_PREFER_REGISTER disabled; the kernel will fall back
176// to a memory-based TLS slot with a small additional load/store per access.
177// =============================================================================
178#if STK_TLS && STK_TLS_PREFER_REGISTER
179// =============================================================================
180
194static __stk_forceinline Word GetTls()
195{
196 Word tp;
197 __asm volatile("MOV %0, r9" : "=r"(tp) : /* input: none */ : /* clobbers: none */);
198 return tp;
199}
200
209static __stk_forceinline void SetTls(Word tp)
210{
211 __asm volatile("MOV r9, %0" : /* output: none */ : "r"(tp) : /* clobbers: none */);
212}
213
214// Notify stk_arch.h that we defined inline versions of GetTls/SetTls.
215#define STK_INLINE_TLS (1)
216
217// =============================================================================
218#endif // STK_TLS_PREFER_REGISTER
219// =============================================================================
220
221namespace hw {
222
237
238} // namespace hw
239
240// =============================================================================
241#if STK_MPU
242// =============================================================================
243
248namespace hw {
249namespace mpu {
250
251#if STK_ARCH_ARMV8_M
252
253// ARMv8-M MPU Variant (PMSAv8 Layout)
254
260enum EMpuAccess : uint8_t
261{
262 ACCESS_NONE = 0xFFU,
263
264 ACCESS_PRIV_RW_USER_NO = (0x0U << 1U),
265 ACCESS_FULL = (0x1U << 1U),
266 ACCESS_PRIV_RO_USER_NO = (0x2U << 1U),
267 ACCESS_PRIV_RO_USER_RO = (0x3U << 1U)
268};
269
274enum EMpuExec : uint8_t
275{
276 EXEC_ALLOWED = (0x0U << 0U),
277 EXEC_NEVER = (0x1U << 0U)
278};
279
285enum EMpuType : uint8_t
286{
287 TYPE_STRONGLY_ORDERED = 0U,
288 TYPE_DEVICE = 1U,
289 TYPE_NORMAL_NON_CACHE = 2U,
290 TYPE_NORMAL_CACHEABLE = 3U
291};
292
298enum EMpuShare : uint8_t
299{
300 SHARE_NON = (0x0U << 3U),
301 SHARE_OUTER = (0x2U << 3U),
302 SHARE_INNER = (0x3U << 3U)
303};
304
305#else // !STK_ARCH_ARMV8_M
306
307// Legacy ARMv7-M MPU Variant (PMSAv7 Layout)
308
312enum EMpuAccess : uint32_t
313{
314 ACCESS_NONE = 0xFFFFFFFFU,
315
316 ACCESS_HW_NO_ACCESS = (0x0U << 24U),
317 ACCESS_PRIV_RW_USER_NO = (0x1U << 24U),
318 ACCESS_PRIV_RW_USER_RO = (0x2U << 24U),
319 ACCESS_FULL = (0x3U << 24U),
320 ACCESS_PRIV_RO_USER_NO = (0x5U << 24U),
321 ACCESS_PRIV_RO_USER_RO = (0x6U << 24U)
322};
323
327enum EMpuExec : uint32_t
328{
329 EXEC_ALLOWED = (0x0U << 28U),
330 EXEC_NEVER = (0x1U << 28U)
331};
332
336enum EMpuType : uint32_t
337{
338 TYPE_STRONGLY_ORDERED = 0x000000U,
339 TYPE_DEVICE = 0x010000U,
340 TYPE_NORMAL_NON_CACHE = 0x080000U,
341 TYPE_NORMAL_CACHEABLE = 0x030000U
342};
343
350enum EMpuShare : uint32_t
351{
352 SHARE_NON = (0x0U << 18U),
353 SHARE_OUTER = (0x1U << 18U),
354 SHARE_INNER = (0x1U << 18U)
355};
356
357#endif // STK_ARCH_ARMV8_M
358
362enum EMpuConfigFlags : uint32_t
363{
364 MPU_CFG_NONE = 0U,
365 MPU_CFG_PRIVILEGED_BG_MEM = (1U << 0),
366 MPU_CFG_IN_FAULTS = (1U << 1),
367 MPU_CFG_CLEAR_ON_INIT = (1U << 2),
368 MPU_CFG_NONSECURE_MPU = (1U << 3)
369};
370
371} // namespace mpu
372} // namespace hw
373
377struct MpuRegionConfig
378{
379 Word addr;
380 size_t size;
381 hw::mpu::EMpuAccess access_perm;
382 hw::mpu::EMpuType mem_type;
383 hw::mpu::EMpuShare share;
384 hw::mpu::EMpuExec exec;
385};
386
421
422// =============================================================================
423#endif // STK_MPU
424// =============================================================================
425
434{
438 struct Mpu
439 {
443 struct Region
444 {
448 };
449
451 #if STK_ARCH_ARMV8_M
452 Word MAIR0;
453 Word MAIR1;
454 #endif
456 };
457
466#if STK_MPU
467 Mpu mpu;
468 #if STK_ARCH_ARMV8_M && STK_TZ_SECURE
469 Mpu mpu_ns;
470 #endif
471#endif
474
479 void Fill(const Word *stacked_regs, Word exc_return);
480};
481
482} // namespace stk
483
484#endif /* STK_ARCH_ARM_CORTEX_M_H_ */
static void __stk_dmb()
Hardware memory barrier: ensures visibility across cores and bus masters.
#define STK_CORTEX_M_MPU_REGIONS_MAX
Number of MPU regions supported by MPU peripheral.
Contains interface definitions of the library.
#define __stk_forceinline
Forces compiler to always inline the decorated function, regardless of optimisation level.
Definition stk_defs.h:277
#define STK_VIRT_DTOR
Makes destructors virtual and compliant to strict rules if STK_STRICT_COMPLIANCY=0.
Definition stk_defs.h:261
Namespace of STK package.
uintptr_t Word
Native processor word type.
Definition stk_common.h:143
EWaitResult
Wait result (see IKernelService::Wait).
Definition stk_common.h:121
int64_t Ticks
Ticks value.
Definition stk_common.h:158
int32_t Timeout
Timeout time (ticks).
Definition stk_common.h:153
PlatformArmCortexM PlatformDefault
Default platform implementation.
EStackType
Stack type.
Definition stk_common.h:79
uint64_t Cycles
Cycles value.
Definition stk_common.h:168
Word TId
Task (thread) id.
Definition stk_common.h:148
Hardware Abstraction Layer (HAL) for architecture-specific operations.
Concrete implementation of IPlatform driver for the Arm Cortex-M0, M3, M4, M7 processors.
void SwitchToNext() override
Switch to a next task.
void Sleep(Timeout ticks) override
Put calling process into a sleep state.
void ProcessTick() override
Process one tick.
Word GetCallerSP() const override
Get caller's Stack Pointer (SP).
void ProcessHardFault() override
Cause a hard fault of the system.
void ForceContextSwitch(TId id) override
Force context switch.
uint32_t GetTickResolution() const override
Get resolution of the system tick timer in microseconds. Resolution means a number of microseconds be...
Timeout Suspend() override
Suspend scheduling.
void Start() override
Start scheduling.
void SetCpuFrequency(uint8_t core_id, uint32_t frequency) override
Notify the scheduler of a CPU core's operating frequency.
void Stop() override
Stop scheduling.
TId GetTid() const override
Get thread Id.
void SetEventOverrider(IEventOverrider *overrider, bool non_secure) override
Set platform event overrider.
uint32_t GetSysTimerFrequency() const override
Get system timer frequency.
Cycles GetSysTimerCount() const override
Get system timer count value.
void InitStack(EStackType stack_type, Stack *stack, IStackMemory *stack_memory, ITask *user_task) override
Initialize stack memory of the user task.
EWaitResult Wait(ISyncObject *sync_obj, IMutex *mutex, Timeout timeout) override
Put calling process into a waiting state until synchronization object is signaled or timeout occurs.
void Resume(Timeout elapsed_ticks) override
Resume scheduling after a prior Suspend() call.
void Initialize(IEventHandler *event_handler, IKernelService *service, uint32_t resolution_us, Stack *exit_trap) override
Initialize scheduler's context.
~PlatformArmCortexM()=default
Destructor.
bool SleepUntil(Ticks timestamp) override
Put calling process into a sleep state until the specified timestamp.
ARMv7-M/ARMv8-M hardware exception frame (8 words, highest address on the stack).
ARMv7-M/ARMv8-M system fault exception context state capture.
Word BFAR
BusFault Address Register (BFAR).
Word AFSR
Auxiliary Fault Status Register (AFSR).
Word HFSR
HardFault Status Register (HFSR).
hw::ExceptionFrame frame
Saved hardware exception stack frame.
Word MMFAR
Memory Management Fault Address Register (MMFAR).
Word CFSR
Configurable Fault Status Register (CFSR: MemManage, BusFault, UsageFault).
Word CONTROL
Core CONTROL register state snapshot.
bool mmfar_valid
Flag indicating validity of MMFAR address value (derived from CFSR.MMARVALID).
Word EXC_RETURN
Exception return magic value (EXC_RETURN).
bool bfar_valid
Flag indicating validity of BFAR address value (derived from CFSR.BFARVALID).
void Fill(const Word *stacked_regs, Word exc_return)
Populate fault context registers and hardware MPU state from an exception stack frame.
Hardware Memory Protection Unit (MPU) status register snapshot.
Region regions[(8U)]
Active hardware MPU region register state table.
Word CTRL
MPU Control Register (MPU_CTRL).
Register snapshot for an individual hardware MPU region slot.
Word RNR
Region Number Register (RNR).
Word ATTR
Region Attribute and Size Register (RASR / RLAR / MPU_RLAR).
Word RBAR
Region Base Address Register (RBAR).
Stack descriptor.
Definition stk_common.h:392
Interface for a stack memory region.
Definition stk_common.h:413
Synchronization object interface.
Definition stk_common.h:564
Interface for mutex synchronization primitive.
Definition stk_common.h:697
Interface for a user task.
Definition stk_common.h:755
Interface for a platform driver.
Definition stk_common.h:978
Interface for a back-end event handler.
Definition stk_common.h:986
Interface for a platform event overrider.
Interface for the kernel services exposed to the user processes during run-time when Kernel started s...