From 6830cf052c6503cb80c11ffb64e551f26a1989a0 Mon Sep 17 00:00:00 2001 From: Zingo Andersen Date: Fri, 5 Jun 2026 08:39:24 +0200 Subject: [PATCH 1/9] Zephyr: Update to Zephyr 4.4 Update CI install and testing, samples and docs Zephyr 4.4 also added support for ensemble_e8_dk so it can be used out of the box instead of the alif zephyr git fork. Signed-off-by: Zingo Andersen Change-Id: Iddebc0516933be3136aefbf28e6fa74e033a76f8 --- .ci/docker/common/install_zephyr.sh | 7 - .ci/scripts/test_zephyr.sh | 175 ++++++++---- .ci/scripts/zephyr_sdk_release_proxy.py | 264 ++++++++++++++++++ .claude/skills/zephyr/SKILL.md | 10 +- .github/workflows/trunk.yml | 7 +- .gitignore | 3 + backends/arm/scripts/toolchain_utils.sh | 8 +- backends/arm/test/test_github_trunk_zephyr.sh | 27 +- docs/source/zephyr_alif_tutorial.md | 229 +++++++++++---- zephyr/README.md | 24 +- zephyr/samples/hello-executorch/README.md | 3 +- zephyr/samples/mv2-ethosu/README.md | 24 +- .../alif_e8_dk_ae822fa0e5597xx0_rtss_hp.conf | 10 - ...semble_e8_dk_ae822fa0e5597ls0_rtss_he.conf | 18 ++ ...ble_e8_dk_ae822fa0e5597ls0_rtss_he.overlay | 38 +++ ...semble_e8_dk_ae822fa0e5597ls0_rtss_hp.conf | 18 ++ ...ble_e8_dk_ae822fa0e5597ls0_rtss_hp.overlay | 38 +++ 17 files changed, 756 insertions(+), 147 deletions(-) create mode 100755 .ci/scripts/zephyr_sdk_release_proxy.py delete mode 100644 zephyr/samples/mv2-ethosu/boards/alif_e8_dk_ae822fa0e5597xx0_rtss_hp.conf create mode 100644 zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_he.conf create mode 100644 zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_he.overlay create mode 100644 zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_hp.conf create mode 100644 zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_hp.overlay diff --git a/.ci/docker/common/install_zephyr.sh b/.ci/docker/common/install_zephyr.sh index 7275c7b91f6..8ac1753c671 100644 --- a/.ci/docker/common/install_zephyr.sh +++ b/.ci/docker/common/install_zephyr.sh @@ -83,13 +83,6 @@ install_prerequiresites() { rm -f kitware-archive.sh pip_install --no-cache-dir west pip_install pyelftools - - # Zephyr SDK - wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.4/zephyr-sdk-0.17.4_linux-x86_64.tar.xz - tar -xf zephyr-sdk-0.17.4_linux-x86_64.tar.xz - rm -f zephyr-sdk-0.17.4_linux-x86_64.tar.xz* - # Save setup to later and this get symlinked in to another folder in the test in trunk.yml - #./zephyr-sdk-0.17.4/setup.sh -c -t arm-zephyr-eabi } install_prerequiresites diff --git a/.ci/scripts/test_zephyr.sh b/.ci/scripts/test_zephyr.sh index 6ce8e082b84..7e33a02f310 100755 --- a/.ci/scripts/test_zephyr.sh +++ b/.ci/scripts/test_zephyr.sh @@ -14,6 +14,9 @@ ZEPHYR_README_PATH="zephyr/README.md" ZEPHYR_SAMPLES_README_PATH="zephyr/samples/hello-executorch/README.md" TARGETS_ARG="${TARGET_LIST:-}" +SKIP_ZEPHYR_SETUP=0 +SETUP_ONLY=0 +ZEPHYR_DEV_ROOT="${ZEPHYR_DEV_ROOT:-zephyr_dev_root}" usage() { cat < README containing test_* command blocks --targets Comma-separated target list, e.g. ethos-u55,cortex-m55,ethos-u85 + --zephyr-dev-root Zephyr workspace directory (default: ${ZEPHYR_DEV_ROOT}) + --skip-zephyr-setup Reuse an existing Zephyr workspace + --setup-only Set up Zephyr workspace and exit without running sample tests -h, --help Show this help EOF } while [[ $# -gt 0 ]]; do case "$1" in + --zephyr-samples-readme-path) + ZEPHYR_SAMPLES_README_PATH="$2" + shift 2 + ;; + --zephyr-dev-root) + ZEPHYR_DEV_ROOT="$2" + shift 2 + ;; --targets) TARGETS_ARG="$2" shift 2 ;; - --zephyr-samples-readme-path) - ZEPHYR_SAMPLES_README_PATH="$2" - shift 2 + --skip-zephyr-setup) + SKIP_ZEPHYR_SETUP=1 + shift + ;; + --setup-only) + SETUP_ONLY=1 + shift ;; -h|--help) usage @@ -48,7 +66,13 @@ while [[ $# -gt 0 ]]; do esac done -if [[ -z "${TARGETS_ARG}" ]]; then +if [[ ${SKIP_ZEPHYR_SETUP} -eq 1 && ${SETUP_ONLY} -eq 1 ]]; then + echo "ERROR: --skip-zephyr-setup and --setup-only cannot be used together" >&2 + usage >&2 + exit 1 +fi + +if [[ ${SETUP_ONLY} -eq 0 && -z "${TARGETS_ARG}" ]]; then echo "ERROR: --targets or TARGET_LIST must be set" >&2 usage >&2 exit 1 @@ -94,66 +118,117 @@ run_target_test_blocks_from_readme() { done <<< "${markers}" } -# Check that zephyr/README.md and zephyr/executorch.yaml are in sync. -verify_zephyr_readme +run_west_sdk_install_with_proxy_fallback() { + local sdk_version proxy_port proxy_url proxy_cache_dir proxy_pid -# Based on instructions in zephyr/README.md and the selected sample README. -run_command_block_from_readme "${ZEPHYR_README_PATH}" "" + # Try expected setup first. + if run_command_block_from_readme "${ZEPHYR_README_PATH}" ""; then + return 0 + fi -# Make sure to backup the zephyr_scratch folder if it exists to allow for local -# testing that does not lose code/data. -if [[ -d "zephyr_scratch" ]]; then - mv "zephyr_scratch" "zephyr_scratch.backup.$(date +%Y%m%d%H%M%S)" -fi -mkdir -p zephyr_scratch/ + echo "west sdk install failed; retrying through local release proxy" -cd zephyr_scratch -export ZEPHYR_PROJ_ROOT="$(realpath "$(pwd)")" + sdk_version="1.0.1" + if [[ -f "zephyr/SDK_VERSION" ]]; then + sdk_version="$(/dev/null 2>&1 || true' RETURN + + for _ in {1..30}; do + if wget -qO- "${proxy_url}?page=1" >/dev/null 2>&1; then + break + fi + sleep 1 + done + + west sdk install \ + --version "${sdk_version}" \ + --api-url "${proxy_url}" \ + --gnu-toolchains arm-zephyr-eabi + + kill "${proxy_pid}" >/dev/null 2>&1 || true + trap - RETURN +} -# Download and setup Zephyr SDK 0.17.4 if not already present -if [ ! -d "zephyr-sdk-0.17.4" ]; then - echo "---- Downloading Zephyr SDK ----" - wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.4/zephyr-sdk-0.17.4_linux-x86_64.tar.xz - tar -xf zephyr-sdk-0.17.4_linux-x86_64.tar.xz - rm -f zephyr-sdk-0.17.4_linux-x86_64.tar.xz* -fi +setup_zephyr_workspace() { + # Check that zephyr/README.md and zephyr/executorch.yaml are in sync. + verify_zephyr_readme -./zephyr-sdk-0.17.4/setup.sh -c -t arm-zephyr-eabi -export ZEPHYR_SDK_INSTALL_DIR=$(realpath ./zephyr-sdk-0.17.4) + # Based on instructions in zephyr/README.md and the selected sample README. + run_command_block_from_readme "${ZEPHYR_README_PATH}" "" -cd ${ZEPHYR_PROJ_ROOT} + # Make sure to backup the Zephyr workspace folder if it exists to allow for local + # testing that does not lose code/data. + if [[ -d "${ZEPHYR_DEV_ROOT}" ]]; then + mv "${ZEPHYR_DEV_ROOT}" "${ZEPHYR_DEV_ROOT}.backup.$(date +%Y%m%d%H%M%S)" + fi + mkdir -p "${ZEPHYR_DEV_ROOT}" -run_command_block_from_readme "${ZEPHYR_README_PATH}" "" + cd "${ZEPHYR_DEV_ROOT}" + export ZEPHYR_PROJ_ROOT="$(realpath "$(pwd)")" -cp "${EXECUTORCH_PROJ_ROOT}/zephyr/executorch.yaml" zephyr/submanifests/ + cd "${ZEPHYR_PROJ_ROOT}" -run_command_block_from_readme "${ZEPHYR_README_PATH}" "" + run_command_block_from_readme "${ZEPHYR_README_PATH}" "" -# Switch to executorch in this PR e.g. replace modules/lib/executorch with the -# root folder of this repo instead of doing a re-checkout and figuring out the -# correct commit hash. -rm -Rf modules/lib/executorch -ln -s "${EXECUTORCH_PROJ_ROOT}" modules/lib/executorch + cp "${EXECUTORCH_PROJ_ROOT}/zephyr/executorch.yaml" zephyr/submanifests/ -# Setup git local user for Executorch git to allow -# modules/lib/executorch/examples/arm/setup.sh to run inside CI later. -if ! git config --get user.name >/dev/null 2>&1; then - git config --global user.name "Github Executorch" -fi -if ! git config --get user.email >/dev/null 2>&1; then - git config --global user.email "github_executorch@arm.com" + run_command_block_from_readme "${ZEPHYR_README_PATH}" "" + + # Switch to executorch in this PR e.g. replace modules/lib/executorch with the + # root folder of this repo instead of doing a re-checkout and figuring out the + # correct commit hash. + rm -Rf modules/lib/executorch + ln -s "${EXECUTORCH_PROJ_ROOT}" modules/lib/executorch + + run_command_block_from_readme "${ZEPHYR_README_PATH}" "" + + # Sometimes west sdk install can fail due to network issues or problems with + # rate limiting on the Zephyr SDK download server. If it fails, retry through + # a temporary local proxy that serves the release files from a local cache. + run_west_sdk_install_with_proxy_fallback + + # Setup git local user for Executorch git to allow + # modules/lib/executorch/examples/arm/setup.sh to run inside CI later. + if ! git config --get user.name >/dev/null 2>&1; then + git config --global user.name "Github Executorch" + fi + if ! git config --get user.email >/dev/null 2>&1; then + git config --global user.email "github_executorch@arm.com" + fi + + run_command_block_from_readme "${ZEPHYR_README_PATH}" "" + run_command_block_from_readme "${ZEPHYR_README_PATH}" "" +} + +use_existing_zephyr_workspace() { + if [[ ! -d "${ZEPHYR_DEV_ROOT}" ]]; then + echo "ERROR: --skip-zephyr-setup requires an existing ${ZEPHYR_DEV_ROOT} directory" >&2 + exit 1 + fi + cd "${ZEPHYR_DEV_ROOT}" + export ZEPHYR_PROJ_ROOT="$(realpath "$(pwd)")" +} + +if [[ ${SKIP_ZEPHYR_SETUP} -eq 1 ]]; then + use_existing_zephyr_workspace +else + setup_zephyr_workspace fi -run_command_block_from_readme "${ZEPHYR_README_PATH}" "" -run_command_block_from_readme "${ZEPHYR_README_PATH}" "" +if [[ ${SETUP_ONLY} -eq 1 ]]; then + exit 0 +fi for TARGET in "${TARGETS[@]}"; do TARGET="$(echo "${TARGET}" | xargs)" diff --git a/.ci/scripts/zephyr_sdk_release_proxy.py b/.ci/scripts/zephyr_sdk_release_proxy.py new file mode 100755 index 00000000000..bcd61ad1f7c --- /dev/null +++ b/.ci/scripts/zephyr_sdk_release_proxy.py @@ -0,0 +1,264 @@ +#!/usr/bin/env python3 +# Copyright 2026 Arm Limited and/or its affiliates. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + +"""Local Zephyr SDK release proxy for `west sdk install`. + +This avoids GitHub releases API rate limits by serving a tiny synthetic releases +API locally. Asset requests are served from a cache directory and populated with +`wget` on cache miss. + +Examples: + + # Prepopulate CI cache only. + .ci/scripts/zephyr_sdk_release_proxy.py \ + --version 1.0.1 \ + --cache-dir .cache/zephyr-sdk/v1.0.1 \ + --download-only + + # Serve cached assets and release metadata. + .ci/scripts/zephyr_sdk_release_proxy.py \ + --version 1.0.1 \ + --cache-dir .cache/zephyr-sdk/v1.0.1 \ + --port 8765 + + west sdk install \ + --version 1.0.1 \ + --api-url http://127.0.0.1:8765/releases \ + --gnu-toolchains arm-zephyr-eabi +""" + +from __future__ import annotations + +import argparse +import hashlib +import http.server +import json +import os +import platform +import re +import subprocess +import sys +import urllib.parse +from pathlib import Path + + +class AssetVerificationError(Exception): + pass + + +def host_tuple() -> tuple[str, str]: + system = platform.system() + machine = platform.machine() + + if system != "Linux": + raise SystemExit(f"Unsupported host OS: {system}") + + if machine in ("x86_64", "AMD64"): + return "linux", "x86_64" + if machine in ("aarch64", "arm64"): + return "linux", "aarch64" + + raise SystemExit(f"Unsupported host architecture: {machine}") + + +def release_base_url(version: str) -> str: + return f"https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v{version}" + + +def asset_names(version: str, toolchain: str) -> list[str]: + host_os, host_arch = host_tuple() + return [ + "sha256.sum", + f"zephyr-sdk-{version}_{host_os}-{host_arch}_minimal.tar.xz", + f"hosttools_{host_os}-{host_arch}.tar.xz", + f"toolchain_gnu_{host_os}-{host_arch}_{toolchain}.tar.xz", + ] + + +def run_wget(url: str, output: Path) -> None: + output.parent.mkdir(parents=True, exist_ok=True) + partial = output.with_suffix(output.suffix + ".tmp") + cmd = [ + "wget", + "--continue", + "--progress=bar:force:noscroll", + "--output-document", + str(partial), + url, + ] + subprocess.run(cmd, check=True) + partial.replace(output) + + +def ensure_asset(cache_dir: Path, version: str, filename: str) -> Path: + path = cache_dir / filename + if path.exists(): + return path + + url = f"{release_base_url(version)}/{filename}" + print(f"Downloading {url}", flush=True) + run_wget(url, path) + return path + + +def parse_sha256_sum(path: Path) -> dict[str, str]: + checksums: dict[str, str] = {} + for line in path.read_text().splitlines(): + match = re.match(r"^([0-9a-fA-F]{64})\s+(.+)$", line.strip()) + if match: + checksums[match.group(2)] = match.group(1).lower() + return checksums + + +def verify_asset(cache_dir: Path, checksums: dict[str, str], filename: str) -> None: + if filename == "sha256.sum": + return + + expected = checksums.get(filename) + if expected is None: + raise AssetVerificationError(f"No checksum entry for {filename}") + + hasher = hashlib.sha256() + with (cache_dir / filename).open("rb") as f: + for chunk in iter(lambda: f.read(1024 * 1024), b""): + hasher.update(chunk) + digest = hasher.hexdigest() + + if digest != expected: + raise AssetVerificationError( + f"Checksum mismatch for {filename}: expected {expected}, got {digest}" + ) + + +def populate_cache(cache_dir: Path, version: str, toolchain: str) -> None: + cache_dir.mkdir(parents=True, exist_ok=True) + names = asset_names(version, toolchain) + + sha_file = ensure_asset(cache_dir, version, "sha256.sum") + checksums = parse_sha256_sum(sha_file) + + for name in names: + ensure_asset(cache_dir, version, name) + verify_asset(cache_dir, checksums, name) + + +def release_json(version: str, toolchain: str, base_url: str) -> bytes: + assets = [ + { + "name": name, + "browser_download_url": f"{base_url}/assets/{name}", + } + for name in asset_names(version, toolchain) + ] + return json.dumps([{"tag_name": f"v{version}", "assets": assets}]).encode() + + +class SdkProxyHandler(http.server.SimpleHTTPRequestHandler): + version: str + toolchain: str + cache_dir: Path + + def log_message(self, fmt: str, *args: object) -> None: + print(f"{self.address_string()} - {fmt % args}", file=sys.stderr) + + def send_bytes(self, data: bytes, content_type: str) -> None: + self.send_response(200) + self.send_header("Content-Type", content_type) + self.send_header("Content-Length", str(len(data))) + self.end_headers() + self.wfile.write(data) + + def do_GET(self) -> None: + parsed = urllib.parse.urlparse(self.path) + + if parsed.path == "/releases": + query = urllib.parse.parse_qs(parsed.query) + page = query.get("page", ["1"])[0] + if page == "1": + host = self.headers.get("Host", "127.0.0.1") + data = release_json(self.version, self.toolchain, f"http://{host}") + else: + data = b"[]" + self.send_bytes(data, "application/json") + return + + if parsed.path.startswith("/assets/"): + filename = Path(urllib.parse.unquote(parsed.path[len("/assets/") :])).name + allowed = set(asset_names(self.version, self.toolchain)) + if filename not in allowed: + self.send_error(404, f"Unknown asset: {filename}") + return + + try: + path = ensure_asset(self.cache_dir, self.version, filename) + if filename != "sha256.sum": + sha_file = ensure_asset(self.cache_dir, self.version, "sha256.sum") + verify_asset(self.cache_dir, parse_sha256_sum(sha_file), filename) + except ( + AssetVerificationError, + subprocess.CalledProcessError, + OSError, + ) as error: + self.send_error(500, str(error)) + return + + self.send_response(200) + self.send_header("Content-Type", "application/octet-stream") + self.send_header("Content-Length", str(path.stat().st_size)) + self.end_headers() + with path.open("rb") as f: + while chunk := f.read(1024 * 1024): + self.wfile.write(chunk) + return + + self.send_error(404, "Not found") + + +def default_cache_dir(version: str) -> Path: + root = os.environ.get("XDG_CACHE_HOME") + if root: + return Path(root) / "zephyr-sdk" / f"v{version}" + return Path.home() / ".cache" / "zephyr-sdk" / f"v{version}" + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--version", default=os.environ.get("SDK_VERSION", "1.0.1")) + parser.add_argument("--toolchain", default="arm-zephyr-eabi") + parser.add_argument("--cache-dir", type=Path) + parser.add_argument("--host", default="127.0.0.1") + parser.add_argument("--port", type=int, default=8765) + parser.add_argument("--download-only", action="store_true") + return parser.parse_args() + + +def main() -> None: + args = parse_args() + cache_dir = args.cache_dir or default_cache_dir(args.version) + + if args.download_only: + try: + populate_cache(cache_dir, args.version, args.toolchain) + except AssetVerificationError as error: + raise SystemExit(str(error)) from error + print(f"Cached Zephyr SDK assets in {cache_dir}") + return + + SdkProxyHandler.version = args.version + SdkProxyHandler.toolchain = args.toolchain + SdkProxyHandler.cache_dir = cache_dir + + server = http.server.ThreadingHTTPServer((args.host, args.port), SdkProxyHandler) + print( + f"Serving Zephyr SDK release metadata at http://{args.host}:{args.port}/releases", + flush=True, + ) + print(f"Cache directory: {cache_dir}", flush=True) + server.serve_forever() + + +if __name__ == "__main__": + main() diff --git a/.claude/skills/zephyr/SKILL.md b/.claude/skills/zephyr/SKILL.md index c5d76fa1b3d..13f8cc7b5b4 100644 --- a/.claude/skills/zephyr/SKILL.md +++ b/.claude/skills/zephyr/SKILL.md @@ -56,7 +56,7 @@ mkdir zephyr_workspace && cd zephyr_workspace python3 -m venv .venv && source .venv/bin/activate pip install west "cmake<4.0.0" pyelftools ninja jsonschema -west init --manifest-rev v4.3.0 +west init --manifest-rev v4.4.0 ``` ### 2. Add ExecuTorch as a module @@ -77,6 +77,7 @@ west config manifest.project-filter -- '-.*,+zephyr,+executorch,+cmsis,+cmsis_6, west update rm -rf modules/lib/executorch ln -s /path/to/your/executorch modules/lib/executorch +west packages pip --install ``` ### 3. Install ExecuTorch @@ -91,12 +92,7 @@ cd ../../.. ### 4. Install Zephyr SDK ```bash -wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.4/zephyr-sdk-0.17.4_linux-x86_64_minimal.tar.xz -tar xf zephyr-sdk-0.17.4_linux-x86_64_minimal.tar.xz -wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.4/toolchain_linux-x86_64_arm-zephyr-eabi.tar.xz -tar xf toolchain_linux-x86_64_arm-zephyr-eabi.tar.xz -C zephyr-sdk-0.17.4/ -./zephyr-sdk-0.17.4/setup.sh -c -t arm-zephyr-eabi -export ZEPHYR_SDK_INSTALL_DIR=$(realpath ./zephyr-sdk-0.17.4) +west sdk install --gnu-toolchains arm-zephyr-eabi ``` ### 5. Install Ethos-U tools (if targeting NPU boards) diff --git a/.github/workflows/trunk.yml b/.github/workflows/trunk.yml index e73df2495bb..90ae58e3123 100644 --- a/.github/workflows/trunk.yml +++ b/.github/workflows/trunk.yml @@ -100,9 +100,10 @@ jobs: timeout: 120 script: | #!/bin/bash - - CONDA_ENV=$(conda env list --json | jq -r ".envs | .[-1]") - conda activate "${CONDA_ENV}" + + # Zephyr minimum Python version is 3.12; since ExecuTorch supports 3.10, ensure we always use 3.12 independent of the base image + conda create -y -n conda_zephyr_test python=3.12 > /dev/null + conda activate conda_zephyr_test # Test zephyr backend set -e diff --git a/.gitignore b/.gitignore index 02dcea02026..87772e21014 100644 --- a/.gitignore +++ b/.gitignore @@ -77,6 +77,9 @@ xcuserdata/ *.dll *.pyd +# Zephyr +zephyr_dev_root/ +zephyr_dev_root.backup.*/ # Agents .claude/*.local.* diff --git a/backends/arm/scripts/toolchain_utils.sh b/backends/arm/scripts/toolchain_utils.sh index 0ed1058fa28..e85d63ae928 100644 --- a/backends/arm/scripts/toolchain_utils.sh +++ b/backends/arm/scripts/toolchain_utils.sh @@ -52,14 +52,14 @@ function zephyr_select_toolchain() { fi if [[ "${ARCH}" == "x86_64" ]] ; then - toolchain_url="https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.4/toolchain_linux-x86_64_arm-zephyr-eabi.tar.xz" + toolchain_url="https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v1.0.1/toolchain_gnu_linux-x86_64_arm-zephyr-eabi.tar.xz" toolchain_dir="arm-zephyr-eabi" - toolchain_md5_checksum="68ae71edc0106c3093055b97aaa47017" + toolchain_md5_checksum="da38a6b6a20bfae8249ab9c7eef72cdd" toolchain_archive="${toolchain_dir}.tar.xz" elif [[ "${ARCH}" == "aarch64" ]] || [[ "${ARCH}" == "arm64" ]] ; then - toolchain_url="https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.4/toolchain_linux-aarch64_arm-zephyr-eabi.tar.xz" + toolchain_url="https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v1.0.1/toolchain_gnu_linux-aarch64_arm-zephyr-eabi.tar.xz" toolchain_dir="arm-zephyr-eabi" - toolchain_md5_checksum="d8a6dfd4314d55da713957d0b161d01f" + toolchain_md5_checksum="ebb47b3f29fa468c6c06fcaa43ebe108" toolchain_archive="${toolchain_dir}.tar.xz" else # This should never happen, it should be covered by setup.sh but catch it anyway diff --git a/backends/arm/test/test_github_trunk_zephyr.sh b/backends/arm/test/test_github_trunk_zephyr.sh index c4ab0e5cfbc..20cbec4e6cc 100755 --- a/backends/arm/test/test_github_trunk_zephyr.sh +++ b/backends/arm/test/test_github_trunk_zephyr.sh @@ -31,6 +31,7 @@ README_PATH="${README_PATH:-}" HELLO_README_PATH="zephyr/samples/hello-executorch/README.md" MV2_README_PATH="zephyr/samples/mv2-ethosu/README.md" DEFAULT_MV2_TARGET_LIST="ethos-u55,ethos-u85" +ZEPHYR_DEV_ROOT="${ZEPHYR_DEV_ROOT:-zephyr_dev_root}" usage() { cat < build/zephyr/zephyr.json << 'EOF' +ZEPHYR_BUILD=~/zephyr_workspace/build/zephyr + +cd /app-release-exec-linux_FW_1.109.00_DEV + +ln -sf "$ZEPHYR_BUILD/zephyr.bin" build/images/zephyr.bin + +cat > build/images/zephyr.json << 'EOF' { - "HP_img_class": { + "DEVICE": { + "binary": "app-device-config.json", + "version": "0.5.0", + "signed": true + }, + "MV2": { "binary": "zephyr.bin", "version": "1.0.0", "mramAddress": "0x80008000", @@ -191,46 +221,143 @@ cat > build/zephyr/zephyr.json << 'EOF' } } EOF + +cat > build/images/app-device-config.json << 'EOF' +{ + "metadata": { + "device": "AE822FA0E5597LS0", + "project": "", + "external_clock_sources": [ + { + "id": "OSC_HFXO", + "enabled": true, + "frequency": 38400000 + }, + { + "id": "OSC_LFXO", + "enabled": false, + "frequency": 32768 + } + ] + }, + "firewall": {"firewall_components": []}, + "pinmux": {"configurations": []}, + "miscellaneous": [] +} +EOF ``` -> **Important:** Use `mramAddress: "0x80008000"` (FLASH_LOAD_OFFSET=0x8000), -> **not** the default `0x80200000`. The default offset does not leave enough -> MRAM for the ~3.5 MB MV2 model blob. +Make sure `cpu_id` matches your target: use `M55_HP` for +`ensemble_e8_dk/ae822fa0e5597ls0/rtss_hp` and `M55_HE` for +`ensemble_e8_dk/ae822fa0e5597ls0/rtss_he`. -> **Note:** Your SE Tools install may include additional `zephyr.json` entries -> (e.g., a `DEVICE` block referencing `app-device-config.json`). Copy those -> from the SE Tools template if your board configuration requires them. +`zephyr.json` places the image at `0x80008000`, matching the board config's +`CONFIG_FLASH_LOAD_OFFSET=0x8000`: -Generate the table of contents and flash using the SE Tools: +> **Important:** Keep `mramAddress: "0x80008000"` and +> `CONFIG_FLASH_LOAD_OFFSET=0x8000` in sync. If these differ, SES may accept the +> ATOC but the M55 image will not start correctly. + +Generate the ATOC package from the SE Tools directory. The executable releases +expect image files under their own `build/images` directory, so stage the Zephyr +outputs there with symlinks: ```bash -cd build/zephyr -python /app-gen-toc.py -python /app-write-mram.py -cd ../.. +./app-gen-toc -f "build/images/zephyr.json" ``` -Refer to the Alif SE Tools documentation for installation and detailed usage. +Note that some versions use app-gen-toc.py + +This creates `build/AppTocPackage.bin` in the SE Tools directory. + + +The DK-E8 routes the J-Link VCOM to different UARTs using `SW4`: + +- Set `SW4=SE` for SE Tools and the Secure Enclave boot log at 57600 baud. +- Set `SW4=U2` for the Zephyr RTSS-HE console at 115200 baud. +- Set `SW4=U4` for the Zephyr RTSS-HP console at 115200 baud. + +To flash set `SW4=SE` and run + +```bash +./app-write-mram +``` +Note that some versions use app-write-mram.py + +On some boards the running application prevents the ISP handshake. In that case, +enter hard maintenance mode first. Keep `SW4=SE`, close any serial terminal, and +use the same baud rate as the SE boot log (`57600` on DK-E8): + +```bash +./maintenance -c /dev/ttyACM0 -b 57600 +``` + +Select: + +```text +1 - Device Control +1 - Hard maintenance mode +``` + +When the tool prints `Waiting for Target..[RESET Platform]`, press the physical +reset button on the board. Wait for the tool to return to the menu. + +Verify that hard maintenance really succeeded before flashing. From the returned +menu, select: + +```text +Enter - return to the top-level menu +2 - Device Information +4 - Device enquiry +``` + +Continue only if the device enquiry reports `Maintenance Mode = Enabled`. The +maintenance tool may still show menus after `Device did not respond`; that does +not mean the target is connected. If device enquiry also reports `Target did not +respond`, power-cycle the board, keep `SW4=SE`, press reset, and repeat the hard +maintenance step. + +After `Maintenance Mode = Enabled`, exit the maintenance tool and flash without +resetting out of maintenance mode: + +```bash +./app-write-mram -b 57600 -nr -s +``` + +If prompted for the serial port, enter the J-Link VCOM port, for example +`/dev/ttyACM0`. + +You can verify the flash and boot if needed with `SW4` set to `SE`, connected +to the SE boot UART at 57600 baud: + +```bash +picocom -b 57600 /dev/ttyACM0 +``` + +Press the reset button on the E8 DevKit. +The package has been accepted and booted when you see `ATOC ok` and a table row +for `M55-HP` or `M55-HE` whose flags include `B`. ### Connect Serial Console -Connect to UART4 at 115200 baud. On Linux: +After flashing, make sure `SW4` is set to `U4` for RTSS-HP or `U2` for RTSS-HE, +open the serial terminal, and press reset: ```bash -picocom -b 115200 /dev/ttyUSB0 +picocom -b 115200 /dev/ttyACM0 ``` Press the reset button on the E8 DevKit. You should see: ``` -Booting Zephyr OS build ff8b8697c0f5 *** +*** Booting Zephyr OS build v4.4.0 *** ======================================== ExecuTorch MobileNetV2 Classification Demo ======================================== I [executorch:main.cpp] Ethos-U backend registered successfully -I [executorch:main.cpp] Model PTE at 0x8004b290, Size: 3490912 bytes +I [executorch:main.cpp] Model PTE at 0x800774a0, Size: 3380576 bytes I [executorch:main.cpp] Model loaded, has 1 methods I [executorch:main.cpp] Running method: forward I [executorch:main.cpp] Method allocator pool size: 1572864 bytes. @@ -238,24 +365,26 @@ I [executorch:main.cpp] Setting up planned buffer 0, size 752640. I [executorch:main.cpp] Loading method... I [executorch:main.cpp] Method 'forward' loaded successfully I [executorch:main.cpp] Preparing input: static RGB image (150528 bytes) +I [executorch:main.cpp] Input tensor: scalar_type=Float, numel=150528, nbytes=602112 +I [executorch:main.cpp] Converting uint8 input (150528 elements) to float32 I [executorch:main.cpp] --- Starting inference --- -I [executorch:main.cpp] Inference completed in 19 ms +I [executorch:main.cpp] Inference completed in 30 ms I [executorch:main.cpp] --- Classification Results --- -I [executorch:main.cpp] Top-5 predictions: -I [executorch:main.cpp] [1] class 0: 0.0000 -I [executorch:main.cpp] [2] class 1: 0.0000 -I [executorch:main.cpp] [3] class 2: 0.0000 -I [executorch:main.cpp] [4] class 3: 0.0000 -I [executorch:main.cpp] [5] class 4: 0.0000 +Top-5 predictions: +I [executorch:main.cpp] [1] class 92: 3.2362 +I [executorch:main.cpp] [2] class 21: 3.0362 +I [executorch:main.cpp] [3] class 127: 2.8180 +I [executorch:main.cpp] [4] class 22: 2.5998 +I [executorch:main.cpp] [5] class 18: 2.5089 I [executorch:main.cpp] ======================================== I [executorch:main.cpp] MobileNetV2 Demo Complete -I [executorch:main.cpp] Model size: 3490912 bytes -I [executorch:main.cpp] Input: 224x224x3 RGB image (150528 bytes) +I [executorch:main.cpp] Model size: 3380576 bytes +I [executorch:main.cpp] Input: [1, 3, 224, 224] NCHW RGB tensor (150528 bytes) I [executorch:main.cpp] Output: 1000 ImageNet classes (top-5 shown) -I [executorch:main.cpp] Inference time: 19 ms +I [executorch:main.cpp] Inference time: 30 ms I [executorch:main.cpp] ======================================== ``` @@ -269,8 +398,9 @@ Use `mv2` (with torchvision pretrained weights) for meaningful class scores. | Linker: `region 'FLASH' overflowed` | Model PTE too large for ITCM | Use the DDR overlay (FVP) or verify mramAddress (Alif) | | Linker: `region 'RAM' overflowed` | Pools + model copy exceed SRAM | Set `CONFIG_ET_ARM_MODEL_PTE_DMA_ACCESSIBLE=y` to skip the SRAM copy | | FVP hangs after "Ethos-U backend registered" | Cycle-accurate MV2 simulation is slow | Wait 10-20 min, or use Corstone-320 (faster than 300) | -| No serial output on Alif | Wrong UART or baud rate | Use UART4 at 115200 baud | -| `app-write-mram.py` fails | Wrong mramAddress | Use `0x80008000`, not `0x80200000` | +| No Zephyr serial output on Alif | `SW4` still routes VCOM to SE UART | Move `SW4` to `U4` and use 115200 baud | +| No SE Tools response | Serial terminal is open, wrong `SW4` setting, or app blocks ISP | Close terminal, set `SW4=SE`, or enter hard maintenance mode | +| `app-write-mram` fails or app does not boot | `mramAddress` and link address differ | Use `0x80008000`, not `0x80200000` with `CONFIG_FLASH_LOAD_OFFSET=0x8000` | | Runtime: method allocator OOM | Pool size too small | Increase `CONFIG_EXECUTORCH_METHOD_ALLOCATOR_POOL_SIZE` in the Zephyr config used for the build (for example `prj.conf`, an `OVERLAY_CONFIG`, or a board `.conf`) | ## Memory Layout @@ -298,7 +428,6 @@ Cortex-M builds, `/executorch-kb` for backend-specific debugging. ## Next Steps -- Swap `mv2_untrained` for `mv2` (with torchvision) to get real ImageNet predictions - Try other models: `resnet18`, or bring your own `.py` model file - Explore the [hello-executorch sample](https://github.com/pytorch/executorch/tree/main/zephyr/samples/hello-executorch) for a minimal starting point - See the {doc}`Ethos-U Getting Started tutorial ` for the baremetal (non-Zephyr) flow diff --git a/zephyr/README.md b/zephyr/README.md index 67fa680aa17..48fd2e86fa9 100644 --- a/zephyr/README.md +++ b/zephyr/README.md @@ -23,13 +23,7 @@ pip install west "cmake<4.0.0" pyelftools ninja jsonschema Setup zephyr repo ``` -west init --manifest-rev v4.3.0 -``` - -Install Zephyr SDK according to Zephyr's guides and set ZEPHYR_SDK_INSTALL_DIR - -``` -export ZEPHYR_SDK_INSTALL_DIR= +west init --manifest-rev v4.4.0 ``` # Usage with Zephyr @@ -59,6 +53,22 @@ west config manifest.project-filter -- -.*,+zephyr,+executorch,+cmsis,+cmsis_6,+ west update ``` +## Install Zephyr Python packages + + +``` +west packages pip --install +``` + +## Install Zephyr SDK + + +``` +west sdk install --gnu-toolchains arm-zephyr-eabi +``` + +Or install Zephyr SDK according to Zephyr's guides for other targets. + ## Setup and install ExecuTorch Setup ExecuTorch diff --git a/zephyr/samples/hello-executorch/README.md b/zephyr/samples/hello-executorch/README.md index 45efe73d7d1..80fb84a3ddb 100644 --- a/zephyr/samples/hello-executorch/README.md +++ b/zephyr/samples/hello-executorch/README.md @@ -21,6 +21,7 @@ Config Zephyr Corstone300 FVP ``` export FVP_ROOT=$PWD/modules/lib/executorch/examples/arm/arm-scratch/FVP-corstone300 export ARMFVP_BIN_PATH=${FVP_ROOT}/models/Linux64_GCC-9.3 +export LD_LIBRARY_PATH=${FVP_ROOT}/python/lib:${ARMFVP_BIN_PATH}:${LD_LIBRARY_PATH:-} export ARMFVP_EXTRA_FLAGS="-C mps3_board.uart0.shutdown_on_eot=1 -C ethosu.num_macs=128" ``` @@ -76,7 +77,7 @@ Config Zephyr Corstone320 FVP ``` export FVP_ROOT=$PWD/modules/lib/executorch/examples/arm/arm-scratch/FVP-corstone320 export ARMFVP_BIN_PATH=${FVP_ROOT}/models/Linux64_GCC-9.3 -export LD_LIBRARY_PATH=${FVP_ROOT}/python/lib:${ARMFVP_BIN_PATH}:${LD_LIBRARY_PATH} +export LD_LIBRARY_PATH=${FVP_ROOT}/python/lib:${ARMFVP_BIN_PATH}:${LD_LIBRARY_PATH:-} export ARMFVP_EXTRA_FLAGS="-C mps4_board.uart0.shutdown_on_eot=1 -C mps4_board.subsystem.ethosu.num_macs=256" ``` diff --git a/zephyr/samples/mv2-ethosu/README.md b/zephyr/samples/mv2-ethosu/README.md index 70877abcafb..1de68870792 100644 --- a/zephyr/samples/mv2-ethosu/README.md +++ b/zephyr/samples/mv2-ethosu/README.md @@ -9,7 +9,7 @@ The model classifies a static RGB test input tensor with shape `[1, 3, 224, 224] ## Prerequisites - Zephyr SDK with ExecuTorch module enabled -- Python 3.10+ with ExecuTorch, torchvision, and ethos-u-vela installed +- Python 3.12+ with ExecuTorch, torchvision, and ethos-u-vela installed - A board with Arm Ethos-U NPU (e.g., Corstone-300 FVP, Alif E7/E8 DevKit) ## Corstone-300 FVP (Ethos-U55) @@ -27,6 +27,7 @@ Config Zephyr Corstone300 FVP ``` export FVP_ROOT=$PWD/modules/lib/executorch/examples/arm/arm-scratch/FVP-corstone300 export ARMFVP_BIN_PATH=${FVP_ROOT}/models/Linux64_GCC-9.3 +export LD_LIBRARY_PATH=${FVP_ROOT}/python/lib:${ARMFVP_BIN_PATH}:${LD_LIBRARY_PATH:-} export ARMFVP_EXTRA_FLAGS="-C mps3_board.uart0.shutdown_on_eot=1 -C ethosu.num_macs=128" ``` @@ -62,7 +63,7 @@ Config Zephyr Corstone320 FVP ``` export FVP_ROOT=$PWD/modules/lib/executorch/examples/arm/arm-scratch/FVP-corstone320 export ARMFVP_BIN_PATH=${FVP_ROOT}/models/Linux64_GCC-9.3 -export LD_LIBRARY_PATH=${FVP_ROOT}/python/lib:${ARMFVP_BIN_PATH}:${LD_LIBRARY_PATH} +export LD_LIBRARY_PATH=${FVP_ROOT}/python/lib:${ARMFVP_BIN_PATH}:${LD_LIBRARY_PATH:-} export ARMFVP_EXTRA_FLAGS="-C mps4_board.uart0.shutdown_on_eot=1 -C mps4_board.subsystem.ethosu.num_macs=256" ``` @@ -102,12 +103,27 @@ python -m modules.lib.executorch.backends.arm.scripts.aot_arm_compiler \ ``` ```bash -west build -b alif_e8_dk/ae822fa0e5597xx0/rtss_hp \ - -S ethos-u55-enable \ +west build -d build -b ensemble_e8_dk/ae822fa0e5597ls0/rtss_hp \ modules/lib/executorch/zephyr/samples/mv2-ethosu -- \ -DET_PTE_FILE_PATH=mv2_ethosu.pte ``` +### Flash with west +```bash +west flash +``` +If `west flash` does not work on your board, flash with Alif SE Tools instead; +see the [Zephyr Alif tutorial](../../../docs/source/zephyr_alif_tutorial.md). + +### Run + +After flashing, make sure the board has `SW4=U4`, open the Zephyr +console at 115200 baud, and reset again: + +```bash +picocom -b 115200 /dev/ttyACM0 +``` + ## Expected output ``` diff --git a/zephyr/samples/mv2-ethosu/boards/alif_e8_dk_ae822fa0e5597xx0_rtss_hp.conf b/zephyr/samples/mv2-ethosu/boards/alif_e8_dk_ae822fa0e5597xx0_rtss_hp.conf deleted file mode 100644 index 3f7c0afa4f2..00000000000 --- a/zephyr/samples/mv2-ethosu/boards/alif_e8_dk_ae822fa0e5597xx0_rtss_hp.conf +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# -# Copyright 2026 Arm Limited and/or its affiliates. -# -# SPDX-License-Identifier: Apache-2.0 -# -# Alif Ensemble E8 DevKit (HP core): Ethos-U55 with 256 MACs. -# MRAM is DMA-accessible by the NPU so no SRAM copy is needed. -CONFIG_ETHOS_U=y -CONFIG_ET_ARM_MODEL_PTE_DMA_ACCESSIBLE=y diff --git a/zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_he.conf b/zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_he.conf new file mode 100644 index 00000000000..32725f34b1b --- /dev/null +++ b/zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_he.conf @@ -0,0 +1,18 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# Copyright 2026 Arm Limited and/or its affiliates. +# +# SPDX-License-Identifier: Apache-2.0 + +# Keep the linked image address in sync with the Alif ATOC mramAddress used by +# this sample's generated zephyr.json. +CONFIG_FLASH_LOAD_OFFSET=0x8000 + +# Enable the Zephyr Ethos-U driver so the ExecuTorch Arm backend is built and +# the EthosUBackend delegate is registered at runtime. +CONFIG_ETHOS_U=y +CONFIG_ETHOS_U55_256=y + +# Alif MRAM is DMA-accessible by the NPU, so avoid duplicating the model into +# SRAM at startup. +CONFIG_ET_ARM_MODEL_PTE_DMA_ACCESSIBLE=y diff --git a/zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_he.overlay b/zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_he.overlay new file mode 100644 index 00000000000..64aa03107b5 --- /dev/null +++ b/zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_he.overlay @@ -0,0 +1,38 @@ +/* Copyright (c) Meta Platforms, Inc. and affiliates. + * + * Copyright 2026 Arm Limited and/or its affiliates. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* The default board DTS routes Zephyr RAM to 256 KiB DTCM on RTSS-HE. + * MobileNetV2 needs much more space, so expose the contiguous SRAM0 and SRAM1 + * banks as one 8 MiB Zephyr RAM region for this sample. + */ + +/delete-node/ &sram0; +/delete-node/ &sram1; + +&soc { + ethosu0: ethosu55@400e1000 { + compatible = "arm,ethos-u"; + reg = <0x400e1000 0x1000>; + interrupts = <55 0>; + interrupt-parent = <&nvic>; + secure-enable; + privilege-enable; + status = "okay"; + }; + + sram0: sram@2000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x2000000 DT_SIZE_M(8)>; + zephyr,memory-region = "SRAM0"; + }; +}; + +/ { + chosen { + zephyr,sram = &sram0; + }; +}; diff --git a/zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_hp.conf b/zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_hp.conf new file mode 100644 index 00000000000..32725f34b1b --- /dev/null +++ b/zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_hp.conf @@ -0,0 +1,18 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# Copyright 2026 Arm Limited and/or its affiliates. +# +# SPDX-License-Identifier: Apache-2.0 + +# Keep the linked image address in sync with the Alif ATOC mramAddress used by +# this sample's generated zephyr.json. +CONFIG_FLASH_LOAD_OFFSET=0x8000 + +# Enable the Zephyr Ethos-U driver so the ExecuTorch Arm backend is built and +# the EthosUBackend delegate is registered at runtime. +CONFIG_ETHOS_U=y +CONFIG_ETHOS_U55_256=y + +# Alif MRAM is DMA-accessible by the NPU, so avoid duplicating the model into +# SRAM at startup. +CONFIG_ET_ARM_MODEL_PTE_DMA_ACCESSIBLE=y diff --git a/zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_hp.overlay b/zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_hp.overlay new file mode 100644 index 00000000000..3151018ea42 --- /dev/null +++ b/zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_hp.overlay @@ -0,0 +1,38 @@ +/* Copyright (c) Meta Platforms, Inc. and affiliates. + * + * Copyright 2026 Arm Limited and/or its affiliates. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* The default board DTS routes Zephyr RAM to 1 MiB DTCM. MobileNetV2 allocator + * pools exceed that space, so expose the contiguous SRAM0 and SRAM1 banks as + * one 8 MiB Zephyr RAM region for this sample. + */ + +/delete-node/ &sram0; +/delete-node/ &sram1; + +&soc { + ethosu0: ethosu55@400e1000 { + compatible = "arm,ethos-u"; + reg = <0x400e1000 0x1000>; + interrupts = <55 0>; + interrupt-parent = <&nvic>; + secure-enable; + privilege-enable; + status = "okay"; + }; + + sram0: sram@2000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x2000000 DT_SIZE_M(8)>; + zephyr,memory-region = "SRAM0"; + }; +}; + +/ { + chosen { + zephyr,sram = &sram0; + }; +}; From 97a6240d03e7025a4f1beff2046603986b4c6637 Mon Sep 17 00:00:00 2001 From: Zingo Andersen Date: Fri, 5 Jun 2026 11:36:16 +0200 Subject: [PATCH 2/9] Zephyr: Precache SDK in CI Docker Signed-off-by: Zingo Andersen Change-Id: I071cc0d1332f27b326792e93e2a81fb30502a6b6 --- .ci/docker/common/install_zephyr.sh | 17 ++++++- .../common}/zephyr_sdk_release_proxy.py | 47 +++++++++++++---- .ci/docker/ubuntu/Dockerfile | 3 +- .ci/scripts/test_zephyr.sh | 51 ++++++++++++------- .github/workflows/trunk.yml | 6 +-- 5 files changed, 89 insertions(+), 35 deletions(-) rename .ci/{scripts => docker/common}/zephyr_sdk_release_proxy.py (88%) mode change 100755 => 100644 diff --git a/.ci/docker/common/install_zephyr.sh b/.ci/docker/common/install_zephyr.sh index 8ac1753c671..cd2b90a7359 100644 --- a/.ci/docker/common/install_zephyr.sh +++ b/.ci/docker/common/install_zephyr.sh @@ -9,8 +9,10 @@ set -ex +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + # shellcheck source=/dev/null -source "$(dirname "${BASH_SOURCE[0]}")/utils.sh" +source "${SCRIPT_DIR}/utils.sh" # Double check if the NDK version is set [ -n "${ZEPHYR_SDK}" ] @@ -56,7 +58,7 @@ install_prerequiresites() { apt update test -f /usr/share/doc/kitware-archive-keyring/copyright || \ wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null - "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/kitware.list > /dev/null + echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/kitware.list > /dev/null apt update apt install cmake @@ -83,6 +85,17 @@ install_prerequiresites() { rm -f kitware-archive.sh pip_install --no-cache-dir west pip_install pyelftools + + # Cache the Zephyr SDK release assets in the image. CI still runs + # `west sdk install` in its workspace, but the local proxy fallback can serve + # these files without downloading them on every job. + local zephyr_sdk_version + zephyr_sdk_version="$(python3 "${SCRIPT_DIR}/zephyr_sdk_release_proxy.py" --print-version)" + local zephyr_sdk_cache_dir="${ZEPHYR_SDK_RELEASE_PROXY_CACHE_DIR:-/opt/zephyr-sdk-cache/v${zephyr_sdk_version}}" + python3 "${SCRIPT_DIR}/zephyr_sdk_release_proxy.py" \ + --version "${zephyr_sdk_version}" \ + --cache-dir "${zephyr_sdk_cache_dir}" \ + --populate-cache } install_prerequiresites diff --git a/.ci/scripts/zephyr_sdk_release_proxy.py b/.ci/docker/common/zephyr_sdk_release_proxy.py old mode 100755 new mode 100644 similarity index 88% rename from .ci/scripts/zephyr_sdk_release_proxy.py rename to .ci/docker/common/zephyr_sdk_release_proxy.py index bcd61ad1f7c..4adf3912516 --- a/.ci/scripts/zephyr_sdk_release_proxy.py +++ b/.ci/docker/common/zephyr_sdk_release_proxy.py @@ -13,19 +13,19 @@ Examples: # Prepopulate CI cache only. - .ci/scripts/zephyr_sdk_release_proxy.py \ - --version 1.0.1 \ - --cache-dir .cache/zephyr-sdk/v1.0.1 \ - --download-only + .ci/docker/common/zephyr_sdk_release_proxy.py \ + --version \ + --cache-dir .cache/zephyr-sdk/v \ + --populate-cache # Serve cached assets and release metadata. - .ci/scripts/zephyr_sdk_release_proxy.py \ - --version 1.0.1 \ - --cache-dir .cache/zephyr-sdk/v1.0.1 \ + .ci/docker/common/zephyr_sdk_release_proxy.py \ + --version \ + --cache-dir .cache/zephyr-sdk/v \ --port 8765 west sdk install \ - --version 1.0.1 \ + --version \ --api-url http://127.0.0.1:8765/releases \ --gnu-toolchains arm-zephyr-eabi """ @@ -45,10 +45,21 @@ from pathlib import Path +DEFAULT_SDK_VERSION = "1.0.1" + + class AssetVerificationError(Exception): pass +def default_sdk_version() -> str: + return ( + os.environ.get("ZEPHYR_SDK_VERSION") + or os.environ.get("SDK_VERSION") + or DEFAULT_SDK_VERSION + ) + + def host_tuple() -> tuple[str, str]: system = platform.system() machine = platform.machine() @@ -226,17 +237,33 @@ def default_cache_dir(version: str) -> Path: def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--version", default=os.environ.get("SDK_VERSION", "1.0.1")) + parser.add_argument("--version", default=default_sdk_version()) parser.add_argument("--toolchain", default="arm-zephyr-eabi") parser.add_argument("--cache-dir", type=Path) parser.add_argument("--host", default="127.0.0.1") parser.add_argument("--port", type=int, default=8765) - parser.add_argument("--download-only", action="store_true") + parser.add_argument( + "--print-version", + action="store_true", + help="Print the effective default SDK version and exit.", + ) + parser.add_argument( + "--download-only", + "--populate-cache", + dest="download_only", + action="store_true", + help="Download and verify release assets, then exit without serving.", + ) return parser.parse_args() def main() -> None: args = parse_args() + + if args.print_version: + print(args.version) + return + cache_dir = args.cache_dir or default_cache_dir(args.version) if args.download_only: diff --git a/.ci/docker/ubuntu/Dockerfile b/.ci/docker/ubuntu/Dockerfile index 9a5b2536df0..5acbd8181d1 100644 --- a/.ci/docker/ubuntu/Dockerfile +++ b/.ci/docker/ubuntu/Dockerfile @@ -93,9 +93,10 @@ RUN rm install_arm.sh ARG ZEPHYR_SDK COPY ./common/install_zephyr.sh install_zephyr.sh +COPY ./common/zephyr_sdk_release_proxy.py zephyr_sdk_release_proxy.py COPY ./common/utils.sh utils.sh RUN if [ -n "${ZEPHYR_SDK}" ]; then bash ./install_zephyr.sh; fi -RUN rm install_zephyr.sh utils.sh +RUN rm install_zephyr.sh zephyr_sdk_release_proxy.py utils.sh ARG QNN_SDK diff --git a/.ci/scripts/test_zephyr.sh b/.ci/scripts/test_zephyr.sh index 7e33a02f310..444793e4fd1 100755 --- a/.ci/scripts/test_zephyr.sh +++ b/.ci/scripts/test_zephyr.sh @@ -119,45 +119,59 @@ run_target_test_blocks_from_readme() { } run_west_sdk_install_with_proxy_fallback() { - local sdk_version proxy_port proxy_url proxy_cache_dir proxy_pid + local sdk_version proxy_port proxy_url proxy_cache_dir proxy_pid proxy_ready - # Try expected setup first. - if run_command_block_from_readme "${ZEPHYR_README_PATH}" ""; then - return 0 - fi - - echo "west sdk install failed; retrying through local release proxy" - - sdk_version="1.0.1" - if [[ -f "zephyr/SDK_VERSION" ]]; then - sdk_version="$(/dev/null 2>&1 || true' RETURN + proxy_ready=0 for _ in {1..30}; do if wget -qO- "${proxy_url}?page=1" >/dev/null 2>&1; then + proxy_ready=1 break fi sleep 1 done - west sdk install \ + if [[ ${proxy_ready} -ne 1 ]]; then + echo "Zephyr SDK release proxy did not become reachable at ${proxy_url}; retrying direct install" >&2 + kill "${proxy_pid}" >/dev/null 2>&1 || true + trap - RETURN + run_command_block_from_readme "${ZEPHYR_README_PATH}" "" + return + fi + + if west sdk install \ --version "${sdk_version}" \ --api-url "${proxy_url}" \ - --gnu-toolchains arm-zephyr-eabi + --gnu-toolchains arm-zephyr-eabi; then + kill "${proxy_pid}" >/dev/null 2>&1 || true + trap - RETURN + return 0 + fi kill "${proxy_pid}" >/dev/null 2>&1 || true trap - RETURN + + echo "west sdk install through local release proxy failed; retrying direct install" + run_command_block_from_readme "${ZEPHYR_README_PATH}" "" } setup_zephyr_workspace() { @@ -193,9 +207,8 @@ setup_zephyr_workspace() { run_command_block_from_readme "${ZEPHYR_README_PATH}" "" - # Sometimes west sdk install can fail due to network issues or problems with - # rate limiting on the Zephyr SDK download server. If it fails, retry through - # a temporary local proxy that serves the release files from a local cache. + # Install through a temporary local proxy so CI can use SDK release assets + # cached in the Docker image and avoid downloading them in every job. run_west_sdk_install_with_proxy_fallback # Setup git local user for Executorch git to allow diff --git a/.github/workflows/trunk.yml b/.github/workflows/trunk.yml index 90ae58e3123..e41834ac2d3 100644 --- a/.github/workflows/trunk.yml +++ b/.github/workflows/trunk.yml @@ -100,14 +100,14 @@ jobs: timeout: 120 script: | #!/bin/bash - + + set -euo pipefail + # Zephyr minimum Python version is 3.12; since ExecuTorch supports 3.10, ensure we always use 3.12 independent of the base image conda create -y -n conda_zephyr_test python=3.12 > /dev/null conda activate conda_zephyr_test # Test zephyr backend - set -e - .ci/scripts/test_zephyr.sh \ --targets "${TARGET_LIST:-${{ matrix.target }}}" \ --zephyr-samples-readme-path "${{ matrix.readme }}" From e005c82f396b25394f5a3d13bef13327d54b61dc Mon Sep 17 00:00:00 2001 From: Zingo Andersen Date: Fri, 5 Jun 2026 11:07:03 +0200 Subject: [PATCH 3/9] Zephyr: Zephyr 4.4 setup requieres venv Signed-off-by: Zingo Andersen Change-Id: I9e0bbd7bdb2abc3eef6daeba1ae04babde7d80b8 --- .github/workflows/trunk.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/trunk.yml b/.github/workflows/trunk.yml index e41834ac2d3..1b0f608b06b 100644 --- a/.github/workflows/trunk.yml +++ b/.github/workflows/trunk.yml @@ -103,9 +103,10 @@ jobs: set -euo pipefail - # Zephyr minimum Python version is 3.12; since ExecuTorch supports 3.10, ensure we always use 3.12 independent of the base image - conda create -y -n conda_zephyr_test python=3.12 > /dev/null - conda activate conda_zephyr_test + # Zephyr requires a Python 3.12 venv; keep this independent of the + # base image's default ExecuTorch Python environment. + python3.12 -m venv zephyr_test_venv + source zephyr_test_venv/bin/activate # Test zephyr backend .ci/scripts/test_zephyr.sh \ From 157013eacd468a87a0af24244d3a4b6526a82a29 Mon Sep 17 00:00:00 2001 From: Zingo Andersen Date: Fri, 5 Jun 2026 11:36:16 +0200 Subject: [PATCH 4/9] Zephyr: Align Alif RTSS-HE Ethos-U target Signed-off-by: Zingo Andersen Change-Id: I8ddcae1b95e948336ead54bb307f202b1fa927ce --- docs/source/zephyr_alif_tutorial.md | 4 ++-- .../boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_he.conf | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/zephyr_alif_tutorial.md b/docs/source/zephyr_alif_tutorial.md index c04fe5132be..c6598fcdf3f 100644 --- a/docs/source/zephyr_alif_tutorial.md +++ b/docs/source/zephyr_alif_tutorial.md @@ -95,7 +95,7 @@ source modules/lib/executorch/examples/arm/arm-scratch/setup_path.sh Export a quantized INT8 MobileNetV2 with Ethos-U delegation. Choose the target that matches your hardware: -**For Alif E8 (Ethos-U55 with 256 MACs):** +**For Alif E8 (HP Ethos-U55 with 256 MACs):** ```bash python -m modules.lib.executorch.backends.arm.scripts.aot_arm_compiler \ @@ -105,7 +105,7 @@ python -m modules.lib.executorch.backends.arm.scripts.aot_arm_compiler \ --output=mv2_ethosu.pte ``` -If rtss_he is used instead of rtss_hp below use `--target=ethos-u55-128` +If rtss_he is used instead of rtss_hp below use `--target=ethos-u55-128` to match the hardware. **For Corstone-320 FVP (Ethos-U85 with 256 MACs):** diff --git a/zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_he.conf b/zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_he.conf index 32725f34b1b..77b3aebd3bc 100644 --- a/zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_he.conf +++ b/zephyr/samples/mv2-ethosu/boards/ensemble_e8_dk_ae822fa0e5597ls0_rtss_he.conf @@ -11,7 +11,7 @@ CONFIG_FLASH_LOAD_OFFSET=0x8000 # Enable the Zephyr Ethos-U driver so the ExecuTorch Arm backend is built and # the EthosUBackend delegate is registered at runtime. CONFIG_ETHOS_U=y -CONFIG_ETHOS_U55_256=y +CONFIG_ETHOS_U55_128=y # Alif MRAM is DMA-accessible by the NPU, so avoid duplicating the model into # SRAM at startup. From b9c0bb7c6b6a26d68e88970ef36e356478e503d3 Mon Sep 17 00:00:00 2001 From: Zingo Andersen Date: Mon, 8 Jun 2026 07:45:40 +0200 Subject: [PATCH 5/9] Zephyr: Fix CI install script so it can be used in scripts Signed-off-by: Zingo Andersen Change-Id: Ic0e1724409ca976375f54b1bf2dfd8badbb3f582 --- .ci/docker/common/install_zephyr.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.ci/docker/common/install_zephyr.sh b/.ci/docker/common/install_zephyr.sh index cd2b90a7359..e6e374f444f 100644 --- a/.ci/docker/common/install_zephyr.sh +++ b/.ci/docker/common/install_zephyr.sh @@ -53,14 +53,13 @@ install_prerequiresites() { # Upgrade cmake ot 3.24 apt update - apt install cmake - apt install software-properties-common lsb-release + apt install -y software-properties-common lsb-release apt update test -f /usr/share/doc/kitware-archive-keyring/copyright || \ wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/kitware.list > /dev/null apt update - apt install cmake + apt install -y cmake # Install additional required software for Zephyr apt install --no-install-recommends -y ccache \ From dfcaa7d2d3da30c075f5a094978609fdd297efae Mon Sep 17 00:00:00 2001 From: Zingo Andersen Date: Mon, 8 Jun 2026 15:38:26 +0200 Subject: [PATCH 6/9] Zephyr: Fix Zephyr size tests for toolchain used by Zephyr 4.4 Signed-off-by: Zingo Andersen Change-Id: Iaeb5cd988a3e3d091179c11dd6667479a412acd5 --- examples/zephyr/x86_64-linux-arm-zephyr-eabi-gcc.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/zephyr/x86_64-linux-arm-zephyr-eabi-gcc.cmake b/examples/zephyr/x86_64-linux-arm-zephyr-eabi-gcc.cmake index ef58f9b4e8d..20c59c2a276 100644 --- a/examples/zephyr/x86_64-linux-arm-zephyr-eabi-gcc.cmake +++ b/examples/zephyr/x86_64-linux-arm-zephyr-eabi-gcc.cmake @@ -1,5 +1,5 @@ # -# Copyright (c) 2020-2022 Arm Limited. All rights reserved. +# Copyright (c) 2020-2022,2026 Arm Limited. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 # @@ -57,10 +57,10 @@ add_compile_definitions("$<$>:NDEBUG>") # Link options add_link_options(-mcpu=${GCC_CPU} -mthumb) +# Zephyr SDK GCC defaults to Picolibc and does not ship GNU Arm's +# nosys.specs/rdimon.specs files. if(SEMIHOSTING) - add_link_options(--specs=rdimon.specs) -else() - add_link_options(--specs=nosys.specs) + add_link_options(-lsemihost) endif() # Set floating point unit From 9a522c63779c3118c840cfe8b6a268adb46f35fa Mon Sep 17 00:00:00 2001 From: Zingo Andersen Date: Wed, 10 Jun 2026 16:38:08 +0200 Subject: [PATCH 7/9] Zephyr: PR Fixes Signed-off-by: Zingo Andersen Change-Id: I8fc09f92447475f0735686f1e29d9040f796b73f --- .ci/scripts/test_zephyr.sh | 11 +++++++++++ docs/source/zephyr_alif_tutorial.md | 7 ++++--- .../zephyr/x86_64-linux-arm-zephyr-eabi-gcc.cmake | 6 ------ 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.ci/scripts/test_zephyr.sh b/.ci/scripts/test_zephyr.sh index 444793e4fd1..bdd0069ebe8 100755 --- a/.ci/scripts/test_zephyr.sh +++ b/.ci/scripts/test_zephyr.sh @@ -32,17 +32,28 @@ Options: EOF } +require_value() { + if [[ -z "${2:-}" || "${2:-}" == -* ]]; then + echo "ERROR: $1 requires a non-empty argument" >&2 + usage >&2 + exit 1 + fi +} + while [[ $# -gt 0 ]]; do case "$1" in --zephyr-samples-readme-path) + require_value "$1" "${2:-}" ZEPHYR_SAMPLES_README_PATH="$2" shift 2 ;; --zephyr-dev-root) + require_value "$1" "${2:-}" ZEPHYR_DEV_ROOT="$2" shift 2 ;; --targets) + require_value "$1" "${2:-}" TARGETS_ARG="$2" shift 2 ;; diff --git a/docs/source/zephyr_alif_tutorial.md b/docs/source/zephyr_alif_tutorial.md index c6598fcdf3f..70d8d6f9671 100644 --- a/docs/source/zephyr_alif_tutorial.md +++ b/docs/source/zephyr_alif_tutorial.md @@ -383,13 +383,14 @@ I [executorch:main.cpp] I [executorch:main.cpp] MobileNetV2 Demo Complete I [executorch:main.cpp] Model size: 3380576 bytes I [executorch:main.cpp] Input: [1, 3, 224, 224] NCHW RGB tensor (150528 bytes) -I [executorch:main.cpp] Output: 1000 ImageNet classes (top-5 shown) +I [executorch:main.cpp] Output: 1000 classes (top-5 shown) I [executorch:main.cpp] Inference time: 30 ms I [executorch:main.cpp] ======================================== ``` -All predictions show `0.0000` because `mv2_untrained` has random weights. -Use `mv2` (with torchvision pretrained weights) for meaningful class scores. +Use `mv2_untrained` instead of `mv2` if you want to avoid downloading +pretrained weights. In that case the class scores are arbitrary and may all be +close to `0.0000`. ## Troubleshooting diff --git a/examples/zephyr/x86_64-linux-arm-zephyr-eabi-gcc.cmake b/examples/zephyr/x86_64-linux-arm-zephyr-eabi-gcc.cmake index 20c59c2a276..ffee9e9edc4 100644 --- a/examples/zephyr/x86_64-linux-arm-zephyr-eabi-gcc.cmake +++ b/examples/zephyr/x86_64-linux-arm-zephyr-eabi-gcc.cmake @@ -57,12 +57,6 @@ add_compile_definitions("$<$>:NDEBUG>") # Link options add_link_options(-mcpu=${GCC_CPU} -mthumb) -# Zephyr SDK GCC defaults to Picolibc and does not ship GNU Arm's -# nosys.specs/rdimon.specs files. -if(SEMIHOSTING) - add_link_options(-lsemihost) -endif() - # Set floating point unit if(CMAKE_SYSTEM_PROCESSOR MATCHES "\\+fp") set(FLOAT hard) From 7044edcc4c168a26f6775f4670ccfb85dc525469 Mon Sep 17 00:00:00 2001 From: Zingo Andersen Date: Thu, 11 Jun 2026 16:42:29 +0200 Subject: [PATCH 8/9] Zephyr: Add a lot of debuginfo during testing Signed-off-by: Zingo Andersen Change-Id: I6e7f8d3ac08f8e557a131a5371c4b2dcbcda6ce9 --- .ci/scripts/test_zephyr.sh | 96 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/.ci/scripts/test_zephyr.sh b/.ci/scripts/test_zephyr.sh index bdd0069ebe8..9b1eed32d7e 100755 --- a/.ci/scripts/test_zephyr.sh +++ b/.ci/scripts/test_zephyr.sh @@ -185,6 +185,97 @@ run_west_sdk_install_with_proxy_fallback() { run_command_block_from_readme "${ZEPHYR_README_PATH}" "" } +print_tool_details() { + local tool="$1" + local path + + if path="$(command -v "${tool}" 2>/dev/null)"; then + echo "${tool}: ${path}" + file "${path}" || true + "${path}" --version || true + else + echo "${tool}: not found" + fi +} + +print_path_details() { + local label="$1" + local path="$2" + local interpreter + + echo "${label}: ${path}" + if [[ -e "${path}" ]]; then + ls -ld "${path}" || true + file "${path}" || true + interpreter="$(file "${path}" | sed -n 's/.*interpreter \([^,]*\).*/\1/p')" + if [[ -n "${interpreter}" && -x "${interpreter}" ]]; then + echo "${label} dynamic loader: ${interpreter}" + "${interpreter}" --list "${path}" || true + fi + if [[ -x "${path}" ]]; then + "${path}" --version || true + fi + else + echo "${label}: missing" + fi +} + +print_zephyr_diagnostics() { + local sdk_version sdk_dir + + echo "---- Zephyr diagnostics ----" + echo "uname -a: $(uname -a)" + echo "uname -m: $(uname -m)" + echo "PATH: ${PATH}" + echo "LD_LIBRARY_PATH: ${LD_LIBRARY_PATH:-}" + echo "VIRTUAL_ENV: ${VIRTUAL_ENV:-}" + echo "ZEPHYR_PROJ_ROOT: ${ZEPHYR_PROJ_ROOT:-}" + echo "EXECUTORCH_PROJ_ROOT: ${EXECUTORCH_PROJ_ROOT}" + echo "ZEPHYR_SDK_INSTALL_DIR: ${ZEPHYR_SDK_INSTALL_DIR:-}" + echo "ZEPHYR_TOOLCHAIN_VARIANT: ${ZEPHYR_TOOLCHAIN_VARIANT:-}" + echo "ZEPHYR_SDK_RELEASE_PROXY_CACHE_DIR: ${ZEPHYR_SDK_RELEASE_PROXY_CACHE_DIR:-}" + echo "EXECUTORCH_ZEPHYR_DTC: ${EXECUTORCH_ZEPHYR_DTC:-}" + + sdk_version="$(python3 "${EXECUTORCH_PROJ_ROOT}/.ci/docker/common/zephyr_sdk_release_proxy.py" --print-version)" + echo "Zephyr SDK version: ${sdk_version}" + echo "Zephyr SDK release assets for this host:" + python3 - <" + echo "---- ${TARGET} tool diagnostics before README test blocks ----" + print_zephyr_diagnostics + # Run all blocks that match run_target_test_blocks_from_readme "${ZEPHYR_SAMPLES_README_PATH}" "${TARGET}" done From 5180e7e3e10ac9863e6927b099a452048ab0bc24 Mon Sep 17 00:00:00 2001 From: Zingo Andersen Date: Fri, 12 Jun 2026 22:53:07 +0200 Subject: [PATCH 9/9] Zephyr: Avoid host library path when running SDK tools The Zephyr CI image sets LD_LIBRARY_PATH globally to include host system library directories. When Zephyr SDK host tools such as dtc are launched, this can make the SDK dynamic loader resolve libraries from the host instead of the SDK hosttools sysroot. Signed-off-by: Zingo Andersen Change-Id: I036dd0ae732bbfe20c8e6c41831692a3bb7c6f60 --- .github/workflows/trunk.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/trunk.yml b/.github/workflows/trunk.yml index 1b0f608b06b..940e4f899d7 100644 --- a/.github/workflows/trunk.yml +++ b/.github/workflows/trunk.yml @@ -108,6 +108,10 @@ jobs: python3.12 -m venv zephyr_test_venv source zephyr_test_venv/bin/activate + # The Zephyr SDK host tools carry their own runtime. The CI Docker image sets a + # global LD_LIBRARY_PATH for other jobs, which can make SDK tools pick host libs. + unset LD_LIBRARY_PATH + # Test zephyr backend .ci/scripts/test_zephyr.sh \ --targets "${TARGET_LIST:-${{ matrix.target }}}" \