Skip to content

Commit 94cabc6

Browse files
author
sidart
committed
Summary: Add Initial support to pico2 (Arm Cortex M)
Test Plan: TBD Reviewers: Subscribers: Tasks: Tags:
1 parent 3068e1b commit 94cabc6

File tree

11 files changed

+241
-148
lines changed

11 files changed

+241
-148
lines changed

backends/raspberry_pi/CMakeLists.txt

Lines changed: 0 additions & 14 deletions
This file was deleted.

backends/raspberry_pi/README.md

Lines changed: 0 additions & 1 deletion
This file was deleted.

backends/raspberry_pi/pico2/main.cpp

Lines changed: 0 additions & 129 deletions
This file was deleted.

examples/arm/rp_pi/CMakeLists.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
# All rights reserved.
3+
# Copyright 2023-2025 Arm Limited and/or its affiliates.
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+
cmake_minimum_required(VERSION 3.10)
9+
project(pico)
10+
11+
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
12+
set(EXECUTORCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../../)
13+
14+
15+
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/arm-cortex-m0plus-toolchain.cmake)
16+
17+
# Only include here, NOT in arm-cortex-m0plus-toolchain.cmake
18+
include(${CMAKE_SOURCE_DIR}/tools/cmake/Codegen.cmake)
19+
20+
target_sources(executorch_core PRIVATE ${CMAKE_CURRENT_LIST_DIR}/syscall_stubs.c)
21+
#gen_selected_ops(LIB_NAME "portable_ops_lib" ROOT_OPS "aten::add.out")

examples/arm/rp_pi/README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
## Overview
2+
This document outlines the steps required to run a simple Add Module on the Pico2 microcontroller using executorch.
3+
## Steps
4+
5+
### 1. Cross Compile Executorch for Arm Cortex M Target
6+
To begin, navigate to the executorch root directory and execute the following commands:
7+
```bash
8+
mkdir baremetal_build
9+
cd baremetal_build
10+
cmake .. -DCMAKE_TOOLCHAIN_FILE=./examples/arm/rp_pi/pico2/arm-cortex-m0plus-toolchain.cmake -DEXECUTORCH_BUILD_ARM_BAREMETAL=ON -DCMAKE_BUILD_TYPE=Release -DROOT_OPS=aten::add.out
11+
cmake --build . -j$(nproc)
12+
```
13+
14+
### 2. Export PICO_SDK_PATH
15+
Download the Pico SDK from GitHub: https://github.com/raspberrypi/pico-sdk and set the PICO_SDK_PATH environment variable:
16+
```bash
17+
export PICO_SDK_PATH=<path_to_local_pico_sdk_folder>
18+
```
19+
20+
### 3. Prepare Third-Party Dependencies
21+
Ensure that the c10 and torch folders are present in the executorch/third-party directory.
22+
23+
### 4. Build the example for Pico2
24+
Go to the example directory and initiate the build process:
25+
```bash
26+
cd examples/arm/rp_pi/pico2/
27+
rm -rf build
28+
mkdir build
29+
cd build
30+
cmake .. -DPICO_BOARD=pico2 -DCMAKE_BUILD_TYPE=Release
31+
cmake --build . -j$(nproc)
32+
```
33+
This will generate the firmware file executorch_pico.uf2.
34+
35+
### 5. Flash the Firmware
36+
Press and hold the BOOTSEL button on the Pico2.
37+
Connect the Pico2 to your computer; it should mount as RPI-RP2.
38+
Copy the executorch_pico.uf2 file to the mounted drive.
39+
40+
### 6. Verify the Firmware
41+
Check that the Pico2's LED blinks 10 times to confirm successful firmware execution.
42+
43+
### 7. (Optional) Check USB Logs on Mac
44+
To view USB logs, use the following command:
45+
```bash
46+
screen /dev/tty.usbmodem1101 115200
47+
```
48+
49+
These steps complete the process required to run the simple Add Module on the Pico2 microcontroller using executorch.

backends/raspberry_pi/arm-cortex-m0plus-toolchain.cmake renamed to examples/arm/rp_pi/arm-cortex-m0plus-toolchain.cmake

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
# All rights reserved.
3+
# Copyright 2023-2025 Arm Limited and/or its affiliates.
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+
18
# cortex-m0plus cmake
29

310
if(NOT DEFINED EXECUTORCH_BUILD_ARM_BAREMETAL)

backends/raspberry_pi/pico2/CMakeLists.txt renamed to examples/arm/rp_pi/pico2/CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ cmake_minimum_required(VERSION 3.13)
22
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
33
project(executorch_pico C CXX ASM)
44
pico_sdk_init()
5-
6-
set(EXECUTORCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../../../)
5+
dddd
6+
set(EXECUTORCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../)
77
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
88

9+
# Replace xxx_pte.c with your model's pte file
910
add_executable(executorch_pico main.cpp simple_addmodule_pte.c)
1011
pico_enable_stdio_usb(executorch_pico 1)
1112
pico_enable_stdio_uart(executorch_pico 0)

examples/arm/rp_pi/pico2/main.cpp

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/* Copyright (c) Meta Platforms, Inc. and affiliates.
2+
* All rights reserved.
3+
* Copyright 2023-2025 Arm Limited and/or its affiliates.
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+
9+
#include "simple_addmodule_pte.h"
10+
11+
#include "pico/stdio_usb.h"
12+
#include "pico/stdlib.h"
13+
#include <executorch/extension/data_loader/buffer_data_loader.h>
14+
#include <executorch/runtime/core/portable_type/scalar_type.h>
15+
#include <executorch/runtime/executor/method.h>
16+
#include <executorch/runtime/executor/program.h>
17+
#include <executorch/runtime/platform/runtime.h>
18+
19+
void wait_for_usb() {
20+
const int kMaxRetryCount = 10;
21+
int retry_usb_count = 0;
22+
while (!stdio_usb_connected() && retry_usb_count++ < kMaxRetryCount) {
23+
printf("Retry again! USB not connected \n");
24+
sleep_ms(100);
25+
}
26+
}
27+
28+
bool load_and_prepare_model(Program& program, Method& method, MemoryManager& memory_manager) {
29+
executorch::extension::BufferDataLoader loader(model_pte, model_pte_len);
30+
auto program_result = Program::load(&loader);
31+
if (!program_result.ok()) {
32+
printf("Failed to load model: %d\n", (int)program_result.error());
33+
blink_indicator(INDICATOR_PIN_1, 10);
34+
return false;
35+
}
36+
program = std::move(*program_result);
37+
38+
auto method_name_result = program.get_method_name(0);
39+
if (!method_name_result.ok()) {
40+
printf("Failed to get method name: %d\n", (int)method_name_result.error());
41+
blink_indicator(INDICATOR_PIN_1, 10);
42+
return false;
43+
}
44+
auto method_result = program.load_method(*method_name_result, &memory_manager);
45+
if (!method_result.ok()) {
46+
printf("Failed to load method: %d\n", (int)method_result.error());
47+
blink_indicator(INDICATOR_PIN_1, 10);
48+
return false;
49+
}
50+
method = std::move(*method_result);
51+
printf("Method loaded [%s]\n", *method_name_result);
52+
return true;
53+
}
54+
55+
bool run_inference(Method& method) {
56+
float input_data_0[4] = {4.0, 109.0, 13.0, 123.0};
57+
float input_data_1[4] = {9.0, 27.0, 11.0, 8.0};
58+
TensorImpl::SizesType sizes[1] = {4};
59+
TensorImpl::DimOrderType dim_order[] = {0};
60+
TensorImpl impl0(ScalarType::Float, 1, sizes, input_data_0, dim_order);
61+
TensorImpl impl1(ScalarType::Float, 1, sizes, input_data_1, dim_order);
62+
Tensor input0(&impl0);
63+
Tensor input1(&impl1);
64+
65+
if (method.set_input(input0, 0) != Error::Ok || method.set_input(input1, 1) != Error::Ok) {
66+
printf("Failed to set input(s)\n");
67+
blink_indicator(INDICATOR_PIN_1, 10);
68+
return false;
69+
}
70+
if (method.execute() != Error::Ok) {
71+
printf("Failed to execute\n");
72+
blink_indicator(INDICATOR_PIN_1, 10);
73+
return false;
74+
}
75+
const EValue& output = method.get_output(0);
76+
if (output.isTensor()) {
77+
const float* out_data = output.toTensor().const_data_ptr<float>();
78+
printf("Output: %f, %f, %f, %f\n", out_data[0], out_data[1], out_data[2], out_data[3]);
79+
} else {
80+
printf("Output is not a tensor!\n");
81+
blink_indicator(INDICATOR_PIN_1, 10);
82+
return false;
83+
}
84+
return true;
85+
}
86+
87+
int executor_runner() {
88+
using namespace executorch::extension;
89+
using namespace executorch::runtime;
90+
stdio_init_all();
91+
sleep_ms(1000);
92+
93+
wait_for_usb();
94+
runtime_init();
95+
96+
static uint8_t method_allocator_pool[1024];
97+
static uint8_t activation_pool[512];
98+
MemoryAllocator method_allocator(sizeof(method_allocator_pool), method_allocator_pool);
99+
method_allocator.enable_profiling("method allocator");
100+
Span<uint8_t> memory_planned_buffers[1]{{activation_pool, sizeof(activation_pool)}};
101+
HierarchicalAllocator planned_memory({memory_planned_buffers, 1});
102+
MemoryManager memory_manager(&method_allocator, &planned_memory);
103+
104+
Program program;
105+
Method method;
106+
if (!load_and_prepare_model(program, method, memory_manager)) {
107+
printf("Failed to load and prepare model\n");
108+
return 1;
109+
}
110+
if (!run_inference(method)) {
111+
printf("Failed to run inference\n");
112+
return 1;
113+
}
114+
115+
blink_indicator(INDICATOR_PIN_1, 100, 500);
116+
return 0;
117+
}
118+
119+
int main() {
120+
return executor_runner();
121+
}

backends/raspberry_pi/pico2/simple_addmodule_pte.c renamed to examples/arm/rp_pi/pico2/simple_addmodule_pte.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
1-
__attribute__((aligned(8))) const unsigned char model_pte[] = {
1+
/* Copyright (c) Meta Platforms, Inc. and affiliates.
2+
* All rights reserved.
3+
* Copyright 2023-2025 Arm Limited and/or its affiliates.
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+
9+
#include "simple_addmodule_pte.h"
10+
11+
const uint8_t model_pte[] __attribute__((aligned(8))) = {
212
0x1c, 0x00, 0x00, 0x00, 0x45, 0x54, 0x31, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 0x10, 0x00, 0x00, 0x00,
313
0x44, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
414
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -34,5 +44,4 @@ __attribute__((aligned(8))) const unsigned char model_pte[] = {
3444
0x22, 0x3a, 0x20, 0x22, 0x5b, 0x5d, 0x22, 0x2c, 0x20, 0x22, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x22, 0x3a, 0x20, 0x5b, 0x5d, 0x7d, 0x5d, 0x7d, 0x5d,
3545
0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x00, };
3646

37-
3847
const unsigned int model_pte_len = sizeof(model_pte);

0 commit comments

Comments
 (0)