The RISC-V open instruction set is getting more and more news coverage these days. In particular since the release of the first RISC-V microcontroller from SiFive and the announcement of an Arduino board at the Maker Faire Bay Area 2017.
As an open source software company we are very interested in this trendy, new, open platform. AdaCore tools already support an open IP core with the Leon processor family, a popular architecture in the space industry that is developed in VHDL and released under the GPL. RISC-V seems to be targeting a different market and opening new horizons.
GNAT - the Ada compiler developed and maintained by AdaCore - is part of the GCC toolchain. As a result, when a new back-end is added we can fairly quickly start targeting it and developing in Ada. In this blog post I will describe the steps I followed to build the tool chain and start programing the HiFive 1 RISC-V microcontroller in Ada.
Building the ToolchainThe first step is to build the compiler. SiFive - manufacturer of the MCU - provides an SDK repository with scripts to build a cross RISC-V GCC. All I had to do was to change the configure options to enable Ada support
--enable-languages=c,c++,ada
and disable libada since this is a bare-metal target (no operating system) we won’t use a complete run-time
--disable-libada
If you want to build the toolchain yourself, I forked and modified the freedom-e-sdk repository.
Just clone it
$ git clone --recursive https://github.com/Fabien-Chouteau/freedom-e-sdk
install a native GNAT from your Linux distrib (I use Ubuntu)
$ sudo apt-get install gnat
and start the build
$ cd freedom-e-sdk
$ make tools
If you have a problem with this procedure don’t hesitate to open an issue on GitHub, I’ll see what I can do to help.
Building the Run-TimeAda programs always need a run-time library, but there are different run-time profiles depending on the constraints of the platform. In GNAT we have the so called Zero FootPrint run-time (ZFP) that provides the bare minimum and therefore is quite easy to port to a new platform (no exception propagation, no tasking, no containers, no file system access, etc.).
I started from Shawn Nock’s ZFP for the Nordic nRF51 and then simply changed the linker script and startup code, everything else is platform independant.
You can find the run-time in this repository: https://github.com/Fabien-Chouteau/zfp-hifive1
Writing the DriversTo control the board I need a few drivers. I started by writing the description of the hardware registers using the SVD format: here.
I then generated Ada mapping from this file using the SVD2Ada tool. You can find more info about this process at the beginning of this blog post.
From these register mappings it’s fairly easy to implement the drivers. So far I wrote GPIO and UART: https://github.com/AdaCore/Ada_Drivers_Library/tree/master/arch/RISC-V/SiFive/drivers
First Ada Projects on the HiFive1The first project is always a blinky. The HiFive1 has RGB leds so I started by driving those. You can find this example in the Ada_Drivers_Library.
If you want to run this simple example on your board, get my fork of the freedom-e-sdk (as described above) and run:
$ make ada_blinky_build
and then
$ make ada_blinky_upload
to flash the board.
For the second project, thanks to the architecture of the Ada_Drivers_Library, I was able to re-use the thermal printer driver from my DIY instant cameraand it took me only 5 minutes to print something from the HiFive1.
All of this is only experimental for the moment, but it shows how quickly we can start programing Ada on new platforms. Proper support would require a run-time with tasking, interruptions, protected objects (Ravenscar profile) and of course complete test and validation of the compiler.
Comments