Zephyr - johnosbb/Automation GitHub Wiki
- Zephyr on the ESP32
- Zephyr Using NXP MCUXpresso Extension for VSCode
- Zephyr Device Trees
- Introduction to Zephyr Part 1: Getting Started - Installation and Blink | DigiKey
- Zephyr esp32s3_devkitc
- Zephyr esp32s3_devkitc - schematic
Create a virtual environment in your chosen directory
D:\ESP32Zephyr> python -m venv zephyrproject\.venvD:\ESP32Zephyr> ls
Directory: D:\ESP32ZephyrActivate 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 westInitialise the Repo and get the zephyr source code
west init zephyrproject
cd zephyrproject
west updateNow go and make some tea!
We now need to export a Zephyr CMake Package to allow us build the boilerplate code.
west zephyr-exportInstall additional Python dependencies
west packages pip --installTime for more tea!
cd zephyr
# we should now be in D:\ESP32Zephyr\zephyrproject\zephyr
west sdk installObtain all esp32 blobs:
west blobs fetch hal_espressifTo 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.
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\blinkyOr for a simpler example you could try:
west build -p always -b esp32s3_devkitc/esp32s3/procpu .\samples\hello_worldBut, continuing with blinky for now, lets flash our new image.
Connect the esp32 to your development machine using a USB cable and then confirm the associated Com port in Device Manager.
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...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_demoI renamed the provided sample structure as follows:
D:\ESP32Zephyr\zephyrproject\applications\
βββ esp32s3_demo/
βββ src/main.c
βββ prj.conf
βββ CMakeLists.txt
βββ boards/esp32s3_devkitc.overlayesp32s3_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 - 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.
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.
Copy the unzipped folder to Program Files
C:\Program Files\xpack-openocd-0.12.0-7Add this to our path
Go to zadig
Select the option for USB JTAG/serial debug uint (interface 2) - you will need to downgrade to WinUSB V6.1.xxxxx
After install we should see a new serial port under com ports and under Universal Serial Bus Devices we should see a JTAG option.
Check that we have no errors
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-elfMy gdb is located here
c:/users/johno/zephyr-sdk-0.17.4/xtensa-espressif_esp32s3_zephyr-elf/bin/xtensa-espressif_esp32s3_zephyr-elf-gdb.exeWe 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.elfThen in the gdb console
target extended-remote localhost:3333We 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: haltedWe 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";
};
{
"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",
}
]
}
Create a new project on Edge Impulse.
Install the edge impulse cli
npm install -g edge-impulse-clihttps://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.542755PS 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!
Graphical view of data