Skip to content

Commit 41e1d62

Browse files
committed
ARMv8-M: Add SMP support to CM33 NTZ non-MPU port
* Enable SMP for Arm Cortex-M33 NTZ port for GCC, ArmClang, and IAR toolchains. * Add per-core scheduler/port state: critical nesting. * Introduce spinlocks and inter-core yield/wakeup (SEV/WFE) plus primary/secondary core bring-up sync. * Update PendSV (i.e., context switch assembly) for core-safe preemption and restore paths. * Extend port macros/hooks for SMP in portmacrocommon.h, single-core builds remain unchanged. * Add the SMP boot sequence along with the necessary steps to enable SMP on Armv8-M based ports. This should help developers understand the requirements and process for enabling SMP on their Armv8-M based applications. * Update the kernel checker script to accept comma separated years in the copyright header. Signed-off-by: Ahmed Ismail <Ahmed.Ismail@arm.com>
1 parent fcc6653 commit 41e1d62

25 files changed

Lines changed: 671 additions & 140 deletions

File tree

.github/.cSpellWords.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ LDRAS
433433
ldrb
434434
ldrbs
435435
LDRBS
436+
ldrex
436437
LDRNE
437438
ldsr
438439
ldxr

.github/scripts/kernel_checker.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#/*
33
# * FreeRTOS Kernel <DEVELOPMENT BRANCH>
44
# * Copyright (C) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5+
# * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
56
# *
67
# * SPDX-License-Identifier: MIT
78
# *
@@ -157,9 +158,10 @@
157158

158159

159160
FREERTOS_COPYRIGHT_REGEX = r"^(;|#)?( *(\/\*|\*|#|\/\/))? Copyright \(C\) 20\d\d Amazon.com, Inc. or its affiliates. All Rights Reserved\.( \*\/)?$"
161+
ARM_COLLAB_YEAR_REGEX = r"20\d\d(?:-20\d\d|, 20\d\d)?"
160162

161163
FREERTOS_ARM_COLLAB_COPYRIGHT_REGEX = r"(^(;|#)?( *(\/\*|\*|#|\/\/))? Copyright \(C\) 20\d\d Amazon.com, Inc. or its affiliates. All Rights Reserved\.( \*\/)?$)|" + \
162-
r"(^(;|#)?( *(\/\*|\*|#|\/\/))? Copyright 20\d\d(-20\d\d)? Arm Limited and/or its affiliates( +<open-source-office@arm\.com>)?( \*\/)?$)|" + \
164+
rf"(^(;|#)?( *(\/\*|\*|#|\/\/))? Copyright { ARM_COLLAB_YEAR_REGEX } Arm Limited and/or its affiliates( +<open-source-office@arm\.com>)?( \*\/)?$)|" + \
163165
r"(^(;|#)?( *(\/\*|\*|#|\/\/))? Copyright \(c\) 20\d\d(-20\d\d)? Arm Technology \(China\) Co., Ltd.All Rights Reserved\.( \*\/)?$)|" + \
164166
r"(^(;|#)?( *(\/\*|\*|#|\/\/))? <open-source-office@arm\.com>( \*\/)?$)"
165167

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
This directory tree contains the master copy of the FreeRTOS Armv8-M and
22
Armv8.1-M ports.
3-
Do not use the files located here! These file are copied into separate
3+
Do not use the files located here! These files are copied into separate
44
FreeRTOS/Source/portable/[compiler]/ARM_[CM23|CM33|CM52|CM55|CM85|STAR_MC3]_NNN directories
55
prior to each FreeRTOS release.
66

@@ -9,3 +9,54 @@ FreeRTOS/Source/portable/[compiler]/ARM_[CM23|CM33|CM52|CM55|CM85|STAR_MC3] dire
99

1010
If your Armv8-M/Armv8.1-M application does not use TrustZone then use the files from
1111
the FreeRTOS/Source/portable/[compiler]/ARM_[CM23|CM33|CM52|CM55|CM85|STAR_MC3]_NTZ directories.
12+
13+
Note:
14+
The Armv8-M ports support SMP (multicore) systems when both MPU and TrustZone are disabled.
15+
However, this has only been validated on Arm Cortex-M33 Non-TrustZone Non-MPU port.
16+
17+
SMP Boot Sequence
18+
---------------------------------------
19+
20+
Primary core flow:
21+
22+
1. Perform core-specific and shared initialization (e.g., zero-initialize `.bss`).
23+
2. Jump to `main()`, create user tasks, optionally pin tasks to specific cores.
24+
3. Call `vTaskStartScheduler()` which invokes `xPortStartScheduler()`.
25+
4. `xPortStartScheduler()` configures the primary core tick timer and signals secondary cores that shared init is complete using the `ucPrimaryCoreInitDoneFlag` variable.
26+
5. Call the application-defined `configWAKE_SECONDARY_CORES` function.
27+
6. Wait until all secondary cores report as brought up.
28+
7. Once all cores are up, call `vStartFirstTask()` to schedule the first task on the primary core.
29+
30+
Secondary core flow:
31+
32+
1. Perform core-specific initialization.
33+
2. Wait until the primary core signals that shared initialization has completed (that is, `ucPrimaryCoreInitDoneFlag` is set to 1). Once this occurs,
34+
the application-defined `configWAKE_SECONDARY_CORES` function is invoked by the primary core to carry out the subsequent steps.
35+
3. Program the inter-processor signaling mechanism (e.g., Arm Doorbell Mechanism) to be used by the kernel to interrupt that core and request that it perform a context switch.
36+
4. Call `vPortConfigureInterruptPriorities` function to setup per core interrupt priorities.
37+
5. If Pointer Authentication (PAC) or Branch Target Identification (BTI) is supported, call `vConfigurePACBTI` with `pdTRUE` as the input parameter to configure the per-core special-purpose CONTROL register
38+
with the appropriate PACBTI settings.
39+
6. Signal the primary that this secondary is online and ready by setting its flag in the `ucSecondaryCoresReadyFlags` array.
40+
7. Issue an SVC with immediate value `102` (portSVC_START_SCHEDULER), which will call `vRestoreContextOfFirstTask()` to start scheduling on this core.
41+
42+
43+
Inter-core notification
44+
---------------------------------------
45+
46+
On SMP systems the application must provide an implementation of the `vInterruptCore( uint8_t ucCoreID )` function. The kernel calls this function
47+
to interrupt another core and request that it perform a context switch (e.g., when a higher-priority task becomes ready on that core).
48+
49+
Typical platform implementation: write a doorbell flag/bit or other inter-processor signaling register targeting `ucCoreID`. This should cause a
50+
"doorbell" (or equivalent) IRQ on the secondary core. In the secondary core’s doorbell IRQ handler, check the reason for the interrupt and, if it is a
51+
schedule request, trigger a context switch (i.e., by calling `portYIELD_FROM_ISR`).
52+
53+
Notes:
54+
55+
* `vInterruptCore` is declared weak in the port so that platforms can override it. If your hardware lacks a dedicated doorbell, use any available
56+
inter-core interrupt/messaging mechanism to achieve the same effect.
57+
58+
* The application must define `configCORE_ID_REGISTER`, usually in `FreeRTOSConfig.h` to the memory-mapped address of the platform register used
59+
to read the current core ID. The port reads this register to determine the executing core and to index per-core scheduler state.
60+
61+
* The application must define `configWAKE_SECONDARY_CORES`, usually in `FreeRTOSConfig.h`, to point to the application/platform-specific function
62+
that wakes up and make the secondary cores ready after the primary core completes initialisation.

0 commit comments

Comments
 (0)