Skip to content

Commit 043c404

Browse files
authored
Cortex-M backend: enable Cortex-M0+ builds against Corstone-300 (#19731)
### Summary Extend the Cortex-M cross-CPU build pipeline to Armv6-M by patching two upstream issues that block the Corstone-300 target source and the CMSIS Cortex DFP from building for `cortex-m0plus`: * `core_platform/0003-*.patch` guards the `HardFault_Handler` in `targets/corstone-300/target.cpp`. The handler uses an `ite eq` IT-block in inline asm and dereferences the SCB CFSR/BFAR/MMFAR fault-status registers; both are Armv7-M / Armv8-M Mainline only. The patch wraps the rich handler in `__ARM_ARCH_7M__ / 7EM / 8M_MAIN / 8_1M_MAIN` and falls back to a minimal stub on Armv6-M / Armv8-M Baseline (M0/M0+/M23). * `core_software/0002-*.patch` fixes `cmsis.cmake`'s handling of the M0+ device. The Cortex DFP names the device directory and headers `ARMCM0plus` (lowercase suffix), while the device sources (`startup_ARMCM0plus.c`, `system_ARMCM0plus.c`) gate their implementations on the `ARMCM0P` preprocessor macro — three different spellings. The previous `string(TOUPPER ...)` produced `ARMCM0PLUS`: the include path lookup failed and the source files hit their `#error device not specified!` guard. Override `ARM_CPU` to `ARMCM0plus` for the directory + filename and introduce a separate `CMSIS_DEVICE_CPU_DEFINE` set to `ARMCM0P` for the cmsis_startup and cmsis_system compile-definitions; all other cores still drive both paths from the uppercased default. Both patches are layered via the existing `patch_repo` mechanism; the `corstone_utils.cmake` TODO is updated so the deletion plan for 0002 and 0003 is documented together. ### Test Plan Locally validated end-to-end on the Corstone-300 FVP with the `qadd` model: `cortex-m0plus` build links a runner that includes `startup_ARMCM0plus.c` / `system_ARMCM0plus.c` and the patched `target.cpp`, and the FVP run prints `TEST: BundleIO index[0] Test_result: PASS` with all error stats zero. The bundled `libcmsis-nn.a` reports `Tag_CPU_arch: v6S-M` and `Tag_THUMB_ISA_use: Thumb-1` with zero DSP / MVE / saturating instructions, confirming the scalar code path was exercised. Authored with Claude. cc @digantdesai @freddan80 @per @zingo @oscarandersson8218 @mansnils @Sebastian-Larsson @robell
1 parent 6128a45 commit 043c404

3 files changed

Lines changed: 132 additions & 5 deletions

File tree

backends/arm/scripts/corstone_utils.cmake

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,12 @@ function(fetch_ethos_u_content ETHOS_SDK_PATH ET_DIR_PATH)
5050
WORKING_DIRECTORY ${ET_DIR_PATH}
5151
)
5252
# Always patch the core_platform repo since this is fast enough. TODO:
53-
# examples/arm/ethos-u-setup/core_platform/0002-*.patch is a transient bridge
54-
# that guards Armv8-M-only MPU init so the source compiles for non-Armv8-M
55-
# Cortex-M cores. Once the same guard lands upstream in ethos-u/core_platform
56-
# and ${core_platform_base_rev} is bumped past that commit, delete the 0002
57-
# patch.
53+
# examples/arm/ethos-u-setup/core_platform/0002-*.patch and 0003-*.patch are
54+
# transient bridges that guard Armv8-M-only MPU init and the Armv7-M-and-newer
55+
# HardFault handler so the Corstone-300 target source compiles for older
56+
# Cortex-M cores. Once the equivalent guards land upstream in
57+
# ethos-u/core_platform and ${core_platform_base_rev} is bumped past those
58+
# commits, delete the 0002 and 0003 patches.
5859
set(core_platform_base_rev "26.02")
5960
execute_process(
6061
COMMAND
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
From 380045853a133f298cee1bcf0c959b93ea94f9a2 Mon Sep 17 00:00:00 2001
2+
From: RJ Ascani <rja@meta.com>
3+
Date: Wed, 13 May 2026 15:42:13 -0700
4+
Subject: [PATCH] Guard HardFault_Handler for Armv6-M / Armv8-M Baseline
5+
6+
The Corstone-300 HardFault_Handler is written for Armv7-M / Armv8-M
7+
Mainline: it uses an `ite eq` IT-block in inline asm, and dereferences
8+
the SCB CFSR/BFAR/MMFAR fault-status registers. Neither is available
9+
on Armv6-M (Cortex-M0/M0+) or Armv8-M Baseline (Cortex-M23), so the
10+
file fails to compile when the Corstone-300 target source is built
11+
with `-mcpu=cortex-m0plus` to exercise the scalar CMSIS-NN code paths
12+
on the Corstone-300 M55 simulator (an ISA superset).
13+
14+
Wrap the Mainline-only implementation in
15+
`__ARM_ARCH_7M__ / 7EM / 8M_MAIN / 8_1M_MAIN` and fall back to a
16+
minimal `printf("Hard fault"); exit(1)` stub on Baseline cores.
17+
---
18+
targets/corstone-300/target.cpp | 8 ++++++++
19+
1 file changed, 8 insertions(+)
20+
21+
diff --git a/targets/corstone-300/target.cpp b/targets/corstone-300/target.cpp
22+
index bda2248..4aa3eea 100644
23+
--- a/targets/corstone-300/target.cpp
24+
+++ b/targets/corstone-300/target.cpp
25+
@@ -246,6 +246,11 @@ struct ExcContext {
26+
};
27+
28+
void HardFault_Handler() {
29+
+ // Armv6-M (M0/M0+) and Armv8-M Baseline (M23) lack the IT instruction and
30+
+ // the SCB CFSR/BFAR/MMFAR fault-status registers, so the rich handler
31+
+ // can't compile or run there. Fall back to a minimal stub on those cores.
32+
+#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__) || \
33+
+ defined(__ARM_ARCH_8_1M_MAIN__)
34+
int irq;
35+
struct ExcContext *e;
36+
uint32_t sp;
37+
@@ -267,6 +272,9 @@ void HardFault_Handler() {
38+
sp);
39+
printf(
40+
"%11s cfsr=0x%08" PRIx32 " bfar=0x%08" PRIx32 " mmfar=0x%08" PRIx32 "\n", "", SCB->CFSR, SCB->BFAR, SCB->MMFAR);
41+
+#else
42+
+ printf("Hard fault\n");
43+
+#endif
44+
exit(1);
45+
}
46+
}
47+
--
48+
2.53.0
49+
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
From 1ee9cf9c956ea6a266fc79dfa62071131f162510 Mon Sep 17 00:00:00 2001
2+
From: RJ Ascani <rja@meta.com>
3+
Date: Wed, 13 May 2026 15:48:07 -0700
4+
Subject: [PATCH] Fix ARMCM0plus directory case and compile-define mismatch
5+
MIME-Version: 1.0
6+
Content-Type: text/plain; charset=UTF-8
7+
Content-Transfer-Encoding: 8bit
8+
9+
The Cortex DFP names the Cortex-M0+ device directory and headers
10+
`ARMCM0plus` (lowercase suffix), while the device source files
11+
(`startup_ARMCM0plus.c`, `system_ARMCM0plus.c`) gate their
12+
implementations on the `ARMCM0P` preprocessor macro — three different
13+
spellings. `cmsis.cmake` previously did
14+
`string(TOUPPER \"ARMCM\${CPU_NUMBER}\" ARM_CPU)`, producing
15+
`ARMCM0PLUS`: the include path lookup fails and the source files hit
16+
their `#error device not specified!` guard.
17+
18+
Override `ARM_CPU` to `ARMCM0plus` and introduce a separate
19+
`CMSIS_DEVICE_CPU_DEFINE` set to `ARMCM0P` for the cmsis_startup and
20+
cmsis_system compile-definitions; all other cores still drive both
21+
paths from the uppercased default.
22+
---
23+
cmsis.cmake | 20 ++++++++++++++++++--
24+
1 file changed, 18 insertions(+), 2 deletions(-)
25+
26+
diff --git a/cmsis.cmake b/cmsis.cmake
27+
index 7f2b93f..c49f205 100644
28+
--- a/cmsis.cmake
29+
+++ b/cmsis.cmake
30+
@@ -23,6 +23,15 @@ endif()
31+
32+
string(TOUPPER "ARMCM${CPU_NUMBER}" ARM_CPU)
33+
34+
+# Cortex-M0+ is special: the Cortex DFP names the device directory and headers
35+
+# `ARMCM0plus` (lowercase suffix), while the device sources gate their
36+
+# implementations on the `ARMCM0P` preprocessor macro. Override both so the
37+
+# directory lookup and `#include` resolution succeed; the compile-definition
38+
+# override is applied instead of `CMSIS_DEVICE_CPU_FEATURE` further down.
39+
+if(CPU_NUMBER STREQUAL "0plus")
40+
+ set(ARM_CPU "ARMCM0plus")
41+
+endif()
42+
+
43+
# Set CPU specific features
44+
if(CMAKE_SYSTEM_PROCESSOR MATCHES "cortex-m33(\\+|$)")
45+
set(ARM_FEATURES "_DSP_FP")
46+
@@ -50,6 +59,13 @@ else()
47+
cmake_path(SET CMSIS_DEVICE_CPU_FEATURE "${ARM_CPU}")
48+
endif()
49+
50+
+# Macro the device sources gate on. Matches CMSIS_DEVICE_CPU_FEATURE for most
51+
+# cores; Cortex-M0+ keys off `ARMCM0P`, not `ARMCM0plus`.
52+
+set(CMSIS_DEVICE_CPU_DEFINE "${CMSIS_DEVICE_CPU_FEATURE}")
53+
+if(CPU_NUMBER STREQUAL "0plus")
54+
+ set(CMSIS_DEVICE_CPU_DEFINE "ARMCM0P")
55+
+endif()
56+
+
57+
target_include_directories(cmsis_device INTERFACE ${CMSIS_DEVICE_PATH}/${ARM_CPU}/Include)
58+
59+
target_compile_options(cmsis_device INTERFACE
60+
@@ -66,12 +82,12 @@ target_sources(cmsis_startup INTERFACE
61+
set_source_files_properties(${CMSIS_DEVICE_PATH}/${ARM_CPU}/Source/startup_${ARM_CPU}.c
62+
PROPERTIES COMPILE_FLAGS -Wno-redundant-decls)
63+
64+
-target_compile_definitions(cmsis_startup INTERFACE ${CMSIS_DEVICE_CPU_FEATURE})
65+
+target_compile_definitions(cmsis_startup INTERFACE ${CMSIS_DEVICE_CPU_DEFINE})
66+
target_link_libraries(cmsis_startup INTERFACE cmsis_device)
67+
68+
# CMSIS system
69+
add_library(cmsis_system INTERFACE)
70+
target_sources(cmsis_system INTERFACE
71+
${CMSIS_DEVICE_PATH}/${ARM_CPU}/Source/system_${ARM_CPU}.c)
72+
-target_compile_definitions(cmsis_system INTERFACE ${CMSIS_DEVICE_CPU_FEATURE})
73+
+target_compile_definitions(cmsis_system INTERFACE ${CMSIS_DEVICE_CPU_DEFINE})
74+
target_link_libraries(cmsis_system INTERFACE cmsis_startup)
75+
--
76+
2.53.0
77+

0 commit comments

Comments
 (0)