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
76#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)
77 #define STK_TZ_SECURE (1)
78#else
79 #define STK_TZ_SECURE (0)
80#endif
81
85#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 1)
86 #define STK_TZ_NON_SECURE (1)
87#else
88 #define STK_TZ_NON_SECURE (0)
89#endif
90
95#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)
96 #define __stk_tz_nsc_entry __attribute__((cmse_nonsecure_entry))
97#else
98 #define __stk_tz_nsc_entry
99#endif
100
104#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)
105 #define __stk_tz_ns_call __attribute__((cmse_nonsecure_call))
106#else
107 #define __stk_tz_ns_call
108#endif
109
113#define STK_TZ_NSC_GATEWAY extern "C" __stk_tz_nsc_entry
114
115// ARM TrustZone Non-Secure binary configuration validation.
116#ifdef _STK_CORTEX_M_TRUSTZONE_NON_SECURE
117#if !STK_TZ_NON_SECURE
118 #error "Do not use -cmse compiler flag for Non-Secure binary compilation!"
119#endif
120#endif
121
122// Task MPU is supported only when MPU is enabled globally.
123#if STK_MPU_STACK_GUARD && !STK_MPU
124 #error "Enable MPU support (STK_MPU=1) to use per-task MPU feature (STK_MPU_STACK_GUARD=1)!"
125#endif
126
130#ifndef STK_CORTEX_M_MPU_REGIONS_MAX
131 #define STK_CORTEX_M_MPU_REGIONS_MAX (8U)
132#endif
133
136static __stk_forceinline void __stk_dmb() { __asm volatile("dmb sy" ::: "memory"); }
137
141
142namespace stk {
143
147class PlatformArmCortexM final : public IPlatform
148{
149public:
154
155 void Initialize(IEventHandler *event_handler, IKernelService *service, uint32_t resolution_us, Stack *exit_trap) override;
156 void Start() override;
157 void Stop() override;
158 void InitStack(EStackType stack_type, Stack *stack, IStackMemory *stack_memory, ITask *user_task) override;
159 uint32_t GetTickResolution() const override;
160 Cycles GetSysTimerCount() const override;
161 uint32_t GetSysTimerFrequency() const override;
162 void SwitchToNext() override;
163 void Sleep(Timeout ticks) override;
164 bool SleepUntil(Ticks timestamp) override;
165 EWaitResult Wait(ISyncObject *sync_obj, IMutex *mutex, Timeout timeout) override;
166 void ProcessTick() override;
167 void ProcessHardFault() override;
168 void SetEventOverrider(IEventOverrider *overrider, bool non_secure) override;
169 Word GetCallerSP() const override;
170 TId GetTid() const override;
171 Timeout Suspend() override;
172 void Resume(Timeout elapsed_ticks) override;
173};
174
179
180// Inline TLS via r9. Active when both STK_TLS and STK_TLS_PREFER_REGISTER are
181// enabled. Requires -ffixed-r9 on all translation units containing task code
182// (see GetTls/SetTls warnings below). If -ffixed-r9 is unavailable or
183// undesirable, leave STK_TLS_PREFER_REGISTER disabled; the kernel will fall back
184// to a memory-based TLS slot with a small additional load/store per access.
185// =============================================================================
186#if STK_TLS && STK_TLS_PREFER_REGISTER
187// =============================================================================
188
202static __stk_forceinline Word GetTls()
203{
204 Word tp;
205 __asm volatile("MOV %0, r9" : "=r"(tp) : /* input: none */ : /* clobbers: none */);
206 return tp;
207}
208
217static __stk_forceinline void SetTls(Word tp)
218{
219 __asm volatile("MOV r9, %0" : /* output: none */ : "r"(tp) : /* clobbers: none */);
220}
221
222// Notify stk_arch.h that we defined inline versions of GetTls/SetTls.
223#define STK_INLINE_TLS 1
224
225// =============================================================================
226#endif // STK_TLS_PREFER_REGISTER
227// =============================================================================
228
229namespace hw {
230
245
246} // namespace hw
247
248// =============================================================================
249#if STK_MPU
250// =============================================================================
251
256namespace hw {
257namespace mpu {
258
259#if STK_ARCH_ARMV8_M
260
261// ARMv8-M MPU Variant (PMSAv8 Layout)
262
268enum EMpuAccess : uint8_t
269{
270 ACCESS_NONE = 0xFFU,
271
272 ACCESS_PRIV_RW_USER_NO = (0x0U << 1U),
273 ACCESS_FULL = (0x1U << 1U),
274 ACCESS_PRIV_RO_USER_NO = (0x2U << 1U),
275 ACCESS_PRIV_RO_USER_RO = (0x3U << 1U)
276};
277
282enum EMpuExec : uint8_t
283{
284 EXEC_ALLOWED = (0x0U << 0U),
285 EXEC_NEVER = (0x1U << 0U)
286};
287
293enum EMpuType : uint8_t
294{
295 TYPE_STRONGLY_ORDERED = 0U,
296 TYPE_DEVICE = 1U,
297 TYPE_NORMAL_NON_CACHE = 2U,
298 TYPE_NORMAL_CACHEABLE = 3U
299};
300
306enum EMpuShare : uint8_t
307{
308 SHARE_NON = (0x0U << 3U),
309 SHARE_OUTER = (0x2U << 3U),
310 SHARE_INNER = (0x3U << 3U)
311};
312
313#else // !STK_ARCH_ARMV8_M
314
315// Legacy ARMv7-M MPU Variant (PMSAv7 Layout)
316
320enum EMpuAccess : uint32_t
321{
322 ACCESS_NONE = 0xFFFFFFFFU,
323
324 ACCESS_HW_NO_ACCESS = (0x0U << 24U),
325 ACCESS_PRIV_RW_USER_NO = (0x1U << 24U),
326 ACCESS_PRIV_RW_USER_RO = (0x2U << 24U),
327 ACCESS_FULL = (0x3U << 24U),
328 ACCESS_PRIV_RO_USER_NO = (0x5U << 24U),
329 ACCESS_PRIV_RO_USER_RO = (0x6U << 24U)
330};
331
335enum EMpuExec : uint32_t
336{
337 EXEC_ALLOWED = (0x0U << 28U),
338 EXEC_NEVER = (0x1U << 28U)
339};
340
344enum EMpuType : uint32_t
345{
346 TYPE_STRONGLY_ORDERED = 0x000000U,
347 TYPE_DEVICE = 0x010000U,
348 TYPE_NORMAL_NON_CACHE = 0x080000U,
349 TYPE_NORMAL_CACHEABLE = 0x030000U
350};
351
358enum EMpuShare : uint32_t
359{
360 SHARE_NON = (0x0U << 18U),
361 SHARE_OUTER = (0x1U << 18U),
362 SHARE_INNER = (0x1U << 18U)
363};
364
365#endif // STK_ARCH_ARMV8_M
366
370enum EMpuConfigFlags : uint32_t
371{
372 MPU_CFG_NONE = 0U,
373 MPU_CFG_PRIVILEGED_BG_MEM = (1U << 0),
374 MPU_CFG_IN_FAULTS = (1U << 1),
375 MPU_CFG_CLEAR_ON_INIT = (1U << 2),
376 MPU_CFG_NONSECURE_MPU = (1U << 3)
377};
378
379} // namespace mpu
380} // namespace hw
381
385struct MpuRegionConfig
386{
387 Word addr;
388 size_t size;
389 hw::mpu::EMpuAccess access_perm;
390 hw::mpu::EMpuType mem_type;
391 hw::mpu::EMpuShare share;
392 hw::mpu::EMpuExec exec;
393};
394
429
438#define STK_MPU_SHARED_DATA_SECTION __attribute__((section(".stk_mpu_shared_data")))
439
448#define STK_MPU_SHARED_CODE_SECTION __attribute__((section(".stk_mpu_shared_code")))
449
465#define STK_MPU_SHARED_BSS_SECTION __attribute__((section(".stk_mpu_shared_bss")))
466
467#else
468
469#define STK_MPU_SHARED_DATA_SECTION
470#define STK_MPU_SHARED_CODE_SECTION
471#define STK_MPU_SHARED_BSS_SECTION
472
473// =============================================================================
474#endif // STK_MPU
475// =============================================================================
476
485{
489 struct Mpu
490 {
494 struct Region
495 {
499 };
500
502 #if STK_ARCH_ARMV8_M
503 Word MAIR0;
504 Word MAIR1;
505 #endif
507 };
508
517#if STK_MPU
518 Mpu mpu;
519 #if STK_ARCH_ARMV8_M && STK_TZ_SECURE
520 Mpu mpu_ns;
521 #endif
522#endif
525
530 void Fill(const Word *stacked_regs, Word exc_return);
531};
532
533} // namespace stk
534
535#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:218
#define STK_VIRT_DTOR
Makes destructors virtual and compliant to strict rules if STK_STRICT_COMPLIANCY=0.
Definition stk_defs.h:202
Namespace of STK package.
uintptr_t Word
Native processor word type.
Definition stk_common.h:140
EWaitResult
Wait result (see IKernelService::Wait).
Definition stk_common.h:118
int64_t Ticks
Ticks value.
Definition stk_common.h:155
int32_t Timeout
Timeout time (ticks).
Definition stk_common.h:150
PlatformArmCortexM PlatformDefault
Default platform implementation.
EStackType
Stack type.
Definition stk_common.h:78
uint64_t Cycles
Cycles value.
Definition stk_common.h:165
Word TId
Task (thread) id.
Definition stk_common.h:145
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.
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 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:380
Interface for a stack memory region.
Definition stk_common.h:401
Synchronization object interface.
Definition stk_common.h:544
Interface for mutex synchronization primitive.
Definition stk_common.h:677
Interface for a user task.
Definition stk_common.h:734
Interface for a platform driver.
Definition stk_common.h:946
Interface for a back-end event handler.
Definition stk_common.h:954
Interface for a platform event overrider.
Interface for the kernel services exposed to the user processes during run-time when Kernel started s...