Experimental Zig-based CoAP node for the HiFive1 RISC-V board

git clone https://git.8pit.net/zig-riscv-embedded.git


2023-11-23 Fix clone URL of zoap submodule Sören Tempel
2022-03-06 Merge branch 'zig-0.9' Sören Tempel
2022-03-06 README.md: Document switch to Zig 0.9.1 Sören Tempel
2022-03-06 zoap: update Sören Tempel
2022-03-06 Replace c_void with anyopaque Sören Tempel

Clone the repository to access all 243 commits.


Experimental Zig-based CoAP node for the HiFive1 RISC-V board.

World's first IoT-enabled Zig-based constrained node


This repository is intended to provide a simple sample application for experimenting with the Zig programming language on freestanding RISC-V. The application targets the SiFive FE310-G000 or more specifically the HiFive 1. While possible to run the application on “real hardware”, it can also be run using QEMU. In both cases it is possible to toggle an LED using CoAP over SLIP.

CoAP over SLIP

To experiment with external dependencies in Zig, this application provides a very bare bone implementation of CoAP using zoap. Since implementing an entire UDP/IP stack from scratch is out-of-scope, this repository transports CoAP packets directly over SLIP.

Unfortunately, the QFN48 package of the FE310-G000 (as used by the HiFive1) does not support the UART1. For this reason, the application multiplexes diagnostic messages and CoAP frames over the same UART (UART0) using Slipmux. For this purpose, a Go-based multiplexer for the development system is available in the ./slipmux subdirectory.


For building the software and the associated Slipmux tooling, the following software is required:

For flashing to real hardware, the following software is required:


The Zig build system is used for building the application, the configuration is available in build.zig. To build the application run:

$ zig build

This will create a freestanding RISC-V ELF binary zig-out/bin/main. If the image should be booted on real hardware, building in the ReleaseSmall build mode may be desirable:

$ zig build -Drelease-small

Furthermore, the Slipmux multiplexer needs to be compiled using the following commands in order to receive diagnostic messages from the device and send CoAP messages to the device:

$ cd slipmux && go build -trimpath

Booting in QEMU

In order to simulate a serial device, which can be used with the ./slipmux tool, QEMU must be started as follows:

$ qemu-system-riscv32 -M sifive_e -nographic -kernel zig-out/bin/main -serial pty

QEMU will print the allocated PTY path to standard output. In a separate terminal the ./slipmux tool can then be started as follows:

$ ./slipmux/slipmux :2342 <PTY allocated by QEMU>

This will create a UDP Socket on localhost:2342, CoAP packets send to this socket are converted into Slipmux CoAP frames and forwarded to the emulated HiFive1 over the allocated PTY. CoAP packets can be send using any CoAP client, e.g. using coap-client(1) from libcoap:

$ coap-client -N -m put coap://[::1]:2342/on
$ coap-client -N -m put coap://[::1]:2342/off

In QEMU, this will cause debug messages to appear in the terminal window were ./slipmux is running. On real hardware, it will also cause the red LED to be toggled.

Booting on real hardware

The binary can be flashed to real hardware using OpenOCD and gdb. For this purpose, a shell script is provided. In order to flash a compiled binary run the following command:

$ ./flash

After flashing the device, interactions through CoAP are possible using the instructions given for QEMU above. However, with real hardware ./slipmux needs to be passed the TTY device for the HiFive1 (i.e. /dev/ttyUSB0).

To debug errors on real hardware start OpenOCD using openocd -f openocd.cfg. In a separate terminal start a gdb version with RISC-V support (e.g. gdb-multiarch) as follows:

$ gdb-multiarch -ex 'target extended-remote :3333' zig-out/bin/main


A pre-commit git hook for checking if files are properly formated is provided in .githooks. It can be activated using:

$ git config --local core.hooksPath .githooks


The application uses slightly modified linker scripts and assembler startup code copied from the RIOT operating system. Unless otherwise noted code written by myself is licensed under AGPL-3.0-or-later. Refer to the license headers of the different files for more information.