Lab 11. Zephyr RTOS

This tutorial walks you through:

  1. setting up a fresh Zephyr development environment (“from scratch”) on a computer
  2. building Zephyr’s hello_world sample for an ESP32‑C6 target
  3. flashing it onto the Sparrow node
  4. seeing the “Hello World” log over the USB connection

1. Install Zephyr “from scratch” on your computer

Zephyr’s official Getting Started Guide is the source of truth for host setup (Ubuntu/macOS/Windows), Python environment, west, and SDK installation. Reference: https://docs.zephyrproject.org/latest/develop/getting_started/index.html

Below is a practical “do this in order” setup that follows that guide.

1.1 Install OS dependencies

Follow the Install dependencies step for your OS in Zephyr’s Getting Started Guide (Ubuntu/macOS/Windows). Guide: https://docs.zephyrproject.org/latest/develop/getting_started/index.html

Typical things you’ll need include: Python 3, CMake, Ninja, Git, and system build tools.

1.2 Create a Zephyr workspace and Python virtual environment

Pick a workspace folder. In this tutorial I’ll use ~/zephyrproject on Linux/macOS. (Windows users can use something like C:\zephyrproject.)

# Linux/macOS
mkdir -p ~/zephyrproject
cd ~/zephyrproject
 
python3 -m venv .venv
source .venv/bin/activate

On Windows PowerShell (example):

mkdir C:\zephyrproject
cd C:\zephyrproject
 
py -m venv .venv
.\.venv\Scripts\Activate.ps1

1.3 Install west

Zephyr’s official west install guide: https://docs.zephyrproject.org/latest/develop/west/install.html

pip install -U west

1.4 Initialize and update the Zephyr workspace

# Still inside ~/zephyrproject (or your chosen folder)
west init -m https://github.com/zephyrproject-rtos/zephyr --mr main
west update

Export Zephyr’s CMake package (so CMake can find Zephyr):

west zephyr-export

Install Python requirements for Zephyr and its modules:

west packages pip --install

(That exact command appears in the Getting Started flow and is commonly the next step after west update.)

1.5 Install the Zephyr SDK (toolchain)

Zephyr SDK documentation: https://docs.zephyrproject.org/latest/develop/toolchains/zephyr_sdk.html

Install the Zephyr SDK for your OS, then ensure your environment can find it (either via the SDK setup script registering it, or via environment variables like ZEPHYR_SDK_INSTALL_DIR / ZEPHYR_TOOLCHAIN_VARIANT=zephyr).

Note: ESP32‑C6 is RISC‑V based, so you’ll need the RISC‑V toolchain that’s included with the Zephyr SDK.

2. ESP32 (Espressif) prerequisites inside Zephyr

2.1 Fetch Espressif RF binary blobs

Zephyr’s Espressif HAL requires binary blobs (RF calibration, etc.). Zephyr board docs for Espressif boards call this out and recommend fetching after west update. Example (ESP32 DevKitC doc): it explicitly instructs west blobs fetch hal_espressif.

Run:

# From your workspace root (~/zephyrproject)
west blobs fetch hal_espressif

If you skip this, you may see build or runtime failures for ESP32 targets.

3. Pick a Zephyr “board target” for Sparrow

Sparrow is not (yet) an upstream Zephyr board, so we need a compatible Zephyr board definition to build/flash a first image.

You have two reasonable approaches:

  1. A. Quick path (recommended for Hello World): use an upstream ESP32‑C6 board definition that is already 4 MB flash and uses USB‑C programming.
  2. B. Proper port: create a custom “out‑of‑tree” Zephyr board for Sparrow (best long‑term, required once you use GPIOs/peripherals and want correct pin mapping).

This tutorial focuses on A to get you a successful first boot quickly, and then outlines B.

3.1 Approach A: Use ''xiao_esp32c6'' as a close match

Zephyr includes the Seeed Studio XIAO ESP32C6 board, which is explicitly documented as an ESP32‑C6 board with 4MB of flash and a USB‑C port for programming/debugging. Board doc: https://docs.zephyrproject.org/latest/boards/seeed/xiao_esp32c6/doc/index.html

Important: this board has two cores (HP + LP). A Zephyr issue notes you must specify the core qualifier, e.g.:

  • xiao_esp32c6/esp32c6/hpcore (High‑Performance core)
  • xiao_esp32c6/esp32c6/lpcore (Low‑Power core)

Source: Zephyr issue describing valid targets for xiao_esp32c6.

For “Hello World”, use HP core.

Why this is good for Sparrow:

  • It’s ESP32‑C6, like Sparrow.
  • It’s 4 MB flash, like Sparrow (per your note and XIAO docs).
  • It typically expects USB‑based programming/console (closer to your Sparrow USB setup than DevKitC’s “USB‑UART adapter” style).

Limitations:

  • Pin mapping (LED, I2C, etc.) won’t match Sparrow.
  • For hello_world, pin mapping doesn’t matter.

3.2 Approach A alternate: Use ''esp32c6_devkitc'' + force 4MB flash

Zephyr’s ESP32‑C6‑DevKitC documentation states the module has 8 MB flash. Doc: https://docs.zephyrproject.org/latest/boards/espressif/esp32c6_devkitc/doc/index.html

If you build with that board unmodified, you risk generating a partition layout that assumes 8 MB.

Zephyr supports applying build “snippets” to override common settings. Snippets can be applied with the -S option to west build. Docs: https://docs.zephyrproject.org/latest/build/snippets/using.html

Many Espressif boards support snippet variants like flash-4M / flash-8M (the XIAO ESP32C6 page lists these variants). So you *can* build with DevKitC + -S flash-4M — but for Sparrow, using a 4 MB native board definition (XIAO) is usually cleaner.

4. Build “Hello World” for Sparrow and route console over USB

This section is where the Sparrow‑specific “special care” matters:

  • ensure 4 MB flash
  • ensure console output goes over the USB Serial/JTAG port (not UART0)

We will:

1. create a small application folder
2. add a devicetree overlay that selects the USB serial device for console
3. build and flash

4.1 Create a tiny application directory

From your Zephyr workspace root:

cd ~/zephyrproject
 
mkdir -p sparrow_hello
cd sparrow_hello

Create these files:

  • CMakeLists.txt
  • prj.conf
  • src/main.c
  • a board overlay file under boards/

You can copy the sample hello_world, but I recommend creating a tiny app so you fully control the console configuration.

CMakeLists.txt

cmake_minimum_required(VERSION 3.20.0)
 
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(sparrow_hello)
 
target_sources(app PRIVATE src/main.c)

src/main.c

#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
 
int main(void)
{
    printk("Hello World from Sparrow (ESP32-C6)!\n");
    while (1) {
        k_sleep(K_SECONDS(1));
    }
    return 0;
}

prj.conf (minimal logging/console)

# Serial/console
CONFIG_SERIAL=y
CONFIG_CONSOLE=y
CONFIG_PRINTK=y
CONFIG_UART_CONSOLE=y
 
# Useful for seeing logs immediately
CONFIG_LOG=y
CONFIG_LOG_MODE_IMMEDIATE=y

4.2 Devicetree overlay: force console to USB Serial/JTAG

On ESP32 chips with a USB Serial/JTAG device exposed to Zephyr as a UART, you can route the console by changing the devicetree chosen nodes.

A Zephyr issue discussing USB serial output on ESP32 shows an overlay pattern like:

  • set zephyr,console to &usb_serial
  • enable the usb_serial node

(See Zephyr issue #60825 about using usb_serial for console on ESP32-class devices.)

Create the overlay directory:

mkdir -p boards

Because the board target includes qualifiers, Zephyr looks for overlay filenames like:

  • boards/xiao_esp32c6_esp32c6_hpcore.overlay

Create:

boards/xiao_esp32c6_esp32c6_hpcore.overlay

/ {
    chosen {
        zephyr,console = &usb_serial;
        zephyr,shell-uart = &usb_serial;
        zephyr,uart-mcumgr = &usb_serial;
    };
};
 
&usb_serial {
    status = "okay";
};

Why this matters for Sparrow:

  • DevKit‑style ESP32 boards often default the console to UART0 (meant for an external USB‑UART bridge).
  • Sparrow uses USB Serial/JTAG over the USB connector, so the console needs to be routed there.

ESP32‑C6’s USB Serial/JTAG is implemented entirely in hardware (fixed‑function serial+JTAG). (Espressif docs: USB Serial/JTAG controller for ESP32‑C6.)

4.3 Build the application (HP core)

Activate your Python venv first if it isn’t active:

cd ~/zephyrproject
source .venv/bin/activate

Then build:

# Build into a local build folder:
west build -b xiao_esp32c6/esp32c6/hpcore -d build_sparrow .

If you get an error about “Board qualifiers not found”, ensure you used the full target name including /esp32c6/hpcore. (See the Zephyr issue listing valid xiao_esp32c6 targets.)

4.4 Flash Sparrow over USB

Connect Sparrow over USB‑C.

Then flash:

west flash -d build_sparrow --runner esp32

If west flash doesn’t pick the correct port automatically, the ESP32 west runner supports options including –esp-device (serial port), –esp-baud-rate, and –esp-flash-size. A Zephyr ESP32 runner option list (mirrored documentation) shows:

  • –esp-device ESP_DEVICE (serial port to flash; default uses $ESPTOOL_PORT or auto‑scan)
  • –esp-baud-rate
  • –esp-flash-size (default “detect”)

Example (Linux):

west flash -d build_sparrow --runner esp32 -- --esp-device /dev/ttyACM0

Example (Windows):

west flash -d build_sparrow --runner esp32 -- --esp-device COM7

Port naming tip (Sparrow’s USB vs DevKitC USB‑UART):

  • Native USB Serial/JTAG devices commonly appear as /dev/ttyACM* on Linux.
  • Boards using a USB‑UART bridge chip often appear as /dev/ttyUSB* on Linux.

Sparrow uses the native USB mapping (per your note), so expect ttyACM rather than ttyUSB on Linux.

If flashing fails with “could not connect”, try:

  • a different USB cable/port
  • pressing BOOT while resetting (if your Sparrow hardware revision requires it)
  • lowering baud rate: –esp-baud-rate 115200

4.5 View “Hello World” output

You have two common options:

  • Use Zephyr’s Espressif monitor extension: many Espressif board docs recommend west espressif monitor.
  • Use a normal serial terminal: screen, minicom, PuTTY, etc.

Example with west:

west espressif monitor -d build_sparrow

If you need to choose the port explicitly, note that older Zephyr tooling discussions show the monitor supports a -p (port) style option; if your environment doesn’t, use a standard serial terminal as a fallback.

Fallback example (Linux):

screen /dev/ttyACM0 115200

If everything is wired correctly, you should see:

Hello World from Sparrow (ESP32-C6)!

5. Ensuring the 4 MB flash layout is correct

If you used xiao_esp32c6, you’re already matching a documented 4MB ESP32‑C6 board. (Zephyr XIAO ESP32C6 board doc.)

If you instead build with an ESP32‑C6 board definition that assumes 8 MB (like DevKitC), use a flash size snippet.

Zephyr’s snippet system is applied with west build -S <snippet>. Docs: https://docs.zephyrproject.org/latest/build/snippets/using.html

Example (conceptual):

west build -b esp32c6_devkitc/esp32c6/hpcore -S flash-4M samples/hello_world

The XIAO ESP32C6 board documentation lists snippet variants like flash-4M / flash-8M / flash-16M / flash-32M / flash-64M. Use the one that matches your module. (Zephyr XIAO ESP32C6 board doc.)

6. “Proper” Sparrow support (out-of-tree board)

Once you move beyond hello_world (I2C sensors, neopixel, display, external SPI flash, etc.), you should create a Sparrow Zephyr board definition.

High-level steps:

1. Create an out‑of‑tree board folder, e.g.:
   * ''<your_workspace>/modules/your_sparrow_board/boards/espressif/esp32c6_sparrow/''
2. Start from a close upstream template:
   * ''boards/seeed/xiao_esp32c6'' (4MB, USB‑C)
   * or ''boards/espressif/esp32c6_devkitc'' (upstream Espressif board)
3. Update the board devicetree:
   * set correct GPIOs for I2C (SDA/SCL), neopixel pin, SPI chip selects, etc.
   * include external SPI NOR flash on the pins listed in the Sparrow README (FLASH_CS GPIO23, MOSI GPIO7, MISO GPIO2, SCK GPIO6, etc.)
4. Keep the console routed to USB Serial/JTAG (as shown in the overlay earlier) if Sparrow has no USB‑UART bridge.
5. Add/adjust partitioning for **4 MB** internal flash (and optionally define external flash partitions for storage).

Sparrow’s README lists the peripheral pin mapping (I2C on GPIO21/22, neopixel on GPIO3, shared SPI bus pins, etc.). Source: https://github.com/FarhadGUL06/esp32-c6-sparrow

When your out‑of‑tree board is ready, you can build with:

west build -b esp32c6_sparrow .

(How you register out‑of‑tree boards depends on whether you keep them in your application tree, a module, or a separate repo; Zephyr’s “Modules” documentation explains module discovery and board discovery concepts.)

7. Troubleshooting checklist

7.1 “esptool.py not found”

If west flash complains about missing esptool.py, it usually means your Espressif HAL/tools were not fully fetched or your environment is inconsistent.

Double-check:

  • you ran west update
  • you ran west blobs fetch hal_espressif (and didn’t ignore errors)
  • your Python venv is activated and has Zephyr requirements installed (west packages pip –install)

There are Zephyr discussions where users hit “esptool.py not found” when their module/tools were missing. (Search for that message if you encounter it.)

7.2 Wrong serial port

Symptoms:

  • flashing fails (can’t connect)
  • monitor shows nothing
  • output only appears on a different port

Actions:

  • On Linux, check which device was created when you plug Sparrow in:
    dmesg | tail -n 50
    ls -l /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
 
  • Try explicit flashing port:
    west flash -d build_sparrow --runner esp32 -- --esp-device /dev/ttyACM0
 
  • Ensure your overlay routes the console to &usb_serial.

7.3 No console output after flashing

Common causes:

  • console is still mapped to UART0 (overlay missing or wrong filename)
  • monitor is connected to the wrong port
  • you built for LP core instead of HP core

Fixes:

  • verify the overlay filename matches your board target (slashes become underscores):
    • xiao_esp32c6/esp32c6/hpcoreboards/xiao_esp32c6_esp32c6_hpcore.overlay
  • rebuild from scratch:
    west build -p always -b xiao_esp32c6/esp32c6/hpcore -d build_sparrow .
 

8. References (primary docs)

iothings/laboratoare/2025/lab11.txt · Last modified: 2025/12/13 15:29 by dan.tudose
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0