Skip to content

Commit 494784d

Browse files
committed
Arm backend: Add Zephyr Cortex-M STM Nucleo n657x0_q example
Moves the Ethos-U driver config to Corstone FVPs board files. This enable smoother building different targets that will enable or not enable the Ethos-U drivers/backend depending on board. This makes it possible to build the example both for Ethos-U and Cortex-M only targets without change. Signed-off-by: Zingo Andersen <Zingo.Andersen@arm.com> Change-Id: I9a7092b3480b479111249f4d101c6f787e3923ed
1 parent 05da1af commit 494784d

File tree

7 files changed

+116
-26
lines changed

7 files changed

+116
-26
lines changed

examples/arm/zephyr/CMakeLists.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Copyright (c) Meta Platforms, Inc. and affiliates.
22
# All rights reserved.
3-
# Copyright 2025 Arm Limited and/or its affiliates.
3+
# Copyright 2025-2026 Arm Limited and/or its affiliates.
44
#
55
# SPDX-License-Identifier: Apache-2.0
66

@@ -85,8 +85,6 @@ else()
8585
)
8686
endif()
8787

88-
set(CONF_FILE "${CMAKE_CURRENT_SOURCE_DIR}/prj.conf")
89-
9088
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
9189
project(executorch_executor_runner)
9290

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright 2026 Arm Limited and/or its affiliates.
2+
#
3+
# This source code is licensed under the BSD-style license found in the
4+
# LICENSE file in the root directory of this source tree.
5+
#
6+
# Enable the Zephyr Ethos-U driver so executorch_delegate_ethos_u can reserve
7+
# and use the hardware instance exposed by the board DTS
8+
# as the board has one available.
9+
CONFIG_ETHOS_U=y
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright 2026 Arm Limited and/or its affiliates.
2+
#
3+
# This source code is licensed under the BSD-style license found in the
4+
# LICENSE file in the root directory of this source tree.
5+
#
6+
# Enable the Zephyr Ethos-U driver so executorch_delegate_ethos_u can reserve
7+
# and use the hardware instance exposed by the board DTS
8+
# as the board has one available.
9+
CONFIG_ETHOS_U=y

examples/arm/zephyr/prj.conf

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,20 @@ CONFIG_REQUIRES_FLOAT_PRINTF=y
2424
# Setting this means you will include all portable ops
2525
CONFIG_EXECUTORCH_BUILD_PORTABLE_OPS=n
2626

27-
# Enable the Zephyr Ethos-U driver so executorch_delegate_ethos_u can reserve
28-
# and use the hardware instance exposed by the board DTS.
29-
CONFIG_ETHOS_U=y
30-
31-
# Add model specific configs
32-
# The default 1 KB pool is too small even for the tiny sample model;
33-
# bump to 256 KB so method buffers and inputs fit during setup.
34-
CONFIG_EXECUTORCH_METHOD_ALLOCATOR_POOL_SIZE=262144
35-
# Ethos-U scratch memory requirements scale with the compiled network.
36-
CONFIG_EXECUTORCH_TEMP_ALLOCATOR_POOL_SIZE=1572864
27+
# To enable the Zephyr Ethos-U driver so executorch_delegate_ethos_u can reserve
28+
# and use the hardware instance exposed by the board DTS is controlled with
29+
# CONFIG_ETHOS_U=y
30+
# This is handled in board specific .conf files, e.g.:
31+
# examples/arm/zephyr/boards/mps4_corstone320_fvp.conf
32+
# To be able to build the example for different HW, in your own project you can
33+
# copy the relevant lines from those files into your own prj.conf
3734

3835
# Enable Helium (MVE) builds of CMSIS-NN by selecting the FPU and hard-float ABI.
3936
CONFIG_FPU=y
4037
CONFIG_FP_HARDABI=y
38+
39+
# Add model specific configs
40+
41+
# Setup memory requirements to scale with the compiled model/network.
42+
CONFIG_EXECUTORCH_METHOD_ALLOCATOR_POOL_SIZE=2000
43+
CONFIG_EXECUTORCH_TEMP_ALLOCATOR_POOL_SIZE=2000

examples/arm/zephyr/src/arm_executor_runner.cpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* Copyright (c) Meta Platforms, Inc. and affiliates.
22
* All rights reserved.
3-
* Copyright 2025 Arm Limited and/or its affiliates.
3+
* Copyright 2025-2026 Arm Limited and/or its affiliates.
44
*
55
* This source code is licensed under the BSD-style license found in the
66
* LICENSE file in the root directory of this source tree.
@@ -180,7 +180,7 @@ Result<BufferCleanup> prepare_input_tensors(
180180

181181
// If input_buffers.size <= 0, we don't have any input, fill it with 1's.
182182
if (input_buffers.size() <= 0) {
183-
for (size_t j = 0; j < t.numel(); j++) {
183+
for (size_t j = 0; j < static_cast<size_t>(t.numel()); j++) {
184184
switch (t.scalar_type()) {
185185
case ScalarType::Int:
186186
t.mutable_data_ptr<int>()[j] = 1;
@@ -226,7 +226,11 @@ int main(int argc, const char* argv[]) {
226226
std::vector<std::pair<char*, size_t>> input_buffers;
227227
size_t pte_size = sizeof(model_pte);
228228

229-
ET_LOG(Info, "PTE at %p Size: %lu bytes", model_pte, pte_size);
229+
ET_LOG(
230+
Info,
231+
"PTE at %p Size: %lu bytes",
232+
model_pte,
233+
static_cast<unsigned long>(pte_size));
230234

231235
// Find the offset to the embedded Program.
232236
if (!model_pte_runtime_initialized) {
@@ -237,7 +241,10 @@ int main(int argc, const char* argv[]) {
237241
size_t program_data_len = pte_size;
238242

239243
auto loader = BufferDataLoader(program_data, program_data_len);
240-
ET_LOG(Info, "PTE Model data loaded. Size: %lu bytes.", program_data_len);
244+
ET_LOG(
245+
Info,
246+
"PTE Model data loaded. Size: %lu bytes.",
247+
static_cast<unsigned long>(program_data_len));
241248

242249
// Parse the program file. This is immutable, and can also be reused
243250
// between multiple execution invocations across multiple threads.
@@ -247,7 +254,7 @@ int main(int argc, const char* argv[]) {
247254
Info,
248255
"Program loading failed @ 0x%p: 0x%" PRIx32,
249256
program_data,
250-
program.error());
257+
static_cast<uint32_t>(program.error()));
251258
}
252259

253260
ET_LOG(Info, "Model buffer loaded, has %zu methods", program->num_methods());
@@ -325,7 +332,7 @@ int main(int argc, const char* argv[]) {
325332
Info,
326333
"Loading of method %s failed with status 0x%" PRIx32,
327334
method_name,
328-
method.error());
335+
static_cast<uint32_t>(method.error()));
329336
}
330337
size_t method_loaded_memsize =
331338
method_allocator.used_size() - method_loaded_membase;
@@ -351,7 +358,7 @@ int main(int argc, const char* argv[]) {
351358
Info,
352359
"Preparing inputs tensors for method %s failed with status 0x%" PRIx32,
353360
method_name,
354-
prepared_inputs.error());
361+
static_cast<uint32_t>(prepared_inputs.error()));
355362
}
356363
}
357364
#if defined(ET_DUMP_INPUT)
@@ -409,8 +416,14 @@ int main(int argc, const char* argv[]) {
409416
Error status = method->execute();
410417
size_t executor_memsize = method_allocator.used_size() - executor_membase;
411418

412-
ET_LOG(Info, "model_pte_program_size: %lu bytes.", program_data_len);
413-
ET_LOG(Info, "model_pte_loaded_size: %lu bytes.", pte_size);
419+
ET_LOG(
420+
Info,
421+
"model_pte_program_size: %lu bytes.",
422+
static_cast<unsigned long>(program_data_len));
423+
ET_LOG(
424+
Info,
425+
"model_pte_loaded_size: %lu bytes.",
426+
static_cast<unsigned long>(pte_size));
414427
if (method_allocator.size() != 0) {
415428
size_t method_allocator_used = method_allocator.used_size();
416429
ET_LOG(
@@ -432,7 +445,7 @@ int main(int argc, const char* argv[]) {
432445
Info,
433446
"Execution of method %s failed with status 0x%" PRIx32,
434447
method_name,
435-
status);
448+
static_cast<uint32_t>(status));
436449
} else {
437450
ET_LOG(Info, "Model executed successfully.");
438451
}

zephyr/CMakeLists.txt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Copyright (c) 2025 Petri Oksanen
22
# Copyright (c) Meta Platforms, Inc. and affiliates.
33
# All rights reserved.
4-
# Copyright 2025 Arm Limited and/or its affiliates.
4+
# Copyright 2025-2026 Arm Limited and/or its affiliates.
55
#
66
# SPDX-License-Identifier: Apache-2.0
77

@@ -14,6 +14,18 @@ if(CONFIG_EXECUTORCH)
1414
include(${EXECUTORCH_DIR}/tools/cmake/common/preset.cmake)
1515
include(${EXECUTORCH_DIR}/tools/cmake/preset/zephyr.cmake)
1616

17+
# Prefer a local CMSIS-NN checkout from the Zephyr workspace if available.
18+
if(NOT DEFINED CMSIS_NN_LOCAL_PATH OR CMSIS_NN_LOCAL_PATH STREQUAL "")
19+
set(_cmsis_nn_default "${ZEPHYR_BASE}/../modules/lib/cmsis-nn")
20+
if(EXISTS "${_cmsis_nn_default}")
21+
set(CMSIS_NN_LOCAL_PATH
22+
"${_cmsis_nn_default}"
23+
CACHE PATH "Path to existing local CMSIS-NN installation"
24+
)
25+
message(STATUS "CMSIS_NN_LOCAL_PATH set to: ${CMSIS_NN_LOCAL_PATH}")
26+
endif()
27+
endif()
28+
1729
# HACK: Force the parent directory of executorch into the global include path.
1830
# This is needed because the executorch CMake scripts generate a relative
1931
# include path ("../") that doesn't resolve correctly in a Zephyr out-of-tree
@@ -51,7 +63,9 @@ if(CONFIG_EXECUTORCH)
5163

5264
set(EXECUTORCH_BUILD_EXTENSION_RUNNER_UTIL ON)
5365
set(EXECUTORCH_BUILD_KERNELS_QUANTIZED ON)
54-
set(EXECUTORCH_BUILD_KERNELS_QUANTIZED_AOT ON)
66+
# Zephyr builds use -fno-rtti; AOT quantized kernels pull in Torch headers
67+
# that require RTTI, so disable to avoid build failures.
68+
set(EXECUTORCH_BUILD_KERNELS_QUANTIZED_AOT OFF)
5569

5670
set(EXECUTORCH_ENABLE_LOGGING ${CONFIG_EXECUTORCH_ENABLE_LOGGING})
5771
set(EXECUTORCH_ENABLE_EVENT_TRACER ${CONFIG_EXECUTORCH_ENABLE_EVENT_TRACER})

zephyr/README.md

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ manifest:
5252

5353
## Run west config and update:
5454

55-
Add ExecuTorch to Zephyr
55+
Add ExecuTorch and Ethos-U driver to Zephyr
5656
<!-- RUN west_config -->
5757
```
5858
west config manifest.project-filter -- -.*,+zephyr,+executorch,+cmsis,+cmsis_6,+cmsis-nn,+hal_ethos_u
@@ -88,6 +88,9 @@ modules/lib/executorch/examples/arm/setup.sh --i-agree-to-the-contained-eula
8888

8989
To run you need to point of the path to the installed Corstone&trade; FVP and you can then use west to build and run. You point out the model PTE file you want to run with -DET_PTE_FILE_PATH= see below.
9090

91+
The magic to include and use Ethos-U backend is to set
92+
CONFIG_ETHOS_U=y/n
93+
This is done in the example depending on the board you build for so it you build for a different board then the ones below you might want to add a board config file, or add this line to the prj.conf
9194

9295
## Corstone&trade; 300 FVP (Ethos&trade;-U55)
9396

@@ -176,6 +179,47 @@ Run the Ethos-U85 PTE model
176179
west build -b mps4/corstone320/fvp modules/lib/executorch/examples/arm/zephyr -t run -- -DET_PTE_FILE_PATH=add_u85_256.pte
177180
```
178181

182+
## STM Nucleo n657x0_q
183+
184+
### Run west config and update:
185+
186+
You need to add hal_stm32 driver to Zephyr
187+
```
188+
west config manifest.project-filter -- -.*,+zephyr,+executorch,+cmsis,+cmsis_6,+cmsis-nn,+hal_stm32
189+
west update
190+
```
191+
192+
### Setup tools
193+
194+
Follow and make sure tools are setup according to this:
195+
196+
https://docs.zephyrproject.org/latest/boards/st/nucleo_n657x0_q/doc/index.html
197+
198+
Test the samples/hello_world in that guide to make sure all tools work.
199+
200+
Please note that the ZephyrOS made a fix for the signing tool version v2.21.0 after the v4.3 release in 20 Nov 2025. Make sure to use a later version of ZephyrOS that contains it.
201+
Also note that the signing tool must be in your path for it to auto sign your elf.
202+
203+
```
204+
export PATH=$PATH:~/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin
205+
```
206+
207+
### Prepare a PTE model file
208+
209+
Prepare the Cortex-M55 PTE model
210+
```
211+
python -m modules.lib.executorch.examples.arm.aot_arm_compiler --model_name=modules/lib/executorch/examples/arm/example_modules/add.py --quantize --output=add_m55.pte
212+
```
213+
214+
#### Build and run
215+
216+
Run the Cortex-M55 PTE model
217+
```
218+
west build -b nucleo_n657x0_q modules/lib/executorch/examples/arm/zephyr -- -DET_PTE_FILE_PATH=add_m55.pte
219+
west flash
220+
```
221+
This will run the simple add model on your hardware one and print the output on the serial consol.
222+
179223
## Notable files
180224

181225
# executorch.yaml

0 commit comments

Comments
 (0)