Embedded Development on a RISC-V board, with a twist.


My local electronic shop was selling a bunch of SiFive HiFive1 RevB at a 85% discount, so even before asking whether I need one, I bought one. No way I'd pass the opportunity to try a RISC-V board!

The board, released around March 2019, is Arduino compatible and embeds a micro-B USB connection, JTAG capabilities, a WiFi and Bluetooth module (needs an external module), I/O headers, a SiFive FE310-G0002 microcontroller, and more.

The processor inside the board microcontroller is a E31 RISC-V RV32IMAC CPU. This is a 32-bit processor running at 320MHz with 16kB of SRAM, 16kB of L1 instruction cache, and 32Mb of flash memory.

Many resources can be found online, including code and documentation. However, the main issue I encountered is the lack of code updates in the recent years: the Freedom Studio or Freedom E SDK (which I will use below) github repositories, necessary to develop for the board, have not been updated since at most 2021. I also had the problem of the documentation being for Ubuntu while I use ArchLinux.

Getting started

The first thing to do is read the Getting Started guide.

Software development can be done either via Freedom Studio, an Eclipse-based IDE plus all the tools necessary for development, or a bit more manually with the Freedom E SDK.

First try on ArchLinux

Innocently, I tried to follow the guide while running on ArchLinux, installing the two following packages for the prerequisite: jlink-software-and-documentation and riscv64-unknown-elf-gcc.

Most of it went fine, until the make command to build one of the Freedom E SDK examples. More specifically, the Makefile runs a Python script that tries to import the distutils module, deprecated since Python 3.10, while I have Python 3.12 installed.

Maybe there is a simple solution to this problem, but I could not find one, so I switched to Ubuntu (in a Docker container).

Successful try on Ubuntu (in Docker)

Last code update on github is around 2021? Let's install Ubuntu 20.04 LTS then! I do not want to remove my ArchLinux, and a virtual machine would be too cumbersome (especially since I need to be able to access the board from the Ubuntu installation), so I created a new Docker container.

The first step is to install Docker:

$ paru -S docker
$ sudo systemctl enable docker
$ sudo systemctl start docker

Then we can get the Ubuntu 20.04 image and install some packages:

$ sudo docker pull ubuntu:20.04
$ sudo docker run -ti --rm ubuntu:20.04 /bin/bash

# # inside the container from this point
# apt update && apt upgrade && apt install build-essential screen git ...
# do NOT exit the container before the next step!

Once done, we will create a new image from the container, so that we do not need to do the above steps each time we want to run the container (the container ID will be different in your case). After this step it is safe to exit the container. Note that you need to redo the commit everytime you install a new software.

$ sudo docker ps
0b79278c9c68   ubuntu:20.04   "/bin/bash"   2 hours ago   Up 2 hours             great_khayyam
$ sudo docker commit -p 0b79278c9c68 ubuntu20.04_hifive1b_dev

Compiling and running the hello example

Let's connect the board to the computer! Note that you need to connect it before running the container, otherwise the container will not be able to access it via /dev/. Another solution, not tried yet, would be to copy the compiled application to the board from the host. This is possible as the board appears to the host as a USB device.

We can run our container again. As I do not want to put the SDK and my code inside the image -- that would increase its size beyond something acceptable -- I am mounting a local folder inside the container. And I also need to pass the --privileged flag to the docker run command to access the board serial console (in /dev/ttyACM0). The new command is:

$ sudo docker run --privileged -ti -v /absolute/path/to/local/folder/shared/with/container:/data ubuntu20.04_hifive1b_dev /bin/bash

To access the board serial console (from the container or host), run the following command:

$ sudo screen /dev/ttyACM0 115200 # remove sudo if already root

We'll use it to check whether our application runs correctly.

From inside the container, for some reason installing the RISC-V toolchain was stalling. And I'm not sure how to install the required JLink tools. So I changed my strategy: I downloaded and extracted Freedom Studio inside the shared folder. It already contains the RISC-V toolchain and JLink tools, quite convenient! As I did on ArchLinux, I also downloaded the Freedom E SDK.

Once done, we need to tell the SDK where to find the tools:

export PATH=/data/FreedomStudio-4.7.2/SiFive/jlink/jlink-6.44.0-2019.03.0:${PATH}
export RISCV_PATH=/data/FreedomStudio-4.7.2/SiFive/toolchain/riscv64-unknown-elf-gcc-8.2.0-2019.02.0

Finally, we can build the code (here the hello example from the SDK) and upload it to the board in one command:

make BSP=metal PROGRAM=hello TARGET=sifive-hifive1-revb software upload

Just press the RESET button on the board to restart it with the new program, and voilà! You should see Hello, World! appearing in the serial console.

Now the fun begins. I think I'll try to write an OS in Rust.