Zephyr - johnosbb/Automation GitHub Wiki

Zephyr

Tutorials

Zephyr ESP32-S3

Getting started

Create a virtual environment in your chosen directory

D:\ESP32Zephyr> python -m venv zephyrproject\.venv
D:\ESP32Zephyr> ls
    Directory: D:\ESP32Zephyr

Activate the environment

PS D:\ESP32Zephyr> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
PS D:\ESP32Zephyr> zephyrproject\.venv\Scripts\Activate.ps1
(.venv) PS D:\ESP32Zephyr>

Install 'west'

pip install west

Initialise the Repo and get the zephyr source code

west init zephyrproject
cd zephyrproject
west update

Now go and make some tea!

We now need to export a Zephyr CMake Package to allow us build the boilerplate code.

west zephyr-export

Install additional Python dependencies

west packages pip --install

Time for more tea!

Install the Zephyr SDK

cd zephyr
# we should now be in D:\ESP32Zephyr\zephyrproject\zephyr
west sdk install

Build for the ESP32-S3-DevKitC-1

Obtain all esp32 blobs:

west blobs fetch hal_espressif

Building Blinky

To build Blinky for the ESP32-s3 Devkit C you will need to modify the device tree to add an overlay for the device tree that defines the onboard led. The ESP32-S3 actually features an RDG led and not a standard onboard led like other Arduino style devices, so for this example we will drive an led on GPIO pin 8.

image

Create a file: esp32s3_devkitc_procpu.overlay in the boards directory. D:\ESP32Zephyr\zephyrproject\zephyr\boards with the content below. Zephyr will automatically apply the overlay that matches the qualified board name.

/ {
    aliases {
        i2c-0 = &i2c0;
        watchdog0 = &wdt0;
        led0 = &onboard_led;
    };

    leds {
        compatible = "gpio-leds";

        onboard_led: led_0 {
            gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
            label = "GPIO LED";
        };
    };
};

A few quick rules of thumb when creating overlays:

  • Use / { ... } when you add or modify things that live under the root (e.g. aliases, chosen, new top-level nodes like leds).
  • Use &some_label { ... } when you want to modify an existing labeled node (e.g. &gpio0, &i2c0).
  • We can have both in the same overlay (as we did): / { aliases { ... }; leds { ... }; }; plus references like gpios = <&gpio0 8 ...>;.
  • Without the / { ... } wrapper, the overlay wouldn’t know where to place aliases (and it would fail to parse or end up in the wrong scope).

We can then build

west build -p always -b esp32s3_devkitc/esp32s3/procpu samples\basic\blinky

Or for a simpler example you could try:

 west build -p always -b esp32s3_devkitc/esp32s3/procpu .\samples\hello_world

But, continuing with blinky for now, lets flash our new image.

Flashing Blinky

Connect the esp32 to your development machine using a USB cable and then confirm the associated Com port in Device Manager.

image

To flash the newly built image we can use. west flash. It will search for connected devices and automatically copy the image to the board.

(.venv) PS D:\ESP32Zephyr\zephyrproject\zephyr>
-- west flash: rebuilding
ninja: no work to do.
-- west flash: using runner esp32
-- runners.esp32: reset after flashing requested
-- runners.esp32: Flashing esp32 chip on None (921600bps)
esptool v5.1.0
Connected to ESP32-S3 on COM11:
Chip type:          ESP32-S3 (QFN56) (revision v0.2)
Features:           Wi-Fi, BT 5 (LE), Dual Core + LP Core, 240MHz, Embedded PSRAM 8MB (AP_3v3)
Crystal frequency:  40MHz
MAC:                d8:3b:da:a4:c5:7c

Stub flasher running.
Changing baud rate to 921600...
Changed.

Configuring flash size...
Flash will be erased from 0x00000000 to 0x00021fff...
Wrote 147456 bytes at 0x00000000 in 1.9 seconds (616.7 kbit/s).
Hash of data verified.

Hard resetting via RTS pin...

Building our own Application

The easiest way to get started with the example-application repository within an existing Zephyr workspace is to build a Workspace Application.

 git clone https://github.com/zephyrproject-rtos/example-application esp32s3_demo

I renamed the provided sample structure as follows:

D:\ESP32Zephyr\zephyrproject\applications\
└── esp32s3_demo/
    β”œβ”€β”€ src/main.c
    β”œβ”€β”€ prj.conf
    β”œβ”€β”€ CMakeLists.txt
    └── boards/esp32s3_devkitc.overlay

esp32s3_demo/CMakeLists.txt: The Build recipe. Finds Zephyr, defines project(app) and adds src/main.c. The Board type is normally selected via west build -b, and not hardcoded into the CMakeLists.txt file..

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

esp32s3_demo/prj.conf: The Default Kconfig for this app. Enables GPIO, logging, blink feature, and sets main stack size.

# esp32s3_demo/prj.conf
CONFIG_BLINK=y
CONFIG_GPIO=y
CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=3
CONFIG_MAIN_STACK_SIZE=4096

esp32s3_demo/src/main.c: This is the App entry. Minimal LED blinker using DT_ALIAS(led0); toggles the pin via gpio_dt_spec.

/*
 * Copyright (c) 2025 John O'Sullivan
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>

/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS   2000

/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led0)

/*
 * A build error on this line means your board is unsupported.
 * See the sample documentation for information on how to fix this.
 */
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);

int main(void)
{
	int ret;
	bool led_state = true;

	if (!gpio_is_ready_dt(&led)) {
		return 0;
	}

	ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
	if (ret < 0) {
		return 0;
	}

	while (1) {
		ret = gpio_pin_toggle_dt(&led);
		if (ret < 0) {
			return 0;
		}

		led_state = !led_state;
		printf("LED state: %s\n", led_state ? "ON" : "OFF");
		k_msleep(SLEEP_TIME_MS);
	}
	return 0;
}

esp32s3_demo/boards/esp32s3_devkitc.overlay: The Devicetree overlay for ESP32-S3 DevKitC. Adds a gpio-leds node and aliases { led0 = &onboard_led; }, wiring the LED used by the app.

/ {
    aliases {
        led0 = &onboard_led;
    };

    leds {
        compatible = "gpio-leds";

        onboard_led: led_0 {
            gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>;
            label = "GPIO-8 LED";
        };
    };
};

esp32s3_demo/Kconfig. This is the App’s Kconfig entry point. Pulls in Kconfig.zephyr, sets up logging template, and defines CONFIG_BLINK under β€œApplication options”.


# Copyright (c) 2021 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
#
# This file is the application Kconfig entry point. All application Kconfig
# options can be defined here or included via other application Kconfig files.
# You can browse these options using the west targets menuconfig (terminal) or
# guiconfig (GUI).

menu "Zephyr"
source "Kconfig.zephyr"
endmenu

module = APP
module-str = APP
source "subsys/logging/Kconfig.template.log_config"


# New: application-specific options
menu "Application options"
config BLINK
    bool "Enable blink logic"
    default y
    help
      Enable the LED blink loop in the application.
endmenu

Build the application (Note: we will be running our commands from D:\ESP32Zephyr\zephyrproject\applications>)

Remove-Item -Recurse -Force build\esp32s3_demo -ErrorAction SilentlyContinue

west build -p always `
  -b esp32s3_devkitc/esp32s3/procpu `
  -d build\esp32s3_demo `
  esp32s3_demo `
  -- `
  "-DDTC_OVERLAY_FILE=boards/esp32s3_devkitc.overlay"

Use "monitor" to view the serial output. Use "Ctrl + [" to exit.

west espressif monitor 

Also Noteworthy

  • esp32s3_demo/sample.yaml:1 β€” Twister/CI metadata for building/testing the sample; defines variants and an optional debug build overlay.
  • esp32s3_demo/debug.conf:1 β€” Kconfig overlay to enable debug-friendly options (e.g., CONFIG_DEBUG_OPTIMIZATIONS and verbose app logging). Use via -DOVERLAY_CONFIG=debug.conf.
  • esp32s3_demo/VERSION:1 β€” Application version file (major/minor/patch). Used to set project/app version metadata during the build.
  • esp32s3_demo/zephyr/module.yml:1 β€” Module descriptor for this repo context when used as a Zephyr module. Points board_root/dts_root to the repo so custom boards/bindings are discoverable and registers a custom runner script.

The relationship between prj.conf and kconfig

When you run west build, CMake runs the Zephyr Kconfig system (same as Linux’s menuconfig). Zephyr reads aAll upstream Kconfig files from the kernel, subsystems, and drivers. The app’s own Kconfig (if present) and the app’s prj.conf and then merges everything into a single generated configuration: build/zephyr/.config. That file is the final resolved configuration used to compile the app. During the build, Zephyr generates: build/zephyr/include/generated/autoconf.h

Note: only Kconfig files can define new symbols.

Installing OpenOCD

Copy the unzipped folder to Program Files

C:\Program Files\xpack-openocd-0.12.0-7

Add this to our path

image

Go to zadig

Select the option for USB JTAG/serial debug uint (interface 2) - you will need to downgrade to WinUSB V6.1.xxxxx

image

After install we should see a new serial port under com ports and under Universal Serial Bus Devices we should see a JTAG option.

image

Check that we have no errors

image

Then try and run the service (if you get a port conflict then change the port)

openocd -f board/esp32s3-builtin.cfg -c "tcl port 6667"

You should see

xPack Open On-Chip Debugger 0.12.0+dev-02228-ge5888bda3-dirty (2025-10-04-22:44)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : esp_usb_jtag: VID set to 0x303a and PID to 0x1001
Info : esp_usb_jtag: capabilities descriptor set to 0x2000
Info : [esp32s3.cpu0] Hardware thread awareness created
Info : [esp32s3.cpu1] Hardware thread awareness created
force hard breakpoints
adapter speed: 40000 kHz
Info : Listening on port 6667 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : esp_usb_jtag: Device found. Base speed 40000KHz, div range 1 to 255
Info : clock speed 40000 kHz
Warn : DEPRECATED: auto-selecting transport "jtag". Use 'transport select jtag' to suppress this message.
Info : JTAG tap: esp32s3.cpu0 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1)
Info : JTAG tap: esp32s3.cpu1 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1)
Info : [esp32s3.cpu0] Examination succeed
Info : [esp32s3.cpu1] Examination succeed
Info : [esp32s3.cpu0] starting gdb server on 3333
Info : Listening on port 3333 for gdb connections
Info : [esp32s3.cpu0] Debug controller was reset.
Info : [esp32s3.cpu0] Core was reset.
Info : [esp32s3.cpu1] Debug controller was reset.
Info : [esp32s3.cpu1] Core was reset.

I had installed my SDK here

c:/users/johno/zephyr-sdk-0.17.4/xtensa-espressif_esp32s3_zephyr-elf

My gdb is located here

c:/users/johno/zephyr-sdk-0.17.4/xtensa-espressif_esp32s3_zephyr-elf/bin/xtensa-espressif_esp32s3_zephyr-elf-gdb.exe

We can invoke with

c:/users/johno/zephyr-sdk-0.17.4/xtensa-espressif_esp32s3_zephyr-elf/bin/xtensa-espressif_esp32s3_zephyr-elf-gdb.exe .\build\esp32s3_demo_advanced\zephyr\zephyr.elf

Then in the gdb console

target extended-remote localhost:3333

We should see something like

(gdb) target extended-remote localhost:3333
Remote debugging using localhost:3333
warning: multi-threaded target stopped without sending a thread-id, using first non-exited thread
0x40376f28 in arch_cpu_idle () at D:/ESP32Zephyr/zephyrproject/zephyr/arch/xtensa/core/cpu_idle.c:14
14      }

And in the OCD console

Info : accepting 'gdb' connection on tcp/3333
Info : Set GDB target to 'esp32s3.cpu0'
Info : New GDB Connection: 1, Target esp32s3.cpu0, state: halted

We can monitor serial output and debug with just a single cable. The cable should be plugged into the JTAG port and we can than adjust our device tree overlay to direct serial output to USB Serial/JTAG by adding the section below:

/ {
    chosen {
        zephyr,console = &usb_serial;
        zephyr,shell-uart = &usb_serial;
    };
};

&usb_serial {
    status = "okay";
};

Integrating with VSCode

{
    "configurations": [
        {
            "name": "Debug ESP32-S3",
            "type": "cppdbg",
            "request": "launch",
            "program": "${input:elfPath}",
            "args": [],
            "stopAtEntry": true,
            "cwd":  "${workspaceFolder}",
            "MIMode": "gdb",
            "miDebuggerPath": "c:/users/johno/zephyr-sdk-0.17.4/xtensa-espressif_esp32s3_zephyr-elf/bin/xtensa-espressif_esp32s3_zephyr-elf-gdb.exe",
            "miDebuggerServerAddress": "localhost:3333",
            "setupCommands": [
                {
                    "description": "Pretty print for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        }
    ],
    "inputs": [
        {
            "id": "elfPath",
            "type": "promptString",
            "description": "Enter the path to the ELF file",
        }
    ]
}

EdgeImpulse

Create a new project on Edge Impulse.

Install the edge impulse cli

npm install -g edge-impulse-cli

https://studio.edgeimpulse.com/studio/821779

Our program should now output

9345,19.274814,67.552291
9454,19.274814,67.523681
9564,19.264133,67.548477
9673,19.253452,67.519866
9782,19.266803,67.502700
9892,19.266803,67.558013
10001,19.258793,67.527496
10111,19.266803,67.542755
10220,19.250782,67.542755
PS C:\Users\johno> edge-impulse-data-forwarder
Edge Impulse data forwarder v1.35.1
Endpoints:
    Websocket: wss://remote-mgmt.edgeimpulse.com
    API:       https://studio.edgeimpulse.com
    Ingestion: https://ingestion.edgeimpulse.com

[SER] Connecting to COM12
[SER] Serial is connected (D8::3:B::DA::A:4::C5::7:C)
[WS ] Connecting to wss://remote-mgmt.edgeimpulse.com
[WS ] Connected to wss://remote-mgmt.edgeimpulse.com

? To which project do you want to connect this device? (πŸ” type to search) 821779
[SER] Detecting data frequency...
[SER] Detected data frequency: 10Hz
? 3 sensor axes detected (example values: [518055,19.477759,67.353927]). What do you want to call them? Separate the nam
es with ',': TimeMS,Temperature,Humidity
? What name do you want to give this device? ESP32S3_Monitor
[WS ] Device "ESP32S3_Monitor" is now connected to project "TempHumidityESP32S3". To connect to another project, run `edge-impulse-data-forwarder --clean`.
[WS ] Go to https://studio.edgeimpulse.com/studio/821779/acquisition/training to build your machine learning model!

Edge Impulse Dashboard

Options for a Captured Sample

image

Capturing Samples

image

Graphical view of data

image
⚠️ **GitHub.com Fallback** ⚠️