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 hardware100`./slipmux` needs to be passed the TTY device for the HiFive1 (i.e.101`/dev/ttyUSB0`).102103To debug errors on real hardware start OpenOCD using `openocd -f104openocd.cfg`. In a separate terminal start a gdb version with RISC-V105support (e.g. [gdb-multiarch][gdb-multiarch alpine]) as follows:106107 $ gdb-multiarch -ex 'target extended-remote :3333' zig-out/bin/main108109## Development110111A pre-commit git hook for checking if files are properly formated is112provided in `.githooks`. It can be activated using:113114 $ git config --local core.hooksPath .githooks115116## License117118The application uses slightly modified linker scripts and assembler119startup code copied from the [RIOT][riot fe310] operating system. Unless120otherwise noted code written by myself is licensed under121`AGPL-3.0-or-later`. Refer to the license headers of the different files122for more information.123124[zig website]: https://ziglang.org/125[zig build modes]: https://ziglang.org/documentation/master/#Build-Mode126[qemu website]: https://www.qemu.org/127[fe310 manual]: https://static.dev.sifive.com/FE310-G000.pdf128[hifive1 website]: https://www.sifive.com/boards/hifive1129[riot fe310]: https://github.com/RIOT-OS/RIOT/tree/master/cpu/fe310130[slipmux]: https://datatracker.ietf.org/doc/html/draft-bormann-t2trg-slipmux-03131[rfc7252]: https://datatracker.ietf.org/doc/html/rfc7252132[rfc1055]: https://datatracker.ietf.org/doc/html/rfc1055133[libcoap github]: https://github.com/obgm/libcoap134[golang web]: https://golang.org135[zoap github]: https://github.com/nmeum/zoap136[riscv-openocd]: https://github.com/riscv/riscv-openocd137[gdb web]: https://www.gnu.org/software/gdb/138[gdb-multiarch alpine]: https://pkgs.alpinelinux.org/package/edge/main/x86_64/gdb-multiarch