This is for folks interested in learning about Zephyr. The first section shows, step by step, how to work through the Zephyr Getting Started Guide to install Zephyr on Linux, build the hello world sample, and run it on an Adafruit QT Py ESP32-S3. The second part has notes for tuning the default settings to use fewer resources for faster CI builds.
What are Zephyr and West?
The Zephyr Real Time Operating System (RTOS) provides an abstraction layer that helps make it easier to port applications like CircuitPython to boards from various manufacturers.
In theory, using an RTOS makes it easier to implement features using audio synthesis, graphic displays, HTTPS, MQTT, BLE, etc. By building on top of Zephyr APIs, rather than vendor-specific SDK APIs, application code can ignore some of the differences between microcontroller families. Zephyr helps with low-level hardware details and coordinating CPU time for concurrent tasks including application logic, hardware IO, network stacks, and number crunching.
Zephyr has a command line tool calledΒ west to manage and coordinate the many tasks involved in working on a Zephyr project. Once you install west, you can do west help to see documentation on the available sub-commands.
Differences from Official Getting Started Guide
- The official Zephyr Getting Started GuideΒ describes a lot of options, sidebars, and choices to make. Also, it suggests using west commands with defaults that use a lot of bandwidth and disk space.
- This guide focuses on the linear, step by step procedure to install Zephyr efficiently on Debian 12 (Bookworm) and build firmware for an Adafruit QT Py ESP32-S3. This procedure will probably also work on Ubuntu 22 LTS or 24 LTS.
- This guide assumes you are already familiar with using a Linux command line shell to install packages and work with Python virtual environments.
- This guide includes notes on reducing resource use when usingΒ
west init,west update, andwest sdk install. I expect these notes might help people who want to write GitHub CI actions to build firmware with Zephyr.
Install Debian 12 Distro Packages
These instructions should work to install package dependencies on Debian 12. If you want to use a different OS, you might check the official getting started guide for notes on minimum required versions of Python, CMake, etc.
Debian shell commands to install package dependencies:
sudo apt update sudo apt upgrade sudo apt install git cmake make ninja-build gperf ccache dfu-util \ Β device-tree-compiler wget xz-utils file openocd \ Β python3-dev python3-pip python3-setuptools python3-tk python3-wheel \ Β python3-venv gcc gcc-multilib g++-multilib libsdl2-dev libmagic1
This is similar to the official guide, but I've added options to limit the depth of git clone. Using limited depth cloning saves bandwidth, time, and disk space.
Debian shell commands to create a top-level workspace directory called zephyr-workspaceΒ and install west in a Python virtual environment:
cd ~/code # or whatever directory you want to use python3 -m venv zephyr-workspace/.venv source zephyr-workspace/.venv/bin/activate pip install west cd zephyr-workspace west init -o=--depth=1 west update -o=--depth=500 west zephyr-export west packages pip --install
The official guide suggests usingΒ west sdk install with no options. But, that takes 9 GB of disk space. I've added options here to only install the toolchains for ESP32-S3 and ARM, which cover many of Adafruit's boards.
Debian shell commands to create a top-level workspace directory called zephyr-workspaceΒ and install west in a Python virtual environment:
cd ~/code/zephyr-workspace/zephyr west sdk install --no-toolchains west sdk install --toolchains xtensa-espressif_esp32s3_zephyr-elf west sdk install --toolchains arm-zephyr-eabi
Doing it this way uses about 1.7 GB forΒ ~/zephyr-sdk-0.17.0 (instead of 9 GB).
Build and Run Hello World
This builds one of the sample projects from the zephyr repo for Adafruit QT Py ESP32-S3 with 8MB Flash and no PSRAM.
For specifying the board variant and CPU qualifiers, check the documentation at the Zephyr board page for QT Py ESP32-S3:
- 8MB flash / No PSRAM:Β
-b adafruit_qt_py_esp32s3/esp32s3/procpu - 4MB flash / 2MB PSRAM:
-b adafruit_qt_py_esp32s3@psram/esp32s3/procpu
Debian shell commands to build firmware (assumes venv is already active):
cd ~/code/zephyr-workspace/zephyr west blobs fetch hal_espressif # only need to run fetch once west build -p always -b adafruit_qt_py_esp32s3/esp32s3/procpu samples/hello_world
To flash the firmware:
- Hold BOOT button on QT Py ESP32-S3
- Press and release RESET button while still holding BOOT down
- Release BOOT button
- RunΒ
west flash, wait for it to finish - Reset board or power cycle it by unplugging the USB cable
To see output:
- RunΒ
west espressif monitorΒ (Ctrl+] to exit monitor)
Hello World Sample Output
This is what I got fromΒ west espressif monitor:
(.venv) $ west espressif monitor Serial port /dev/ttyACM0 Connecting... Detecting chip type... ESP32-S3 --- idf_monitor on /dev/ttyACM0 115200 --- --- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- ESP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0x15 (USB_UART_CHIP_RESET),boot:0x8 (SPI_FAST_FLASH_BOOT) Saved PC:0x400490cc SPIWP:0xee mode:DIO, clock div:2 load:0x3fc8d5a0,len:0x1798 load:0x40374000,len:0x9580 0x40374000: _WindowOverflow4 at /home/sam/code/zephyr-workspace/zephyr/arch/xtensa/core/window_vectors.S:56 SHA-256 comparison failed: Calculated: d8bf627803a97d93b575d89be58fe15d03159cb115a83c18972a42e6d1c1cbc1 Expected: 00000000a0520000000000000000000000000000000000000000000000000000 Attempting to boot anyway... entry 0x403778f8 0x403778f8: __start at /home/sam/code/zephyr-workspace/zephyr/soc/espressif/common/loader.c:253 I (64) soc_init: ESP Simple boot I (64) soc_init: compile time Jan 12 2025 01:58:38 W (64) soc_init: Unicore bootloader I (65) spi_flash: detected chip: gd I (67) spi_flash: flash io: dio W (70) spi_flash: Detected size(8192k) larger than the size in the binary image header(2048k). Using the size in the binary image header. I (82) soc_init: chip revision: v0.2 I (85) flash_init: Boot SPI Speed : 40MHz I (89) flash_init: SPI Mode : DIO I (92) flash_init: SPI Flash Size : 8MB I (96) soc_random: Enabling RNG early entropy source I (101) boot: DRAM: lma 0x00000020 vma 0x3fc8d5a0 len 0x1798 (6040) I (107) boot: IRAM: lma 0x000017c0 vma 0x40374000 len 0x9580 (38272) 0x40374000: _WindowOverflow4 at /home/sam/code/zephyr-workspace/zephyr/arch/xtensa/core/window_vectors.S:56 I (113) boot: IRAM: lma 0x0000ad58 vma 0x00000000 len 0x52a0 (21152) I (119) boot: IMAP: lma 0x00010000 vma 0x42000000 len 0x3a9c (15004) 0x42000000: _stext at ??:? I (125) boot: IRAM: lma 0x00013aa4 vma 0x00000000 len 0xc554 (50516) I (132) boot: DMAP: lma 0x00020000 vma 0x3c010000 len 0x1110 (4368) I (138) boot: Image with 6 segments I (141) boot: DROM segment: paddr=00020000h, vaddr=3c010000h, size=01110h ( 4368) map I (149) boot: IROM segment: paddr=00010000h, vaddr=42000000h, size=03A9Ah ( 15002) map I (168) soc_random: Disabling RNG early entropy source I (168) boot: Disabling glitch detection I (168) boot: Jumping to the main image... I (193) heap_runtime: ESP heap runtime init at 0x3fc915d8 size 352 kB. *** Booting Zephyr OS build 99a63a776980 *** Hello World! adafruit_qt_py_esp32s3/esp32s3/procpu
The hello world code that generated the message is on github at:
Β zephyrproject-rtos/zephyr/samples/hello_world/src/main.c
Β
CI Notes
This section might be useful for people who want to write CI actions to build CircuitPython on Zephyr.
The full Zephyr install with all the hardware libraries and compilers is about 15 GB. But, you can customize the defaults to use fewer resources.
Optimizing west init and west update
The west init command sets up a Zephyr workspace according to options given in a manifest file. The default manifest file comes from https://github.com/zephyrproject-rtos/zephyr, and it includes a lot of stuff for many different hardware platforms.
For building CI systems using west, you may want to consider using options to limit the git clone depth and to specify a custom manifest file. For details, seeΒ west help init and west help update.
When I ran west init with the default options, it cloned a new zephyr repo under the top-level workspace directory, downloading about 690 MB, which expanded to about 1.1 GB on disk.
UsingΒ west init -o=--depth=1Β to limit the clone depth cut the download to 87 MiB, which expand to 452 MB on disk.
When I ran west update it cloned many git repositories into the bootloader, tools, and modules directories under the top-level workspace directory. The total disk space using default options was about 5 GB.
When I switched to usingΒ west update -o=--depth=500 to limit the clone depth, it cut the disk space down to about 4.6 GB. It would probably be possible to save more bandwidth and disk space with a custom manifest file that omits unnecessary hal repos.
west update causes errors. My guess is that the errors probably have to do with pinned dependencies that want specific commit hashes which are behind the HEAD of certain repos.
These are the new directories created in the workspace by west update:
(.venv) $ du -sh *
15M bootloader
4.6G modules
20M tools
452M zephyr
(.venv) $ tree -L 1 bootloader/ tools/; tree -L 2 modules/
bootloader/
βββ mcuboot
tools/
βββ edtt
βββ net-tools
5 directories, 0 files
modules/
βββ bsim_hw_models
βΒ Β βββ nrf_hw_models
βββ crypto
βΒ Β βββ mbedtls
βΒ Β βββ tinycrypt
βββ debug
βΒ Β βββ mipi-sys-t
βΒ Β βββ percepio
βΒ Β βββ segger
βββ fs
βΒ Β βββ fatfs
βΒ Β βββ littlefs
βββ hal
βΒ Β βββ adi
βΒ Β βββ altera
βΒ Β βββ ambiq
βΒ Β βββ atmel
βΒ Β βββ cmsis
βΒ Β βββ espressif
βΒ Β βββ ethos_u
βΒ Β βββ gigadevice
βΒ Β βββ infineon
βΒ Β βββ intel
βΒ Β βββ libmetal
βΒ Β βββ microchip
βΒ Β βββ nordic
βΒ Β βββ nuvoton
βΒ Β βββ nxp
βΒ Β βββ openisa
βΒ Β βββ quicklogic
βΒ Β βββ renesas
βΒ Β βββ rpi_pico
βΒ Β βββ silabs
βΒ Β βββ st
βΒ Β βββ stm32
βΒ Β βββ tdk
βΒ Β βββ telink
βΒ Β βββ ti
βΒ Β βββ wch
βΒ Β βββ wurthelektronik
βΒ Β βββ xtensa
βββ lib
βΒ Β βββ acpica
βΒ Β βββ cmsis_6
βΒ Β βββ cmsis-dsp
βΒ Β βββ cmsis-nn
βΒ Β βββ gui
βΒ Β βββ hostap
βΒ Β βββ liblc3
βΒ Β βββ loramac-node
βΒ Β βββ nrf_wifi
βΒ Β βββ open-amp
βΒ Β βββ openthread
βΒ Β βββ picolibc
βΒ Β βββ uoscore-uedhoc
βΒ Β βββ zcbor
βββ tee
βββ tf-a
βββ tf-m
60 directories, 0 files
Optimizing west sdk install
When I ranΒ west sdk install with the default options, it installed 9 GB of toolchain files in ~/zephyr-sdk-0.17.0.
This is the disk usage that resulted from the default west sdk install:
(.venv) $ cd ~/zephyr-sdk-0.17.0/ (.venv) $ du -sh . 9.0G . (.venv) $ du -sh * 259M aarch64-zephyr-elf 304M arc64-zephyr-elf 660M arc-zephyr-elf 1.1G arm-zephyr-eabi 36K cmake 4.0K environment-setup-x86_64-pokysdk-linux 330M microblazeel-zephyr-elf 322M mips-zephyr-elf 330M nios2-zephyr-elf 976M riscv64-zephyr-elf 4.0K sdk_toolchains 4.0K sdk_version 8.0K setup.sh 428M sparc-zephyr-elf 431M sysroots 4.0K version-x86_64-pokysdk-linux 310M x86_64-zephyr-elf 239M xtensa-amd_acp_6_0_adsp_zephyr-elf 195M xtensa-dc233c_zephyr-elf 197M xtensa-espressif_esp32s2_zephyr-elf 202M xtensa-espressif_esp32s3_zephyr-elf 198M xtensa-espressif_esp32_zephyr-elf 214M xtensa-intel_ace15_mtpm_zephyr-elf 215M xtensa-intel_ace30_ptl_zephyr-elf 205M xtensa-intel_tgl_adsp_zephyr-elf 215M xtensa-mtk_mt8195_adsp_zephyr-elf 214M xtensa-nxp_imx8m_adsp_zephyr-elf 216M xtensa-nxp_imx8ulp_adsp_zephyr-elf 214M xtensa-nxp_imx_adsp_zephyr-elf 205M xtensa-nxp_rt500_adsp_zephyr-elf 216M xtensa-nxp_rt600_adsp_zephyr-elf 204M xtensa-nxp_rt700_hifi1_zephyr-elf 216M xtensa-nxp_rt700_hifi4_zephyr-elf 194M xtensa-sample_controller32_zephyr-elf 194M xtensa-sample_controller_zephyr-elf 43M zephyr-sdk-x86_64-hosttools-standalone-0.9.sh
Instead of using the default sdk install, you can save bandwidth, download time, decompression time, and disk space by installing specific toolchains.
To install one or more specific toolchains, do:
west sdk install --toolchains LIST_OF_TOOLCHAIN_NAMES
To see the available toolchain names, look at the GitHub zephyrproject-rtos/sdk-ng repository releases page. For example, the current stable Zephyr SDK 0.17.0 release includes toolchainsΒ xtensa-espressif_esp32s3_zephyr-elf, arm-zephyr-eabi, etc.
Β
The command line help system forΒ west sdkΒ acts a bit strange:
- [update 2/3/2025: this has been fixed] The implementation of
west sdkcomes from code in thezephyrrepository which is auto-detected by west (seezephyr/scripts/west-commands.yml) . If your working directory is somewhere outside ofΒ~/code/zephyr-workspace/zephyr, thenΒwest help sdkandwest sdk install --helpΒ won't work. - The sdk help commands may trigger an error message if you try to use them before you've installed either the "full" or the "minimal" sdk.
To avoid hassles, you can just read the source code for the help messages atΒ zephyr/scripts/west_commands/sdk.py. Or, to get the command line help working before you've installed any toolchains, you can install the minimal SDK with:
west sdk install --no-toolchains
After the minimal SDK is installed, you can use these to read command line options documentation:
west sdk --helpwest sdk install --help
This page (Getting Started with Zephyr on Linux) was last updated on February 03, 2025.
Text editor powered by tinymce.