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

Introduction

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 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.

Update

My solution in the next sections was more complicated than necessary. Thanks to Python support for virtual environments, we can easily use the board on a modern system.

First, let's download a few packages: jlink-software-and-documentation and python38. Two remarks:

  • with Python3.9 the compilation of one package installed by pip fails, so I stick to 3.8 (it's the same version I had in the Docker container);
  • there seems to be something missing when using riscv64-unknown-elf-gcc (ld fails, unable to find -lc and -lgloss), so I instead use the one of FreedomStudio.

Then, we need the Freedom tools.

$ cd <BASE_DIR> # where you install the board tools
$ mkdir FreedomStudio && cd FreedomStudio
$ wget "https://static.dev.sifive.com/dev-tools/FreedomStudio/2019.03.4/FreedomStudio-4.7.2.2019-03-4-linux.gtk.x86_64.tar.gz"
$ tar -xf FreedomStudio-4.7.2.2019-03-4-linux.gtk.x86_64.tar.gz
$ cd ..
$ git clone --recursive https://github.com/sifive/freedom-e-sdk.git

We'll now tell the SDK to build the virtual environment with Python 3.8 intead of the latest one in Arch repos:

$ cd <BASE_DIR>/freedom-e-sdk
$ sed --in-place 's/python3 -m venv/python3.8 -m venv/' scripts/virtualenv.mk

It's now time to compile and run some code.

$ export RISCV_PATH=<BASE_DIR>/FreedomStudio/SiFive/toolchain/riscv64-unknown-elf-gcc-8.2.0-2019.02.0
$ cd <BASE_DIR>/freedom-e-sdk
$ make BSP=metal PROGRAM=hello TARGET=sifive-hifive1-revb software upload

Et voilà !

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
CONTAINER ID   IMAGE          COMMAND       CREATED       STATUS       PORTS     NAMES
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!

You need to connect the board before running the container, otherwise the container will not be able to access it via /dev/. Another solution, not tried, would be to copy the compiled application to the board from the host. This should be possible as the board appears to the host as a USB device.

You can run the 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

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

To access the board serial console (from the container or host), run the following command (we'll use it to check whether our application runs correctly):

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

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.