Skip to content

Add example for Espressif ESP32 executorch runner with no optimizations#18224

Open
jpiat wants to merge 34 commits intopytorch:mainfrom
jpiat:espressif-example
Open

Add example for Espressif ESP32 executorch runner with no optimizations#18224
jpiat wants to merge 34 commits intopytorch:mainfrom
jpiat:espressif-example

Conversation

@jpiat
Copy link
Copy Markdown

@jpiat jpiat commented Mar 17, 2026

Summary

This PR introduce a new example for the ESP32 Espressif SoC. The example implement an executorch runner for the ESP32 platform and a project that executes a simple network. The example does not use ops optimized for ESP32 platform but demonstrate feasibility.

Test plan

This example was tested on a ESP32-S3 development platform. The project compiles and when loaded on the platform show the expected log trace.

cc @psiddh @AdrianLundell @digantdesai

@jpiat jpiat requested a review from larryliu0820 as a code owner March 17, 2026 07:59
Copilot AI review requested due to automatic review settings March 17, 2026 07:59
@jpiat jpiat requested a review from kirklandsign as a code owner March 17, 2026 07:59
@pytorch-bot
Copy link
Copy Markdown

pytorch-bot Bot commented Mar 17, 2026

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/18224

Note: Links to docs will display an error until the docs builds have been completed.

❗ 1 Active SEVs

There are 1 currently active SEVs. If your PR is affected, please view them below:

⚠️ 11 Awaiting Approval

As of commit f0db59a with merge base 32a6cec (image):

AWAITING APPROVAL - The following workflows need approval before CI can run:

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@meta-cla
Copy link
Copy Markdown

meta-cla Bot commented Mar 17, 2026

Hi @jpiat!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an Espressif (ESP32 / ESP32-S3) ExecuTorch “executor runner” example project plus a new CMake preset to help cross-compile ExecuTorch for ESP targets.

Changes:

  • Introduces a new esp-baremetal CMake preset and preset file for ESP-oriented ExecuTorch builds.
  • Adds a full ESP-IDF example project (runner component + template project + build script + docs).
  • Adds ESP-IDF configuration defaults (sdkconfig defaults + partition table) for ESP32-S3-oriented setups.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
tools/cmake/preset/esp_baremetal.cmake New ESP-oriented ExecuTorch build preset settings.
CMakePresets.json Registers the esp-baremetal configure preset.
examples/espressif/README.md End-to-end instructions for exporting, building, flashing, and troubleshooting on ESP32/ESP32-S3.
examples/espressif/build.sh Helper script to build the ESP-IDF project and optionally generate model_pte.h.
examples/espressif/executor_runner/CMakeLists.txt ESP-IDF component + standalone build definition for the runner.
examples/espressif/executor_runner/esp_executor_runner.cpp Main ESP runner implementation (PAL hooks, loading, execution, optional FS load/ETDump/BundleIO).
examples/espressif/executor_runner/esp_memory_allocator.{h,cpp} ESP-specific allocator wrapper with usage tracking.
examples/espressif/executor_runner/esp_perf_monitor.{h,cpp} Simple perf measurements using cycle counter + esp_timer.
examples/espressif/executor_runner/pte_to_header.py Converts .pte into a C header for compiled-in model embedding.
examples/espressif/project/CMakeLists.txt Template ESP-IDF project that pulls in the runner component.
examples/espressif/project/main/{CMakeLists.txt,main.cpp} Minimal “main” component that calls into the runner.
examples/espressif/project/sdkconfig.defaults Default ESP-IDF configuration for the example (generic).
examples/espressif/project/sdkconfig.defaults.esp32s3 Target-specific ESP32-S3 config defaults.
examples/espressif/project/partitions.csv Custom partition table for the example firmware.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread examples/espressif/executor_runner/esp_executor_runner.cpp Outdated
Comment thread examples/espressif/executor_runner/esp_executor_runner.cpp Outdated
Comment thread examples/espressif/executor_runner/esp_perf_monitor.cpp
Comment thread examples/espressif/executor_runner/esp_perf_monitor.cpp Outdated
Comment thread examples/espressif/executor_runner/esp_executor_runner.cpp
Comment thread examples/espressif/README.md Outdated
Comment thread examples/espressif/README.md Outdated
Comment thread examples/espressif/project/partitions.csv Outdated
Comment thread examples/espressif/project/sdkconfig.defaults Outdated
Comment thread tools/cmake/preset/esp_baremetal.cmake Outdated
@jpiat
Copy link
Copy Markdown
Author

jpiat commented Mar 17, 2026

@pytorchbot label "release notes: examples"

@pytorch-bot pytorch-bot Bot added the release notes: examples Changes to any of our example LLMs integrations, such as Llama3 and Llava label Mar 17, 2026
@meta-cla
Copy link
Copy Markdown

meta-cla Bot commented Mar 17, 2026

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Mar 17, 2026
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 17, 2026 08:24
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Espressif ESP32/ESP32-S3 example integration for running ExecuTorch models under ESP-IDF, along with build tooling and documentation to cross-compile ExecuTorch for Xtensa and build/flash an example project.

Changes:

  • Introduces an ESP-IDF executor_runner component and example project scaffolding (CMake, app_main, sdkconfig defaults, partitions).
  • Adds an ESP-focused CMake preset (esp-baremetal) to configure ExecuTorch builds for the target.
  • Adds a model conversion helper (pte_to_header.py), a build helper script, and a comprehensive README.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
tools/cmake/preset/esp_baremetal.cmake New preset to configure ExecuTorch build options for ESP targets.
CMakePresets.json Registers the esp-baremetal CMake preset.
examples/espressif/README.md End-to-end documentation for exporting, building, flashing, and troubleshooting.
examples/espressif/build.sh Helper script to generate model_pte.h and build via idf.py.
examples/espressif/executor_runner/CMakeLists.txt ESP-IDF component definition + standalone CMake build option; integrates prebuilt ExecuTorch libs.
examples/espressif/executor_runner/esp_executor_runner.cpp Core runner implementation: loading PTE, setting up allocators, executing, logging, optional SPIFFS load.
examples/espressif/executor_runner/esp_memory_allocator.{h,cpp} Custom allocator wrapper with tracking helpers.
examples/espressif/executor_runner/esp_perf_monitor.{h,cpp} Perf measurement helpers using cycle counter and esp_timer.
examples/espressif/executor_runner/pte_to_header.py Converts a .pte into a C header byte array for firmware embedding.
examples/espressif/project/CMakeLists.txt Example ESP-IDF project top-level CMake.
examples/espressif/project/main/CMakeLists.txt Minimal main component that depends on executor_runner.
examples/espressif/project/main/main.cpp Provides app_main() that invokes executor_runner_main().
examples/espressif/project/sdkconfig.defaults Baseline ESP-IDF defaults for the example project.
examples/espressif/project/sdkconfig.defaults.esp32s3 ESP32-S3-specific defaults (PSRAM, etc.).
examples/espressif/project/partitions.csv Custom partition table template for the example project.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread examples/espressif/executor_runner/esp_executor_runner.cpp Outdated
Comment thread examples/espressif/executor_runner/esp_executor_runner.cpp
Comment thread examples/espressif/executor_runner/esp_executor_runner.cpp Outdated
Comment thread examples/espressif/executor_runner/esp_executor_runner.cpp Outdated
Comment thread examples/espressif/executor_runner/esp_executor_runner.cpp Outdated
Comment thread examples/espressif/executor_runner/esp_memory_allocator.cpp Outdated
Comment thread examples/espressif/project/main/main.cpp Outdated
Comment thread examples/espressif/project/sdkconfig.defaults
Comment thread examples/espressif/README.md Outdated
Comment thread tools/cmake/preset/esp_baremetal.cmake
Copilot AI review requested due to automatic review settings March 17, 2026 10:32
@jpiat jpiat requested a review from kimishpatel as a code owner March 17, 2026 10:32
Copilot AI review requested due to automatic review settings March 23, 2026 12:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Espressif ESP32/ESP32-S3 example that demonstrates running an ExecuTorch .pte on ESP-IDF (no ESP32-optimized ops), plus a CMake preset to cross-compile ExecuTorch for the target.

Changes:

  • Introduces an ESP-IDF-based executor runner component + template project (runner API, PAL, perf monitor, memory allocator, build glue).
  • Adds an Espressif example README and helper script for building/flashing and converting .ptemodel_pte.h.
  • Adds a new esp-baremetal CMake preset and a small threadpool type fix.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tools/cmake/preset/esp_baremetal.cmake New preset defaults for building ExecuTorch for ESP cross-compilation.
CMakePresets.json Registers the new esp-baremetal preset.
extension/threadpool/threadpool.cpp Adjusts tsan thread limit type to match result type.
examples/espressif/README.md End-to-end documentation for exporting, building, flashing, and troubleshooting.
examples/espressif/build.sh Helper script to generate model header and build the ESP-IDF project.
examples/espressif/project/CMakeLists.txt ESP-IDF project wrapper that pulls in the runner component.
examples/espressif/project/main/CMakeLists.txt Minimal main component depending on the runner.
examples/espressif/project/main/main.cpp ESP-IDF app_main() entrypoint that invokes the runner.
examples/espressif/project/sdkconfig.defaults Baseline ESP-IDF defaults (ESP32/ESP32-S3).
examples/espressif/project/sdkconfig.defaults.esp32s3 ESP32-S3-specific sdkconfig defaults (Octal PSRAM, etc.).
examples/espressif/project/partitions.csv Example partition table for the template project.
examples/espressif/executor_runner/CMakeLists.txt ESP-IDF component definition + integration with prebuilt ExecuTorch libs + optional .pte header generation.
examples/espressif/executor_runner/esp_executor_runner.h Public C API for initializing, setting inputs, executing, and reading outputs.
examples/espressif/executor_runner/esp_executor_runner.cpp Core runner implementation: loading PTE, allocators, inputs/outputs, optional BundleIO/ETDump, optional filesystem load.
examples/espressif/executor_runner/esp_pal.cpp ESP PAL overrides (ticks, log emission, init/abort).
examples/espressif/executor_runner/esp_memory_allocator.h Wrapper allocator tracking used/free bytes for instrumentation.
examples/espressif/executor_runner/esp_memory_allocator.cpp Implementation of the tracking allocator.
examples/espressif/executor_runner/esp_perf_monitor.h Perf monitor API for ESP.
examples/espressif/executor_runner/esp_perf_monitor.cpp Cycle/time based measurement and reporting for ESP.
examples/espressif/executor_runner/pte_to_header.py Utility to embed .pte into firmware as a C byte array header.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +650 to +656
if (!ctx.method->ok()) {
ET_LOG(
Info,
"Loading of method %s failed with status 0x%" PRIx32,
ctx.method_name,
static_cast<unsigned long>(ctx.method->error()));
}
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

runner_init() logs when program.load_method() fails but then continues and dereferences *ctx.method.value() (e.g., in input preparation). If the Result is not ok, this can trigger an assert/abort or undefined behavior. Return early (or ET_CHECK_MSG(ctx.method->ok(), ...)) before using the Method when load fails.

Suggested change
if (!ctx.method->ok()) {
ET_LOG(
Info,
"Loading of method %s failed with status 0x%" PRIx32,
ctx.method_name,
static_cast<unsigned long>(ctx.method->error()));
}
ET_CHECK_MSG(
ctx.method->ok(),
"Loading of method %s failed with status 0x%" PRIx32,
ctx.method_name,
static_cast<unsigned long>(ctx.method->error()));

Copilot uses AI. Check for mistakes.
ET_LOG(Fatal, "Failed to load model from filesystem.");
return false;
}
model_pte = buffer;
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When FILESYSTEM_LOAD is enabled, the model bytes are allocated from method_allocation_pool via file_allocator, but the same method_allocation_pool is then reused for ctx.method_allocator allocations in runner_init(). This can overwrite the PTE buffer that BufferDataLoader/Program still references and corrupt execution. Load the PTE into separate storage (heap/PSRAM), or reserve an initial region in the pool and start the method allocator after it, or switch to a file-backed DataLoader.

Suggested change
model_pte = buffer;
// Copy the loaded PTE into separate heap/PSRAM storage to avoid it being
// overwritten when method_allocation_pool is reused by runner_init().
void* heap_pte = std::malloc(buffer_size);
if (heap_pte == nullptr) {
ET_LOG(Fatal, "Failed to allocate heap memory for model PTE.");
return false;
}
std::memcpy(heap_pte, buffer, buffer_size);
model_pte = static_cast<uint8_t*>(heap_pte);

Copilot uses AI. Check for mistakes.
static_cast<unsigned long>(buffer_bytes),
static_cast<unsigned long>(tensor_bytes));
return false;
}
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

et_runner_get_output() validates buffer_bytes but never checks that buffer is non-null before calling memcpy(). If callers pass buffer=nullptr with a non-zero size, this will crash. Add an explicit null check (e.g., require non-null when tensor_bytes > 0).

Suggested change
}
}
if (tensor_bytes > 0 && buffer == nullptr) {
ET_LOG(
Error,
"Output %lu: null buffer passed for non-empty tensor (size=%lu bytes).",
static_cast<unsigned long>(output_idx),
static_cast<unsigned long>(tensor_bytes));
return false;
}

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +16
| Chip | CPU | Internal SRAM | PSRAM (optional) |
|----------|---------------|---------------|------------------|
| ESP32 | Xtensa LX6 (dual-core, 240MHz) | ~520KB | 4-8MB |
| ESP32-S3 | Xtensa LX7 (dual-core, 240MHz) | ~512KB | 2-32MB (Octal) |

Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The markdown table under “Supported Targets” has an extra leading | on each row (|| ...), which renders as an empty first column in GitHub markdown. Use standard table syntax with a single leading pipe per row.

Copilot uses AI. Check for mistakes.
# Name, Type, SubType, Offset, Size, Flags
nvs,data,nvs,0x9000,24K,
phy_init,data,phy,0xf000,4K,
factory,app,factory,0x10000,2M,
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example code enables SPIFFS-based model loading (partition label storage), and the README suggests adding a SPIFFS partition, but the provided partitions.csv doesn’t include a storage,data,spiffs,... entry. Consider adding a commented-out SPIFFS row (or include it by default) so users enabling FILESYSTEM_LOAD don’t hit SPIFFS partition not found.

Suggested change
factory,app,factory,0x10000,2M,
factory,app,factory,0x10000,2M,
# Optional SPIFFS partition for FILESYSTEM_LOAD (label must be "storage")
# storage,data,spiffs,,1M,

Copilot uses AI. Check for mistakes.
Comment thread tools/cmake/preset/esp_baremetal.cmake Outdated
set_overridable_option(EXECUTORCH_BUILD_KERNELS_QUANTIZED ON)
set_overridable_option(EXECUTORCH_BUILD_EXTENSION_RUNNER_UTIL ON)
set_overridable_option(EXECUTORCH_ENABLE_LOGGING ON)
set_overridable_option(EXECUTORCH_BUILD_ARM_ETDUMP OFF)
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This preset uses set_overridable_option(EXECUTORCH_BUILD_ARM_ETDUMP OFF), which stores the value as a CACHE STRING with no description. In tools/cmake/preset/arm_baremetal.cmake, the same knob is defined via define_overridable_option(... BOOL ...), which gives it the right type and makes it discoverable. Consider switching to define_overridable_option here as well (or use a non-Arm-specific option name).

Suggested change
set_overridable_option(EXECUTORCH_BUILD_ARM_ETDUMP OFF)
define_overridable_option(
EXECUTORCH_BUILD_ARM_ETDUMP
OFF
BOOL
"Enable ETDump devtools support for bare-metal targets"
)

Copilot uses AI. Check for mistakes.
@nil-is-all
Copy link
Copy Markdown
Contributor

@jpiat could you resolve the lintrunner errors reported?

Copilot AI review requested due to automatic review settings April 2, 2026 08:44
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1013 to +1016
EspMemoryAllocator file_allocator(
method_allocation_pool_size, method_allocation_pool);
auto [buffer, buffer_size] =
load_file_from_fs("/spiffs/model.pte", file_allocator);
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With FILESYSTEM_LOAD enabled, file_allocator loads /spiffs/model.pte into method_allocation_pool, and model_pte points into that buffer. runner_init() then constructs ctx.method_allocator over the same method_allocation_pool starting at offset 0, so subsequent allocations can overwrite the model bytes and corrupt Program::load()/method execution. Fix by ensuring the model storage is not reused by the method allocator (e.g., partition the pool and start the method allocator after the aligned model size, or allocate the model in a separate heap/PSRAM buffer, or switch to a file-backed DataLoader).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This remains a problem, as the method allocator could wind up overwriting the PTE file when it creates a new MemoryAllocator for the method_allocation_pool. I think there are two options:

  1. Split the pool in two pools: one for the PTE file, one for the method allocator
  2. Share the same MemoryAllocator object for both uses, so that when method allocation starts, it uses memory after the PTE file, instead of overwriting.

Comment thread tools/cmake/preset/esp_baremetal.cmake Outdated
Comment thread examples/espressif/README.md Outdated
Comment thread examples/espressif/executor_runner/pte_to_header.py Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 2, 2026 11:44
jpiat and others added 2 commits April 2, 2026 13:44
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Info,
"Loading of method %s failed with status 0x%" PRIx32,
ctx.method_name,
static_cast<unsigned long>(ctx.method->error()));
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This log uses a 0x%" PRIx32 format specifier but passes static_cast<unsigned long>(ctx.method->error()). Because ET_LOG is variadic, this type mismatch is undefined behavior on some ABIs and can print garbage. Cast the argument to uint32_t (or change the format to match the argument type).

Suggested change
static_cast<unsigned long>(ctx.method->error()));
static_cast<uint32_t>(ctx.method->error()));

Copilot uses AI. Check for mistakes.
status == Error::Ok,
"Execution of method %s failed with status 0x%" PRIx32,
ctx.method_name,
static_cast<unsigned long>(status));
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ET_CHECK_MSG uses a 0x%" PRIx32 format specifier but passes static_cast<unsigned long>(status). This is a variadic type mismatch and can lead to incorrect output/UB. Cast to uint32_t (or update the format specifier) consistently with other PRIx32 usages in this file.

Suggested change
static_cast<unsigned long>(status));
static_cast<uint32_t>(status));

Copilot uses AI. Check for mistakes.
Comment thread examples/espressif/executor_runner/esp_pal.cpp Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 2, 2026 15:42
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1013 to +1026
EspMemoryAllocator file_allocator(
method_allocation_pool_size, method_allocation_pool);
auto [buffer, buffer_size] =
load_file_from_fs("/spiffs/model.pte", file_allocator);
if (buffer == nullptr) {
ET_LOG(Fatal, "Failed to load model from filesystem.");
return false;
}
model_pte = buffer;
model_pte_size = buffer_size;
pte_size = buffer_size;
#else
pte_size = sizeof(model_pte);
#endif
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When FILESYSTEM_LOAD is enabled, the model is loaded into method_allocation_pool via file_allocator, but then runner_init() constructs ctx.method_allocator over the same method_allocation_pool starting at offset 0. Subsequent allocations will overwrite model_pte and can corrupt Program::load() / method metadata that references the buffer. Reserve the model region in the pool (e.g., construct EspMemoryAllocator for runtime allocations with base_address = method_allocation_pool + aligned_model_size and size = pool_size - aligned_model_size), or load into separate storage (heap/PSRAM) that won’t be reused by the method allocator.

Copilot uses AI. Check for mistakes.
Comment on lines +87 to +91
void* et_pal_allocate(ET_UNUSED size_t size) {
return nullptr;
}

void et_pal_free(ET_UNUSED void* ptr) {}
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

et_pal_allocate()/et_pal_free() are overridden to always return nullptr / no-op. This disables ExecuTorch’s PAL-backed allocations even though this example uses heap-backed features elsewhere (e.g., std::vector, filesystem I/O). Implement these using malloc/free (or heap_caps_malloc/heap_caps_free with appropriate caps) so runtime components that rely on PAL allocation (e.g., PlatformMemoryAllocator or temp allocations when no temp allocator is provided) work correctly.

Suggested change
void* et_pal_allocate(ET_UNUSED size_t size) {
return nullptr;
}
void et_pal_free(ET_UNUSED void* ptr) {}
void* et_pal_allocate(size_t size) {
#if defined(ESP_PLATFORM)
// Allocate from the default-capability heap on ESP platforms.
return heap_caps_malloc(size, MALLOC_CAP_DEFAULT);
#else
// Fallback to standard malloc on non-ESP platforms.
return malloc(size);
#endif
}
void et_pal_free(void* ptr) {
#if defined(ESP_PLATFORM)
heap_caps_free(ptr);
#else
free(ptr);
#endif
}

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +16
| Chip | CPU | Internal SRAM | PSRAM (optional) |
|----------|---------------|---------------|------------------|
| ESP32 | Xtensa LX6 (dual-core, 240MHz) | ~520KB | 4-8MB |
| ESP32-S3 | Xtensa LX7 (dual-core, 240MHz) | ~512KB | 2-32MB (Octal) |

Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Markdown tables use a double leading pipe (|| ... |), which creates an empty first column in GitHub’s renderer. Use a single leading pipe for each row (e.g., | Chip | CPU | ... |) and update the separator row accordingly so the table renders correctly.

Copilot uses AI. Check for mistakes.
extern void executor_runner_main(void);

extern "C" void app_main(void) {
printf("Starting executorch runner !\n");
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Log message has inconsistent capitalization/spacing ("executorch" and a space before !). Consider changing to a consistent product name and punctuation (e.g., "Starting ExecuTorch runner!\n") to match the rest of the example output in the README.

Suggested change
printf("Starting executorch runner !\n");
printf("Starting ExecuTorch runner!\n");

Copilot uses AI. Check for mistakes.
Comment on lines +27 to +39
idf_component_register(
SRCS
"esp_executor_runner.cpp"
"esp_pal.cpp"
"esp_memory_allocator.cpp"
"esp_perf_monitor.cpp"
INCLUDE_DIRS
"."
REQUIRES
esp_timer
esp_system
spiffs
)
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idf_component_register() lists spiffs in REQUIRES unconditionally, but the code only includes/uses SPIFFS when FILESYSTEM_LOAD is enabled. Consider making the spiffs dependency conditional on FILESYSTEM_LOAD so the default (compiled-in model) build doesn’t pull in an unnecessary component or require SPIFFS-related sdkconfig options.

Copilot uses AI. Check for mistakes.
@jpiat
Copy link
Copy Markdown
Author

jpiat commented Apr 3, 2026

@jpiat could you resolve the lintrunner errors reported?

should be fixed now

Copilot AI review requested due to automatic review settings April 14, 2026 13:26
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1013 to +1023
EspMemoryAllocator file_allocator(
method_allocation_pool_size, method_allocation_pool);
auto [buffer, buffer_size] =
load_file_from_fs("/spiffs/model.pte", file_allocator);
if (buffer == nullptr) {
ET_LOG(Fatal, "Failed to load model from filesystem.");
return false;
}
model_pte = buffer;
model_pte_size = buffer_size;
pte_size = buffer_size;
Comment on lines +823 to +848
for (int i = 0; i < outputs.size(); ++i) {
if (outputs[i].isTensor()) {
Tensor tensor = outputs[i].toTensor();
#if defined(ET_LOG_DUMP_OUTPUT)
for (int j = 0; j < tensor.numel(); ++j) {
if (tensor.scalar_type() == ScalarType::Int) {
printf(
"Output[%d][%d]: (int) %d\n",
i,
j,
tensor.const_data_ptr<int>()[j]);
} else if (tensor.scalar_type() == ScalarType::Float) {
printf(
"Output[%d][%d]: (float) %f\n",
i,
j,
tensor.const_data_ptr<float>()[j]);
} else if (tensor.scalar_type() == ScalarType::Char) {
printf(
"Output[%d][%d]: (char) %d\n",
i,
j,
tensor.const_data_ptr<int8_t>()[j]);
} else if (tensor.scalar_type() == ScalarType::Bool) {
printf(
"Output[%d][%d]: (bool) %s (0x%x)\n",
Comment on lines +691 to +695
for (int i = 0; i < inputs.size(); ++i) {
if (inputs[i].isTensor()) {
Tensor tensor = inputs[i].toTensor();
for (int j = 0; j < tensor.numel(); ++j) {
if (tensor.scalar_type() == ScalarType::Int) {
Comment on lines +633 to +636
ET_LOG(
Error,
"ETDump: Could not set_debug_buffer() error:0x%" PRIx32,
result.error());
ET_CHECK_MSG(
status == Error::Ok,
"load_bundled_input failed with status 0x%" PRIx32,
status);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. module: microcontrollers For embedded MCUs like Cortex-M, or RTOS like Zephyr, does not track NPU backend like Arm Ethos. release notes: examples Changes to any of our example LLMs integrations, such as Llama3 and Llava

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants