Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions .ci/scripts/test_espressif_idf_component.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/usr/bin/env bash
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

# Generates the ExecuTorch ESP-IDF component with every shipped profile,
# builds the idf_component_smoke consumer for ESP32-S3 against each, and runs
# the smoke profile build on the emulator.

set -euo pipefail

et_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
build_dir="${ESPRESSIF_BUILD_DIR:-${et_root}/cmake-out-esp-idf-component}"
export ESPRESSIF_TOOLS_DIR="${ESPRESSIF_TOOLS_DIR:-${RUNNER_TEMP:-/tmp}/executorch-espressif}"
mkdir -p "${build_dir}"
build_dir=$(cd "${build_dir}" && pwd)
cd "${et_root}"

collect_artifacts() {
if [[ -n "${RUNNER_ARTIFACT_DIR:-}" ]]; then
mkdir -p "${RUNNER_ARTIFACT_DIR}/esp-idf-component"
for file in "${build_dir}"/*.log "${build_dir}/components/executorch/VERSION"; do
if [[ -f "${file}" ]]; then
cp "${file}" "${RUNNER_ARTIFACT_DIR}/esp-idf-component/"
fi
done
fi
}
trap collect_artifacts EXIT

bash examples/espressif/setup.sh --minimal 2>&1 | tee "${build_dir}/setup.log"
# shellcheck source=/dev/null
source "${ESPRESSIF_TOOLS_DIR}/setup_path.sh"

python examples/espressif/export_smoke_model.py \
--output "${build_dir}/smoke.bpte" --pte-output "${build_dir}/smoke.pte" \
2>&1 | tee "${build_dir}/export.log"

component_dir="${build_dir}/components/executorch"
profiles=$(find examples/espressif/idf_profiles -name '*.ops' -exec basename {} .ops \; \
| sort | paste -sd, -)
bash examples/espressif/build_idf_component.sh --profiles "${profiles}" \
--out "${component_dir}" 2>&1 | tee "${build_dir}/generate.log"

project=examples/espressif/idf_component_smoke
for profile in ${profiles//,/ }; do
profile_upper=$(echo "${profile}" | tr '[:lower:]-' '[:upper:]_')
firmware_dir="${build_dir}/firmware-${profile}"
printf 'CONFIG_ET_OP_PROFILE_%s=y\n' "${profile_upper}" \
> "${build_dir}/${profile}.defaults"
idf.py -C "${project}" -B "${firmware_dir}" \
-DIDF_TARGET=esp32s3 \
-DSDKCONFIG="${build_dir}/sdkconfig-${profile}" \
"-DSDKCONFIG_DEFAULTS=sdkconfig.defaults;${build_dir}/${profile}.defaults" \
-DET_COMPONENT_DIR="${component_dir}" \
-DET_SMOKE_PTE="${build_dir}/smoke.pte" build \
2>&1 | tee "${build_dir}/firmware-${profile}.log"
done

firmware_dir="${build_dir}/firmware-smoke"
idf.py -C "${project}" -B "${firmware_dir}" merge-bin \
2>&1 | tee "${build_dir}/firmware-merge.log"
timeout 130s esp-emu --chip esp32s3 \
--firmware "${firmware_dir}/merged-binary.bin" \
--elf "${firmware_dir}/et_component_smoke.elf" \
--net user --timeout 120s --exit-on 'Program complete.' \
2>&1 | tee "${build_dir}/emulator.log"
for marker in "ET_COMPONENT_SMOKE: PASS" "Program complete."; do
if ! grep -qF "${marker}" "${build_dir}/emulator.log"; then
echo "FAIL: missing '${marker}'; see ${build_dir}/emulator.log" >&2
exit 1
fi
done
echo "PASS: generated ESP-IDF component ran the smoke model on the ESP32-S3 emulator."
23 changes: 23 additions & 0 deletions .github/workflows/test-espressif.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ on:
- tools/cmake/preset/esp_baremetal.cmake
- CMakePresets.json
- .ci/scripts/test_espressif.sh
- .ci/scripts/test_espressif_idf_component.sh
- .github/workflows/test-espressif.yml
schedule:
- cron: '0 4 * * 1'
Expand Down Expand Up @@ -51,3 +52,25 @@ jobs:
source .ci/scripts/utils.sh
install_executorch --use-pt-pinned-commit --minimal
ESPRESSIF_NN_KERNELS="${{ matrix.kernels }}" bash .ci/scripts/test_espressif.sh

test-idf-component:
name: ESP-IDF component (ESP32-S3)
needs: docker-image
uses: pytorch/test-infra/.github/workflows/linux_job_v3.yml@main
permissions:
id-token: write
contents: read
with:
runner: mt-l-x86iavx512-8-64
docker-image: ${{ needs.docker-image.outputs.docker-registry }}/ci-image:executorch-ubuntu-22.04-clang12-${{ needs.docker-image.outputs.ci-docker-hash }}
submodules: recursive
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
timeout: 45
upload-artifact: test-report-esp-idf-component
script: |
set -euo pipefail
CONDA_ENV=$(conda env list --json | jq -r '.envs | .[-1]')
conda activate "${CONDA_ENV}"
source .ci/scripts/utils.sh
install_executorch --use-pt-pinned-commit --minimal
bash .ci/scripts/test_espressif_idf_component.sh
34 changes: 34 additions & 0 deletions examples/espressif/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,40 @@ ESP32-S3 microcontrollers. It is based on the
[Arm Cortex-M executor runner](../arm/executor_runner/) and adapted for the
ESP-IDF build system and ESP32 memory architecture.

## ESP-IDF component (generated, source-vendored)

For integrating ExecuTorch into an existing ESP-IDF project without the
cross-compile-then-link flow below, generate a self-contained ESP-IDF
component from sources in this repository:

```bash
./examples/espressif/build_idf_component.sh --profiles wakeword_int8 \
--out /path/to/your_project/components/executorch
```

The output is a registry-shaped component (`idf_component.yml`,
`CMakeLists.txt`, `Kconfig`, `VERSION`) containing the runtime,
per-profile kernel registration (selected via
`CONFIG_ET_OP_PROFILE_*`; the component is off until
`CONFIG_ET_ENABLE=y`), the shared ESP-IDF PAL from
`platform/esp_pal.cpp` (ESP_LOG + `esp_timer` timing), and a C
inference API (`et_model.h`, flash-XIP model bytes
with internal/PSRAM arena placement). Application pipelines built on
the runtime (for example wake word front ends and detectors) stay
with the application. Op profiles are defined in
`idf_profiles/<name>.ops`; `wakeword_int8` is an int8 wake-word
example profile for a Cadence-backend export — profiles may list
`cadence::` ops, which the generator binds to the Cadence backend's
generic (portable) kernels under `backends/cadence/generic`, next to
the `aten::` ops the same profile needs from the portable kernels.
Consumers need only ESP-IDF — no host CMake build, no flatc.
`idf_component_smoke/` is a minimal consumer that CI generates, builds
and runs on the ESP32-S3 emulator
(`.ci/scripts/test_espressif_idf_component.sh`).

The executor runner below remains the reference for the prebuilt-library
flow and for benchmarking.

## Supported Targets

| Chip | CPU | Internal SRAM | PSRAM (optional) |
Expand Down
Loading
Loading