====== Zephyr ======
===== Länkar =====
* [[https://github.com/Utedass/zephyr-workspace]] -- My own devcontainer setup for Zephyr development
* [[https://embedded.fm/episodes/475?rq=zephyr]] -- Nämner bland annat att det finns några tänkta sätt att strukturera sina projekt för att inte blanda in sin projekt-kod i zephyr-repot
* [[https://www.youtube.com/watch?v=tAH5fy0rSo4|Youtube Linux Foundation]] -- Zephyr Project: RTOS Start-up and Initialization Flow
* [[https://interrupt.memfault.com/blog/building-drivers-on-zephyr]]
* [[https://community.circuitdojo.com/d/146-zephyr-driver-development-use-of-i2c-and-spi-apis]]
== Real world examples ==
* [[https://github.com/zephyrproject-rtos/awesome-zephyr-rtos/tree/main]] -- Awezome Zephyr related list
* [[https://github.com/xycloo/zephyr-examples/tree/master]] -- Rust examples
* [[https://github.com/zmkfirmware/zmk/tree/main]] -- Zephyr Mechanical Keyboard
* [[https://github.com/jakkra/ZSWatch/tree/main]] -- Open Source Smart Watch
== Shawn Hymel / Digikey ==
* [[https://www.youtube.com/watch?v=mTJ_vKlMS_4|Introduction to Zephyr Part 1: Getting Started]]
* [[https://www.youtube.com/watch?v=HSWazjB63cU|Introduction to Zephyr Part 2: CMake Tutorial]]
* [[https://www.youtube.com/watch?v=dXx1Wc15NZE|Introduction to Zephyr Part 3: Kconfig Tutorial]]
* [[https://www.youtube.com/watch?v=fOMJyjwowNk|Introduction to Zephyr Part 4: Devicetree Tutorial]]
* [[https://www.youtube.com/watch?v=nL1kZ3kPyo0|Introduction to Zephyr Part 5: Devicetree Bindings]]
* [[https://interrupt.memfault.com/blog/practical_zephyr_kconfig|Recommended KConfig page]]
== Dokumentation ==
* [[https://docs.zephyrproject.org/apidoc/3.7.0/group__random__api.html|Zephyr API]]
* [[https://docs.zephyrproject.org/3.7.0/services/crypto/random/index.html|Zephyr services]]
* [[https://docs.zephyrproject.org/3.7.0/build/kconfig/index.html|Zephyr KConfig]]
* [[https://cmake.org/cmake/help/v3.20/manual/cmake-commands.7.html|Cmake]]
===== Vanliga kommandon =====
Bygg Zephyr-projekt med overlay
west build -p always -b esp32c6_devkitc -- -DDTC_OVERLAY_FILE=boards/esp32s3_devkitc.overlay
Öppna menuconfig
west build -p always -b esp32c6_devkitc -t menuconfig
Bygg med extra conf file
west build -p always -b esp32c6_devkitc -- -DEXTRA_CONF_FILE=boards/esp32s3_devkitc.conf
Ladda kod
python -m esptool --port COM19 --chip auto --baud 921600 --before default_reset --after hard_reset write_flash -u --flash_size detect 0x0 .\build\zephyr\zephyr.bin
===== Platser =====
| ''zephyr/dts////'' | .dtsi filer för olika chip |
| ''zephyr/dts/bindings//.yaml'' | .yaml binding-filer för olika chips drivrutiner |
| ''zephyr/boards///'' | .dts, Kconfig och default configs för boards |
| ''zephyr/soc///soc.h'' | Startup-kod, HAL-includes etc för specifikt chip |
| ''zephyr/arch//core/'' | Assembler-startup etc för specifik arkitektur |
===== CMake =====
=== CMakeList.txt in project ===
cmake_minimum_required(VERSION 3.20.0)
# Optional for your own extra KConfig modules
set(ZEPHYR_EXTRA_MODULES "${CMAKE_SOURCE_DIR}/../../modules/say_hello")
# Mandatory thing
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
# Name your project
project(random)
# Adds your main entry point to the Zephyr-created "app" lib
target_sources(app PRIVATE src/main.c)
=== CMakeLists.txt ===
CMakeLists file for your own modules
# Check if SAY_HELLO is set in Kconfig
if(CONFIG_SAY_HELLO)
# Add your include directory
zephyr_include_directories(.)
# Add the source file you want to compile
zephyr_library_sources(say_hello.c)
endif()
===== KConfig =====
Öppna menuconfig
west build -p always -b esp32c6_devkitc -t menuconfig
Sparas till ''./build/zephyr/.config'' som kommer tas bort vid nästa bygge.
Generates an include file in ''build/zephyr/include/generated/zephyr/autoconf.h''
För att göra persistent, kolla diff mellan ./build/zephyr/.config.old
# diff build/zephyr/.config.old build/zephyr/.config
574a575,576
> # CONFIG_STACK_CANARIES is not set
> CONFIG_STACK_POINTER_RANDOM=0
1136c1138
< # CONFIG_TEST_RANDOM_GENERATOR is not set
---
> CONFIG_TEST_RANDOM_GENERATOR=y
1137a1140,1141
> CONFIG_TIMER_RANDOM_GENERATOR=y
> CONFIG_TEST_CSPRNG_GENERATOR=y
Lägg sedan detta i antingen appens prj.conf eller ännu bättre i en board-specifik config
# File: boards/esp32s3_devkitc.conf
# CONFIG_STACK_CANARIES is not set
CONFIG_STACK_POINTER_RANDOM=0
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_TIMER_RANDOM_GENERATOR=y
CONFIG_TEST_CSPRNG_GENERATOR=y
# CONFIG_SAY_HELLO=y
Och lägg med denna till bygget med ''-DEXTRA_CONF_FILE=boards/esp32s3_devkitc.conf''
west build -p always -b esp32c6_devkitc -- -DEXTRA_CONF_FILE=boards/esp32s3_devkitc.conf
==== Egna moduler ====
För att lägga till egna moduler som går att aktivera i menuconfig, lägg in en fil som heter exempelvis KConfig i modulens mapp.
# Create a new option in menuconfig
config SAY_HELLO
bool "Basic print test to console"
default n # Set the library to be disabled by default
depends on PRINTK # Make it dependent on PRINTK
help
Adds say_hello() function to print a basic message to the console.
Lägg även till en mapp som heter exakt ''zephyr'' i modulens mapp. Lägg in en fil som heter exakt ''module.yaml'' med likande innehåll. kconfig: pekar ut KConfig-filen ovan.
name: say_hello
build:
cmake: .
kconfig: Kconfig
===== Devicetree =====
* [[https://github.com/devicetree-org/devicetree-specification/releases/download/v0.4/devicetree-specification-v0.4.pdf|Devicetree 0.4 specification]]
* [[https://docs.zephyrproject.org/3.7.0/build/dts/index.html|Zephyr DTS page]]
* [[https://docs.zephyrproject.org/3.7.0/build/dts/bindings-syntax.html|Zephyr DTS bindings]]
The final devicetree will end up under ''build/zephyr/zephyr.dts''.
There is an include file generated from this in ''build/zephyr/include/generated/zephyr/devicetree_generated.h''
=== Words ===
* DTS -- Device Tree Source
* DTC -- Device Tree Compiler
* .dtsi -- Device Tree Source Include file
=== Property types ===
| string | ''status = "disabled";'' |
| int | ''current-speed = <115200>;'' |
| boolean | ''hw-flow-control;'' |
| array 32bit | ''offsets = <0x100 0x200 0x300>;'' |
| uint8-array | ''local-mac-address = [de ad be ef 12 34];'' |
| string-array | ''dma-names = "tx", "rx";'' |
| phandle | ''interrupt-parent = <&gic>;'' |
| phandles | ''pinctrl-0 = <&usart2_tx_pd5 &usart2_rx_pd6>;'' |
| phandle-array | ''dmas = <&dma0 2>, <&dma0 3>;'' |
| path | ''zephyr,bt-c2h-uart = &uart0;'' or ''foo = "/path/to/some/node";'' |
=== Structure ===
[[https://docs.zephyrproject.org/3.7.0/build/dts/intro-syntax-structure.html|Zephyr DTS Syntax Structure]]
In the boards folder for esp32s3_devkitc there is a DTS file for the appcpu, ''/opt/toolchains/zephyr/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_appcpu.dts''.
/*
* Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
/dts-v1/;
#include
#include
/ {
model = "Espressif ESP32S3-DevkitC APPCPU";
compatible = "espressif,esp32s3";
chosen {
zephyr,sram = &sram0;
zephyr,ipc_shm = &shm0;
zephyr,ipc = &ipm0;
};
};
&trng0 {
status = "okay";
};
&ipm0 {
status = "okay";
};
This ''#include '' includes a devicetree source include-file which in turn includes ''#include "esp32s3_common.dtsi"''.
Int the file ''/opt/toolchains/zephyr/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi'' there is a part defining the alias ''gpio0'' for the path ''/soc/gpio/gpio@60004000''.
gpio0: gpio@60004000 {
compatible = "espressif,esp32-gpio";
gpio-controller;
#gpio-cells = <2>;
reg = <0x60004000 0x800>;
interrupts = ;
interrupt-parent = <&intc>;
/* Maximum available pins (per port)
* Actual occupied pins are specified
* on part number dtsi level, using
* the `gpio-reserved-ranges` property.
*/
ngpios = <32>; /* 0..31 */
};
The ''compatible = "espressif,esp32-gpio";'' tells Zephyr to look for a bindings file containing the similar line (file name doesn't really matter, but is by convention the same).
Binding file can be found in ''/opt/toolchains/zephyr/dts/bindings/gpio/espressif,esp32-gpio.yaml''
# Copyright (c) 2019, Yannis Damigos
# SPDX-License-Identifier: Apache-2.0
description: ESP32 GPIO controller
compatible: "espressif,esp32-gpio"
include: [gpio-controller.yaml, base.yaml]
properties:
reg:
required: true
"#gpio-cells":
const: 2
gpio-cells:
- pin
- flags
Also at the location for the board files is the ''/opt/toolchains/zephyr/boards/espressif/esp32s3_devkitc/esp32s3_devkitc-pinctrl.dtsi'' device tree source include file. The start of the file looks like this:
/*
* Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include
#include
#include
&pinctrl {
uart0_default: uart0_default {
group1 {
pinmux = ;
output-high;
};
group2 {
pinmux = ;
bias-pull-up;
};
};
i2c0_default: i2c0_default {
group1 {
pinmux = ,
;
bias-pull-up;
drive-open-drain;
output-high;
};
};
The line ''#include '' refers to the file ''/opt/toolchains/zephyr/include/zephyr/dt-bindings/pinctrl/esp32s3-pinctrl.h'' which has a lot of defines used in the device tree include file.
#define UART0_TX_GPIO43 ESP32_PINMUX(43, ESP_NOSIG, ESP_U0TXD_OUT)
All of the files in ''/opt/toolchains/zephyr'' directories are default files and the device tree thingies can be overridden in you project with a overlay-file.
=== Lables, names, property names ===
[[https://docs.kernel.org/devicetree/bindings/dts-coding-style.html|Kernel DTS Coding Style]]
* Names kan inte ha understreck, men kan ha bindestreck.
* Lables kan inte ha bindestreck men kan ha understreck.
* Names kan ha brädhögar och snabel-a i namnet, ingen magi.
* Property names kan inte ha understreck, men kan ha bindestreck
* I C-kod kommer bindestreck i aliases att automatiskt översättas till understreck
=== /chosen och /aliases ===
Dessa är två speciella noder i device-trädet som DTC behandlar speciellt. Dessa går att fylla på för att ställa in vissa saker eller introducera alias.
/ {
chosen {
zephyr,console = &uart0;
};
aliases {
my-uart = &uart0;
};
soc {
uart0: serial@12340000 {
...
};
};
};
==== Overlay files ====
== Example ==
''boards/esp32s3_devkitc.overlay''
/ {
aliases {
my-led = &led0;
};
leds {
compatible = "gpio-leds";
led0: d5 {
gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>;
};
};
};
===== C-kod =====
== Exempel blink ==
#include
#include
#include
// Settings
static const int32_t sleep_time_ms = 1000;
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_ALIAS(my_led), gpios);
int main(void)
{
int ret;
int state = 0;
// Make sure that the GPIO was initialized
if (!gpio_is_ready_dt(&led))
{
return 0;
}
// Set the GPIO as output
ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT);
if (ret < 0)
{
return 0;
}
// Do forever
while (1)
{
// Change the state of the pin and print
state = !state;
printk("LED state: %d\r\n", state);
// Set pin state
ret = gpio_pin_set_dt(&led, state);
if (ret < 0)
{
return 0;
}
// Sleep
k_msleep(sleep_time_ms);
}
return 0;
}