Rust on embedded RISC-V
Théo Rozier, January 3rd, 2022
In this series of blog posts, I'm going to explain how I managed to develop in Rust on the Ox64 SBC powered by a RISC-V heterogenous SoC. These posts will cover different methodologies you can use for finding relevant documentation and resources while working on such a niche board, in general you can use this series for writing Rust software on any SoC for any architecture.
Table of contents
The board I chose is a PINE64 Ox64, as stated on their wiki, it's a Single Board Computer powered by a Bouffalo Lab BL808 SoC. This SoC is an heterogenous system with three separate CPUs:
- T-head C906 64-bit RISC-V
- T-head E907 32-bit RISC-V
- T-head E902 32-bit RISC-V
I chose this particular board for it's multimedia subsystem, which is mounted around the C906 CPU. I was especially interested in its video processing capabilities.
This board doesn't embed any USB to UART module, the micro-USB port is only for 5V power supply and the USB-C port is not linked to such module. Therefore I had to solder two 20 pins connectors on the board in order to plug it on a breadboard, and then link it to a CP2102 USB to UART module.
The pinout of the board can be found online on their wiki, in general it's good to keep your board's pinout and schematics, it will often be useful if you want to go further (Ox64 Schematic 20221018 v1.1).
It can also be useful to have an oscilloscope around the corner, or simply a multimeter in order to measure status pins. You can additionally use a JTAG probe (in my case a SEGGER J-Link Pro) to debug the chip while running. The pinout is also quite complicated if we want to properly connect status and reset pins.
As said in the introduction, my goal is to develop in Rust. To do so, we use the official Rust installer rustup to install the toolchain (GNU on Linux and MSVC on Windows for example), note that stable toolchain is enough! Once installed, we need to add some extra targets and components to the toolchain with the following commands:
1 2 3
The first command installs the 32-bit RISC-V compiler and tools, the second installs LLVM compiler tools, such as
objdump. The third line install a cargo binary called cargo-binutils, it's a wrapper that links cargo and LLVM tools, this provides additional cargo commands to run an LLVM tool directly on a cargo build's output.
If your distro already provide
cargovia its dependency manager, it's likely that they will not provide the right components for embedded development nor the latest Rust version, so please consider using
For the text editor, I chose Visual Studio Code with rust-analyzer. This isn't important and everyone has its own preferences, but the important point in my opinion is to have autocompletion and type hints, this allows seeing static constraints on types.