Skip to content

Commit 7ffe3f1

Browse files
sidartGithub Executorch
authored andcommitted
Summary: PoC to run/infer a simple mode on raspberry pi pico2
Test Plan: 1 Build pico2 firmware executorch/examples/rpi/build_firmware_pico.sh 2. Flash the firmware : 'executorch_pico.uf2' 3. Verify that it successfully runs / infers the simple add module Reviewers: Subscribers: Tasks: Tags:
1 parent 19d22ab commit 7ffe3f1

File tree

7 files changed

+716
-0
lines changed

7 files changed

+716
-0
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#!/bin/bash
2+
# Copyright (c) Meta Platforms, Inc. and affiliates.
3+
# All rights reserved.
4+
#
5+
# This source code is licensed under the BSD-style license found in the
6+
# LICENSE file in the root directory of this source tree.
7+
8+
#!/bin/bash
9+
# build_firmware_pico.sh
10+
# Simple script to cross-compile ExecuTorch and build Pico2 firmware with optional model input
11+
12+
set -e
13+
14+
# Paths
15+
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)" # examples/rpi/ -> root dir
16+
PICO2_DIR="${ROOT_DIR}/examples/rpi/pico2"
17+
BUILD_DIR="${PICO2_DIR}/build"
18+
EXECUTORCH_BUILD_DIR="${ROOT_DIR}/cmake-out"
19+
20+
# Default model
21+
DEFAULT_MODEL="default_model.pte"
22+
23+
usage() {
24+
echo "Usage: $0 [--clean] [--model=path/to/model.pte]"
25+
echo " --clean Clean build directories"
26+
echo " --model=FILE Specify model file to embed (relative to pico2/)"
27+
exit 1
28+
}
29+
30+
# Parse args
31+
MODEL_INPUT=""
32+
CLEAN_BUILD=0
33+
34+
for arg in "$@"; do
35+
case $arg in
36+
--clean)
37+
CLEAN_BUILD=1
38+
shift
39+
;;
40+
--model=*)
41+
MODEL_INPUT="${arg#*=}"
42+
shift
43+
;;
44+
*)
45+
usage
46+
;;
47+
esac
48+
done
49+
50+
# Clean if requested
51+
if [ $CLEAN_BUILD -eq 1 ]; then
52+
echo "Cleaning build directories..."
53+
rm -rf "${EXECUTORCH_BUILD_DIR}" "${BUILD_DIR}"
54+
echo "Clean complete."
55+
exit 0
56+
fi
57+
58+
# Step 1: Cross compile ExecuTorch from root dir
59+
echo "Cross compiling ExecuTorch baremetal ARM..."
60+
61+
cmake -B "${EXECUTORCH_BUILD_DIR}" \
62+
-DCMAKE_TOOLCHAIN_FILE="${ROOT_DIR}/examples/arm/ethos-u-setup/arm-none-eabi-gcc.cmake" \
63+
-DTARGET_CPU=cortex-m0plus \
64+
-DEXECUTORCH_BUILD_ARM_BAREMETAL=ON \
65+
-DEXECUTORCH_PAL_DEFAULT=minimal \
66+
-DEXECUTORCH_DTYPE_SELECTIVE_BUILD=ON \
67+
-DCMAKE_BUILD_TYPE=MinSizeRel \
68+
-DEXECUTORCH_ENABLE_LOGGING=OFF \
69+
-DEXECUTORCH_SELECT_ALL_OPS=OFF \
70+
-DEXECUTORCH_BUILD_EXECUTOR_RUNNER=OFF \
71+
-DCMAKE_INSTALL_PREFIX="${EXECUTORCH_BUILD_DIR}" \
72+
"${ROOT_DIR}"
73+
74+
cmake --build "${EXECUTORCH_BUILD_DIR}" --target install -j$(nproc)
75+
76+
echo "ExecuTorch cross compile complete."
77+
78+
# Step 2: Build firmware for Pico2 with model input
79+
80+
cd "${PICO2_DIR}"
81+
82+
if [ -n "$MODEL_INPUT" ]; then
83+
# Use specified model
84+
if [ ! -f "${MODEL_INPUT}" ]; then
85+
echo "Error: Specified model file '${MODEL_INPUT}' not found in pico2 directory."
86+
exit 1
87+
fi
88+
echo "Building firmware with model: ${MODEL_INPUT}"
89+
cmake -B "${BUILD_DIR}" -DPICO_BOARD=pico2 -DINPUT_MODEL="./${MODEL_INPUT}" -DCMAKE_BUILD_TYPE=Release
90+
else
91+
# Use default model
92+
echo "Building firmware with default model: ${DEFAULT_MODEL}"
93+
cmake -B "${BUILD_DIR}" -DPICO_BOARD=pico2 -DINPUT_MODEL="./${DEFAULT_MODEL}" -DCMAKE_BUILD_TYPE=Release
94+
fi
95+
96+
cmake --build "${BUILD_DIR}" -j$(nproc)
97+
98+
echo "Firmware build complete. Output in ${BUILD_DIR}, Binary: executorch_pico.uf2"

examples/rpi/pico2/CMakeLists.txt

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
# All rights reserved.
3+
#
4+
# This source code is licensed under the BSD-style license found in the LICENSE
5+
# file in the root directory of this source tree.
6+
7+
cmake_minimum_required(VERSION 3.13)
8+
9+
# Include FetchContent for Pico SDK
10+
include(FetchContent)
11+
12+
FetchContent_Declare(
13+
pico_sdk
14+
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk.git
15+
GIT_TAG 2.0.0
16+
)
17+
18+
FetchContent_MakeAvailable(pico_sdk)
19+
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
20+
include(${PICO_SDK_PATH}/pico_sdk_init.cmake)
21+
22+
project(executorch_pico C CXX ASM)
23+
pico_sdk_init()
24+
25+
set(EXECUTORCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../../..)
26+
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
27+
28+
# Configure input model file
29+
set(INPUT_MODEL "default_model.pte" CACHE STRING "Input PTE model file to embed")
30+
31+
# Convert relative paths to absolute
32+
if(NOT IS_ABSOLUTE "${INPUT_MODEL}")
33+
set(INPUT_MODEL "${CMAKE_CURRENT_SOURCE_DIR}/${INPUT_MODEL}")
34+
endif()
35+
36+
message(STATUS "Using model file: ${INPUT_MODEL}")
37+
38+
# Validate model file exists
39+
if(NOT EXISTS "${INPUT_MODEL}")
40+
message(FATAL_ERROR "Model file '${INPUT_MODEL}' does not exist.")
41+
endif()
42+
43+
# Create model_pte.c if it doesn't exist
44+
set(MODEL_PTE_C "${CMAKE_CURRENT_SOURCE_DIR}/model_pte.c")
45+
if(NOT EXISTS "${MODEL_PTE_C}")
46+
file(WRITE "${MODEL_PTE_C}"
47+
"#include \"model_pte.h\"\n"
48+
"\n"
49+
"const uint8_t model_pte[] __attribute__((aligned(8))) = {\n"
50+
" // Model data will be injected here\n"
51+
"};\n"
52+
"\n"
53+
"const unsigned int model_pte_len = sizeof(model_pte);\n"
54+
)
55+
message(STATUS "Created initial model_pte.c")
56+
endif()
57+
58+
# Use a stamp file instead of declaring model_pte.c as OUTPUT
59+
set(MODEL_STAMP "${CMAKE_CURRENT_BINARY_DIR}/model_pte.stamp")
60+
61+
add_custom_command(
62+
OUTPUT ${MODEL_STAMP}
63+
COMMAND python3 ${EXECUTORCH_ROOT}/executorch/examples/rpi/pte_to_array.py
64+
--model ${INPUT_MODEL}
65+
--file ${MODEL_PTE_C}
66+
COMMAND ${CMAKE_COMMAND} -E touch ${MODEL_STAMP}
67+
DEPENDS ${INPUT_MODEL} ${EXECUTORCH_ROOT}/executorch/examples/rpi/pte_to_array.py
68+
COMMENT "Injecting PTE data from '${INPUT_MODEL}' into model_pte.c"
69+
VERBATIM
70+
)
71+
72+
# Target to ensure model injection happens
73+
add_custom_target(inject_model_data ALL DEPENDS ${MODEL_STAMP})
74+
75+
# Check if source files exist
76+
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp")
77+
message(FATAL_ERROR "main.cpp not found in ${CMAKE_CURRENT_SOURCE_DIR}")
78+
endif()
79+
80+
# Create the executable
81+
add_executable(executorch_pico
82+
main.cpp
83+
${MODEL_PTE_C} # Use the full path to be explicit
84+
)
85+
86+
# Ensure model data is injected before building
87+
add_dependencies(executorch_pico inject_model_data)
88+
89+
# Set correct target properties for Pico2/RP2350
90+
set_target_properties(
91+
executorch_pico
92+
PROPERTIES
93+
SUFFIX ".elf"
94+
OUTPUT_NAME "executorch_pico"
95+
)
96+
97+
# Configure Pico-specific settings
98+
pico_enable_stdio_usb(executorch_pico 1)
99+
pico_enable_stdio_uart(executorch_pico 0)
100+
101+
# Set correct flags for Pico2 (RP2350)
102+
target_compile_options(
103+
executorch_pico PRIVATE
104+
-mcpu=cortex-m33 # Correct CPU for Pico2
105+
-mfloat-abi=soft
106+
-mthumb
107+
)
108+
109+
target_include_directories(
110+
executorch_pico
111+
PRIVATE
112+
${EXECUTORCH_ROOT}
113+
${EXECUTORCH_ROOT}/executorch/third-party
114+
${EXECUTORCH_ROOT}/executorch/runtime/core/portable_type/c10
115+
)
116+
117+
target_compile_definitions(
118+
executorch_pico
119+
PRIVATE
120+
C10_USING_CUSTOM_GENERATED_MACROS
121+
EXECUTORCH_ENABLE_LOGGING=OFF
122+
EXECUTORCH_PAL_DEFAULT=minimal
123+
)
124+
125+
# Optimization flags
126+
target_compile_options(
127+
executorch_pico PRIVATE
128+
-Os
129+
-ffunction-sections
130+
-fdata-sections
131+
)
132+
133+
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
134+
135+
set(BAREMETAL_BUILD_DIR ${EXECUTORCH_ROOT}/executorch/cmake-out/)
136+
137+
# Link ExecuTorch and Pico libraries
138+
target_link_libraries(
139+
executorch_pico
140+
PRIVATE
141+
${BAREMETAL_BUILD_DIR}/lib/libexecutorch.a
142+
${BAREMETAL_BUILD_DIR}/lib/libexecutorch_core.a
143+
-Wl,--whole-archive
144+
${BAREMETAL_BUILD_DIR}/lib/libportable_ops_lib.a
145+
-Wl,--no-whole-archive
146+
${BAREMETAL_BUILD_DIR}/lib/libportable_kernels.a
147+
pico_stdlib
148+
pico_stdio_usb
149+
)
150+
151+
# Only add extra outputs if the target builds successfully
152+
if(TARGET executorch_pico)
153+
pico_add_extra_outputs(executorch_pico)
154+
endif()

examples/rpi/pico2/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Overview
2+
This document outlines the steps required to run a simple Add Module on the Pico2 microcontroller using executorch.
3+
4+
## (Pre-requisistes) Prepare the Environment for Arm
5+
1. See <a href="https://docs.pytorch.org/executorch/main/tutorial-arm.html#set-up-the-developer-environment"/> for instructions on setting up the environment for Arm.
6+
2. Make sure you have the toolchain configured correctly.
7+
```bash
8+
which arm-none-eabi-gcc
9+
--> return something like executorch/examples/arm/ethos-u-scratch/arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc
10+
```
11+
12+
## Build Pico2 Firmware with Executorch
13+
14+
This step involves two sub steps
15+
16+
1. Cross Compile Executorch for Arm Cortex M, Pico2 target
17+
2. Build the firmware with the input model provided (If not provided, it will use the default_model.pte)
18+
19+
Use the following command to build the firmware:
20+
``` bash
21+
executorch/examples/rpi/build_firmware_pico.sh
22+
```
23+
24+
### Flash Firmware
25+
Hold the BOOTSEL button on the Pico2 and connect it to your computer; it will mount as RPI-RP2. Copy the executorch_pico.uf2 file to this drive.
26+
27+
### Verify Execution
28+
Check that the Pico2's LED blinks 10 times at 500 ms interval to confirm successful firmware execution.
29+
The Pico2's LED should blink 10 times at 500 ms intervals, indicating successful firmware execution. If connected via serial, you should see:
30+
31+
```bash
32+
Method loaded [forward]
33+
Output: 13.000000, 136.000000, 24.000000, 131.000000
34+
```
35+
36+
### Debugging via Serial Terminal
37+
On macOS or Linux, open a serial terminal with:
38+
```bash
39+
screen /dev/tty.usbmodem1101 115200
40+
```
41+
42+
Replace /dev/tty.usbmodem1101 with your device path. This terminal shows program logs and errors. If
43+
the LED blinks 10 times at 100 ms intervals, your program hit an error state—check the logs here.
44+
45+
These steps complete running the simple model on Pico2 using ExecuTorch.

0 commit comments

Comments
 (0)