zig-riscv-embedded

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

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

  1# zig-riscv-embedded
  2
  3Experimental [Zig][zig website]-based [CoAP][rfc7252] node for the [HiFive1][hifive1 website] RISC-V board.
  4
  5![World's first IoT-enabled Zig-based constrained node](https://gist.github.com/nmeum/9c921cac9e28e722a8415af3ff213e8c/raw/b936f1f05d5eda07a91a87efdaf5cb1552795ad1/output-2fps-960px.gif)
  6
  7## Status
  8
  9This repository is intended to provide a simple sample application for
 10experimenting with the Zig programming language on freestanding RISC-V.
 11The application targets the [SiFive FE310-G000][fe310 manual] or more
 12specifically the [HiFive 1][hifive1 website]. While possible to run the
 13application on "real hardware", it can also be run using QEMU. In both
 14cases it is possible to toggle an LED using [CoAP][rfc7252] over
 15[SLIP][rfc1055].
 16
 17## CoAP over SLIP
 18
 19To experiment with external dependencies in Zig, this application
 20provides a very bare bone implementation of [CoAP][rfc7252] using
 21[zoap][zoap github]. Since implementing an entire UDP/IP stack from
 22scratch is out-of-scope, this repository transports CoAP packets
 23directly over [SLIP][rfc1055].
 24
 25Unfortunately, the QFN48 package of the FE310-G000 (as used by the
 26HiFive1) does not support the UART1. For this reason, the application
 27multiplexes diagnostic messages and CoAP frames over the same UART
 28(UART0) using [Slipmux][slipmux]. For this purpose, a Go-based
 29multiplexer for the development system is available in the `./slipmux`
 30subdirectory.
 31
 32## Dependencies
 33
 34For building the software and the associated Slipmux tooling, the
 35following software is required:
 36
 37* Zig `0.9.1`
 38* [Go][golang web] for compiling the `./slipmux` tool
 39* A CoAP client, e.g. `coap-client(1)` from [libcoap][libcoap github]
 40* QEMU (`qemu-system-riscv32`) for emulating a HiFive1 (optional)
 41
 42For flashing to real hardware, the following software is required:
 43
 44* [riscv-openocd][riscv-openocd]
 45* [GDB][gdb web] with 32-bit RISC-V support
 46
 47## Building
 48
 49The Zig build system is used for building the application, the
 50configuration is available in `build.zig`. To build the application run:
 51
 52	$ zig build
 53
 54This will create a freestanding RISC-V ELF binary `zig-out/bin/main`.
 55If the image should be booted on real hardware, building in the
 56`ReleaseSmall` [build mode][zig build modes] may be desirable:
 57
 58	$ zig build -Drelease-small
 59
 60Furthermore, the Slipmux multiplexer needs to be compiled using the
 61following commands in order to receive diagnostic messages from the
 62device and send CoAP messages to the device:
 63
 64	$ cd slipmux && go build -trimpath
 65
 66## Booting in QEMU
 67
 68In order to simulate a serial device, which can be used with the
 69`./slipmux` tool, QEMU must be started as follows:
 70
 71	$ qemu-system-riscv32 -M sifive_e -nographic -kernel zig-out/bin/main -serial pty
 72
 73QEMU will print the allocated PTY path to standard output. In a separate
 74terminal the `./slipmux` tool can then be started as follows:
 75
 76	$ ./slipmux/slipmux :2342 <PTY allocated by QEMU>
 77
 78This will create a UDP Socket on `localhost:2342`, CoAP packets send to
 79this socket are converted into Slipmux CoAP frames and forwarded to the
 80emulated HiFive1 over the allocated PTY. CoAP packets can be send using
 81any CoAP client, e.g. using `coap-client(1)` from [libcoap][libcoap github]:
 82
 83	$ coap-client -N -m put coap://[::1]:2342/on
 84	$ coap-client -N -m put coap://[::1]:2342/off
 85
 86In QEMU, this will cause debug messages to appear in the terminal window
 87were `./slipmux` is running. On real hardware, it will also cause the
 88red LED to be toggled.
 89
 90## Booting on real hardware
 91
 92The binary can be flashed to real hardware using OpenOCD and gdb. For
 93this purpose, a shell script is provided. In order to flash a compiled
 94binary run the following command:
 95
 96	$ ./flash
 97
 98After flashing the device, interactions through CoAP are possible using
 99the instructions given for QEMU above. However, with real hardware
100`./slipmux` needs to be passed the TTY device for the HiFive1 (i.e.
101`/dev/ttyUSB0`).
102
103To debug errors on real hardware start OpenOCD using `openocd -f
104openocd.cfg`. In a separate terminal start a gdb version with RISC-V
105support (e.g. [gdb-multiarch][gdb-multiarch alpine]) as follows:
106
107	$ gdb-multiarch -ex 'target extended-remote :3333' zig-out/bin/main
108
109## Development
110
111A pre-commit git hook for checking if files are properly formated is
112provided in `.githooks`. It can be activated using:
113
114	$ git config --local core.hooksPath .githooks
115
116## License
117
118The application uses slightly modified linker scripts and assembler
119startup code copied from the [RIOT][riot fe310] operating system. Unless
120otherwise noted code written by myself is licensed under
121`AGPL-3.0-or-later`. Refer to the license headers of the different files
122for more information.
123
124[zig website]: https://ziglang.org/
125[zig build modes]: https://ziglang.org/documentation/master/#Build-Mode
126[qemu website]: https://www.qemu.org/
127[fe310 manual]: https://static.dev.sifive.com/FE310-G000.pdf
128[hifive1 website]: https://www.sifive.com/boards/hifive1
129[riot fe310]: https://github.com/RIOT-OS/RIOT/tree/master/cpu/fe310
130[slipmux]: https://datatracker.ietf.org/doc/html/draft-bormann-t2trg-slipmux-03
131[rfc7252]: https://datatracker.ietf.org/doc/html/rfc7252
132[rfc1055]: https://datatracker.ietf.org/doc/html/rfc1055
133[libcoap github]: https://github.com/obgm/libcoap
134[golang web]: https://golang.org
135[zoap github]: https://github.com/nmeum/zoap
136[riscv-openocd]: https://github.com/riscv/riscv-openocd
137[gdb web]: https://www.gnu.org/software/gdb/
138[gdb-multiarch alpine]: https://pkgs.alpinelinux.org/package/edge/main/x86_64/gdb-multiarch