/zephyr-workshop

IoT Embedded Programming with Zephyr RTOS

Primary LanguageCApache License 2.0Apache-2.0

IoT Embedded Programming with Zephyr RTOS

Workshop

Note: This new workshop for the workshop days 2022 of ch-open is still in beta. Feedback is welcome, please create an issue.

The Internet of Things (IoT) is the convergence of internet and real world. IoT embedded devices typically have limited resources, but they are also becoming more performant with each generation. This enables more complex software on site, but also places higher demands on the platform. Zephyr RTOS, an open source operating system for embedded devices, provides the necessary abstractions, including POSIX threads, BSD sockets and debugging mechanisms. These allow professional software engineering for robust, reliable IoT applications.

Topics

Objective

This workshop teaches the basics of embedded programming on the latest IoT hardware, with Zephyr OS, in the C programming language.

Target audience

This workshop is aimed at interested people with programming experience, ideally in C, but also in Python or Java.

Prerequisites

Participants need a laptop with MacOS, Windows or Linux, and two USB/USB-C ports. IoT hardware including sensors is available on loan.

The workshop requires a Wi-Fi network that is accessible without a portal. Alternatively, a personal smartphone can be used as a hotspot.

Introduction

Video: Introduction to Zephyr by @TheaClay

Zephyr RTOS

The Zephyr Project strives to deliver the best-in-class RTOS for connected resource-constrained devices, built to be secure and safe.

Secure - Developed with security in mind. Includes CNA with PSIRT response team.

Open Source - Available through the Apache 2.0 open source license. Free to use in commercial and non-commercial solutions.

Product Ready - Long term support (LTS) with security updates. Auditable code base developed with a goal of safety certifications.

Connected - Supports BLE, Wi-Fi, 802.15.4. Supports standards like 6LoWPAN, CoAP, IPv4, IPv6, Ethernet, USB, CAN and Thread.

https://zephyrproject.org/

The Zephyr OS is based on a small-footprint kernel designed for use on resource-constrained and embedded systems: from simple embedded environmental sensors and LED wearables to sophisticated embedded controllers, smart watches, and IoT wireless applications.

https://docs.zephyrproject.org/latest/introduction/index.html

Extensive suite of Kernel services • Multiple Scheduling Algorithms • Highly configurable / Modular for flexibility • Cross Architecture • Memory Protection • Compile-time resource definition • Optimized Device Driver Model • Devicetree Support • Native Networking Stack supporting multiple protocols • Bluetooth Low Energy 5.0 support • Native Linux • macOS • and Windows Development • Virtual File System Interface with LittleFS and FATFS Support • Powerful multi-backend logging Framework • User friendly and full-featured Shell interface • Settings on non-volatile storage • Non-volatile storage (NVS) • Native POSIX port.

https://docs.zephyrproject.org/latest/introduction/index.html#distinguishing-features

Kernel services

The Zephyr kernel lies at the heart of every Zephyr application. It provides a low footprint, high performance, multi-threaded execution environment with a rich set of available features. The rest of the Zephyr ecosystem, including device drivers, networking stack, and application-specific code, uses the kernel’s features to create a complete application.

Scheduling, Interrupts, and Synchronization • Data Passing • Memory Management • Timing • Other

https://docs.zephyrproject.org/latest/kernel/services/index.html

OS services

Cryptography • Debugging • Device Management • File Systems • Formatted Output • Logging • Tracing • Resource Management • Modbus • Asynchronous Notifications • Power Management • OS Abstraction • Shell • Settings • State Machine Framework • Storage • Task Watchdog • Trusted Firmware-M • USB device support • Virtualization • Miscellaneous.

https://docs.zephyrproject.org/latest/services/index.html

Build system

CMake is used to build your application together with the Zephyr kernel. A CMake build is done in two stages. The first stage is called configuration. During configuration, the CMakeLists.txt build scripts are executed. After configuration is finished, CMake has an internal model of the Zephyr build, and can generate build scripts that are native to the host platform.

https://docs.zephyrproject.org/latest/build/cmake/index.html

https://docs.zephyrproject.org/latest/build/cmake/index.html#configuration-phase

https://docs.zephyrproject.org/latest/build/cmake/index.html#pre-build, #intermediate-binaries, #intermediate-binaries-post-processing, #final-binary, #post-processing

Devicetree overview

A devicetree is a hierarchical data structure that describes hardware.

There are two types of devicetree input files: devicetree sources and devicetree bindings. The sources contain the devicetree itself. The bindings describe its contents, including data types.

https://docs.zephyrproject.org/latest/build/dts/intro.html

a devicetree is a tree. The human-readable text format for this tree is called DTS (for devicetree source)

Devicetree nodes have paths identifying their locations in the tree [and] properties [which] are name/value pairs.

In practice, devicetree nodes usually correspond to some hardware, and the node hierarchy reflects the hardware’s physical layout.

https://docs.zephyrproject.org/latest/build/dts/intro.html#syntax-and-structure

A devicetree binding declares requirements on the contents of nodes, and provides semantic information about the contents of valid nodes. Zephyr devicetree bindings are YAML files

https://docs.zephyrproject.org/latest/build/dts/bindings.html

Devicetree details

Step-by-step advice for getting things done with devicetree.

Show final devicetree after a build

$ cat build/zephyr/zephyr.dts

Show final devicetree includes

$ cat build/zephyr/include/generated/devicetree_unfixed.h

https://docs.zephyrproject.org/latest/build/dts/howtos.html

Devicetree input (green) and output (yellow) files

There are four types of devicetree input files:

  • sources (.dts)
  • includes (.dtsi)
  • overlays (.overlay)
  • bindings (.yaml)

Every supported board has a BOARD.dts file describing its hardware

BOARD.dts includes one or more .dtsi files [which] describe the CPU or system-on-chip Zephyr runs on [and] common hardware features shared by multiple boards.

BOARD.dts can be extended or modified using [...] .overlay [...] DTS files [to] adapt the base devicetree for different purposes

Zephyr applications can use overlays to enable a peripheral that is disabled by default, select a sensor on the board for an application specific purpose, etc. [or] defining shields.

https://docs.zephyrproject.org/latest/build/dts/intro.html#input-and-output-files

Devicetree troubleshooting

Here are some tips for fixing devicetree related code.

  • Try again with a pristine build directory
  • Make sure <devicetree.h> is included
  • Make sure you’re using the right names
  • Look at the preprocessor output
  • Validate properties
  • Check for missing bindings
  • Errors with DT_INST_() APIs

https://docs.zephyrproject.org/latest/build/dts/troubleshooting.html#dt-trouble

Toolchain setup

https://docs.zephyrproject.org/latest/develop/getting_started/index.html

Maybe also https://github.com/zephyrproject-rtos/sdk-ng/releases (Installer, optional)

Zephyr

Zephyr on MacOS

Install the Zephyr command line tool west

$ brew install cmake ninja gperf python3 ccache qemu dtc wget
$ pip3 install -U west

Create a Zephyr workspace zephyrproject

$ cd ~/Documents
$ west init zephyrproject
$ cd zephyrproject
$ west update
$ west zephyr-export
$ pip3 install -r zephyr/scripts/requirements.txt 

Install the Zephyr SDK

$ cd ~
$ wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.14.2/zephyr-sdk-0.14.2_macos-x86_64.tar.gz
$ wget -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.14.2/sha256.sum | shasum --check --ignore-missing
$ tar xvf zephyr-sdk-0.14.2_macos-x86_64.tar.gz
$ cd zephyr-sdk-0.14.2
$ ./setup.sh

Clone the workshop directory into the workspace

$ cd ~/Documents/zephyrproject
$ git clone https://github.com/tamberg/zephyr-workshop

(Tipps on Brew, XCode, etc. see https://learn.adafruit.com/blinking-led-with-zephyr-rtos/installing-zephyr-osx)

Zephyr on Linux

TODO

Zephyr on Windows

TODO

Hello World

See samples/hello_world

#include <zephyr/zephyr.h>

void main(void) {
    printk("Hello World! %s\n", CONFIG_BOARD);
}

Hello World on x86 Qemu

This example runs without embedded hardware, on MacOS, Linux or Windows.

$ west build -p auto -b qemu_x86 samples/hello_world
$ west build -t run

SeaBIOS (version rel-1.15.0-0-g2dd4b9b3f840-prebuilt.qemu.org)
Booting from ROM..
*** Booting Zephyr OS build zephyr-v3.0.0-3797-gc28874657b70  ***
Hello World! qemu_x86

West

IDEs

Project structure

Hardware Setup

Zephyr project developers are continually adding board-specific support

https://docs.zephyrproject.org/latest/boards/index.html

ESP32 or ESP32-S2, which are currently the best choices [by Espressif] for running Zephyr

https://www.espressif.com/en/news/Zephyr_updates

FTDI

https://www.adafruit.com/product/4331 (3.3V)

Boards

ESP32-S2

Buy

https://www.adafruit.com/product/5325 (Adafruit QT Py ESP32-S2 WiFi Dev Board)

Board

https://docs.zephyrproject.org/latest/boards/xtensa/esp32s2_saola/doc/index.html

Pinout

Schematic

Datasheets

Devicetree

Pinmux macros

FTDI wiring

Color FTDI Board
Black GND GND
Brown CTS -
Red VCC -
Orange TXD RX
Yellow RXD TX
Green RTS -

ESP32-S2 ROM bootloader mode

To get the ESP32-S2 into ROM bootloader mode

  • Press and hold the BOOT button
  • Then, press the RESET button
  • Release the BOOT button

Now it should show up as a USB device.

ESP32-S2 on MacOS

To install the ESP32-S2 specific toolchain

$ pip3 install --upgrade esptool
$ cd ~/Documents/zephyrproject
$ west espressif update

To check the source code

$ cd ~/Documents/zephyrproject/zephyr
$ cat samples/basic/blinky/src/main.c

To build and flash

$ west build -p auto -b esp32s2_saola samples/basic/blinky
$ west flash
$ # or: west flash --esp-device=/dev/cu.usbmodem01

ESP32-S2 on Linux

TODO

ESP32-S2 on Windows

TODO

ESP32-C3

Not recommended yet.

Buy

https://www.adafruit.com/product/5405 (Adafruit QT Py ESP32-C3 WiFi Dev Board)

Board

https://docs.zephyrproject.org/latest/boards/riscv/esp32c3_devkitm/doc/index.html

Pinout

Schematic

Datasheets

Devicetree

Pinmux macros

ESP32-C3 on MacOS

$ west espressif update
$ cat samples/hello_world/src/main.c
$ west build -p auto -b esp32c3_devkitm samples/hello_world
<press & hold reset, press user button, release user button, release reset>
$ west flash
$ west espressif monitor

TODO: https://forums.adafruit.com/viewtopic.php?f=8&t=191501&p=926488#p926488

ESP32-C3 on Linux

TODO

ESP32-C3 on Windows

TODO

STM32F405

No built-in connectivity.

STM32F405 on MacOS

$ brew install dfu-util
$ brew install gcc-arm-embedded --cask
$ which arm-none-eabi-gdb
$ nano ~/.zshenv
export ZEPHYR_TOOLCHAIN_VARIANT=gnuarmemb
export GNUARMEMB_TOOLCHAIN_PATH=/usr/local/
$ source ~/.zshenv
$ echo $ZEPHYR_TOOLCHAIN_VARIANT
$ echo $GNUARMEMB_TOOLCHAIN_PATH
$ cat samples/basic/blinky/src/main.c
$ west build -p auto -b adafruit_feather_stm32f405 samples/basic/blinky
$ west flash

STM32F405 on Linux

TODO

STM32F405 on Windows

TODO

Custom board

GPIO & sensors

Blink (digital output)

Based on samples/basic/blinky try blink

Button (digital input)

Based on samples/basic/button try button

DHT11 temperature & humidity

Based on samples/sensor/dht try dht

More sensors

See samples/sensor

Threads & Mutex

TODO

Message Queues

TODO

Sockets & HTTP

TODO

Debugging

assert()

printk()

Logging

Debugger

$ west debug

https://www.zephyrproject.org/zephyr-rtos-boards-configurations-hardware-interaction/ (Debugging)

Menuconfig

On the development machine, at build time.

https://docs.zephyrproject.org/2.7.0/guides/build/kconfig/menuconfig.html

$ west build -t menuconfig
$ cat build/zephyr/.config

e.g. https://docs.zephyrproject.org/latest/kconfig.html#CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED

Menu path (Top) > Modules > mbed TLS Support > TLS configuration > Ciphersuite configuration

Shell

On the device, via UART.

a shell with a user-defined command set

https://docs.zephyrproject.org/latest/services/shell/index.html

If the shell or rather specific shell commands are enabled in the config, type e.g.

$ help
$ net iface

Remote

On the deployed device, via Internet.

More

Random

Golioth Posts on Zephyr

Nordic Fork of Zephyr

Videos