Sunday, 27 August 2017

[GSoC 2017 Results: RTEMS for HiFive1] The Final Report

Google Summer of Code 2017 Results

Utilizing full power of RISC-V architecture via usage of RTEMS on top of SiFive FE310 processors

Student: Denis Obrezkov
Mentors: Joel Sherrill, Hesham Almatary

The Goal and Objectives

This project aimed to provide the RTEMS community with a new capability of utilizing the power of SiFive FE310 processors. Since the main goal of the project was to provide developers of embedded systems with new capabilities, a few objectives were defined:
  • to implement HiFive1 BSP with a console and clock driver support
  • to provide project documentation.

These well-defined objectives were achieved during Google Summer of Code 2017. In the following parts of the document it will be shown how to utilize the results of the work, what problems were overcome during the project and what constraints the current solution has. Also, some links to valuable patches, sources and blog posts with a description of the made work will be provided. Finally, there will be some notes about the future involvement.

What was done
The patch summarizing my changes: pull request
My working code repo with a full commits history filtered by author: branch: "hifive1"
My code repository with a cleaned code: branch "hifive1_patch_prep"
The code hasn't been merged yet.


The first problem I encountered during the GSoC is that the previous RTEMS port  for RISC-V contains obsolete instructions, those were removed by this commit:merge request. After that, I created a separate branch for a new BSP and added linker file and init file (commit). Having completed this, I started trying to make little programs be executed (commit 1, commit 2, commit 3). The main difficulty on this stage of the development was the abundance of information about RTEMS, RISC-V architecture and HiFive1 board.


Being able to run small programs on the board, I encountered the second problem - HiFive1 is a very memory constrained platform. It consists only of 16 KiB of RAM, since one of the smallest RTEMS-supported BSPs has 32 KiB of RAM. Keeping this in mind, I started my low-memory BSP way.


Later I was able to utilize UART, but on that stage of the development I had to receive information only from gdb. I added .data section initialization (commit), made a small bug there and fixed it a bit later (commit). My next step was enabling global interrupts (commit) and handling them (commit). Being able to handle interrupts I moved to my console driver. I set up crystal oscillators and uart (commit). I implemented partly a console driver, thus, adding a possibility of utilizing printk() function for debug purposes.


The last stage was the hardest. Though, I had a working console driver, working interrupts and understood to some extent how RTEMS and HiFive1 work - I still had a very limited memory space which made it hard to understand whether my application didn’t work due to memory constraints or because of a hidden bug. At this stage I worked with the clock driver (commit 1, commit 2), the console driver (commit), global configuration options (commit 1, commit 2), context switch and interrupt handling routines (commit 1, commit 2, commit 3). In conclusion, I cleaned up my code (commit 1, commit 2, commit 3, commit 4).

What’s left to do
Though, the main objectives were achieved, there is some amount of work to be done. First of all, on the current stage it is hard to say whether some undefined behavior can be caused by memory constraints or by an occasional bug. Thus, some work should be done in order to prove to some extent the correctness of the BSP. Secondly, the linker file of the BSP uses an obsolete RTEMS structure. Thereby, a new one should be implemented following modern rules (one big common linker file for an architecture and a small linker file for each implementation). Finally, it should be noted that a lot of work could be done in external interrupts handling and utilization of other capabilities of the board like SPI and GPIO ports.

Utilizing RTEMS HiFive1 BSP

In order to try the BSP several steps should be done.
  1. Obtain source code of RTEMS and tools.
  2. Build the toolchain.
  3. Configure RTEMS.
  4. Build and install RTEMS.
  5. (optional) Build and install examples.

Build instructions

First of all, we should create a directory for our project:

$ cd
$ mkdir -p ./development/rtems/kernel
$ cd ./development/rtems/kernel

At this stage we can create an alias for our development folder:

$ export RTEMS_DEV=$HOME/development

Now we should obtain RTEMS distro from my git repository:

$ cd rtems-riscv/
$ git checkout hifive1_patch_prep

As a next step, we should install the tools. We need to do it, because we should compile rtems for our target system, thus, we need a cross-compiler. And the cross-compiler itself is built by the build system - RSB. Let's create a directory for it:

$ cd $RTEMS_DEV
$ mkdir ./rtems/rsb
$ cd ./rtems/rsb

then, download and install it:

$ git clone git://git.rtems.org/rtems-source-builder.git
$ cd rtems-source-builder/rtems
$ ../source-builder/sb-set-builder --prefix=$RTEMS_DEV/rtems/4.12 4.12/rtems-riscv32
$ export PATH=$RTEMS_DEV/rtems/4.12/bin:$PATH

Let's now bootstrap it:

$ cd $RTEMS_DEV/rtems/kernel/rtems-riscv
$ ./bootstrap -c && ./bootstrap -p && ./bootstrap && $RTEMS_DEV/rtems/rsb/rtems-source-builder/source-builder/sb-bootstrap

And configure and build kernel:

$ cd $RTEMS_DEV/rtems
$ mkdir rtems_build
$ cd rtems_build/
$ rm rf ./*
$ $RTEMS_DEV/rtems/kernel/rtems-riscv/configure --prefix=$RTEMS_DEV/rtems/4.12 --disable-networking --target=riscv32-rtems4.12 --enable-rtemsbsp=hifive1 --disable-cxx --disable-tests && make && make install
In order to check our solution we should compile examples:

First of all, we should download examples from RTEMS git repository into our $RTEMS_DEV folder:

$ cd $RTEMS_DEV
$ git clone git://git.rtems.org/examples-v2.git
$ cd examples-v2
$ export EXAMPLES_V2=$RTEMS_DEV/examples-v2

Let's follow the instructions in README.waf file:

$ git submodule init
$ git submodule update

Now we have obtained new folder rtems_waf, which contains some scripts which support application building with the waf build system.

Before building our example applications we should build rtems-tools:

$ cd $RTEMS_DEV/rtems
$ git clone git://git.rtems.org/rtems-tools.git
$ cd ./rtems-tools
$ ./waf configure --prefix=$RTEMS_DEV/rtems/4.12
$ ./waf build install

As a prefix we can use another location.
Let's now build the examples themselves:

$ cd $EXAMPLES_V2

If you don't have yet a path to your compiler and debugger in your PATH variable (you can check it with command 'echo $PATH'):

$ export PATH=$RTEMS_DEV/rtems/4.12/bin:$PATH

Now we should configure our examples:

$ cp $RTEMS_DEV/rtems/rtems-tools/waf ./
$ chmod u+x ./waf
$ ./waf configure --rtems=$RTEMS_DEV/rtems/4.12 --rtems-tools=$RTEMS_DEV/rtems/4.12 --rtems-bsps=riscv32/hifive1 --rtems-version=4.12
$ ./waf

At the moment of this article writing, it is not possible to build all the examples. So, let's compile two distinct examples.
First of all, the Low Ticker Example:

$ cd $EXAMPLES_V2/ticker/low_ticker
$ ../../waf

Secondly, the Hello World Example:

$ cd $EXAMPLES_V2/hello/posix_hello_world
$ ../../waf

In order to run these examples we should download RISC-V tools. The easiest way to do it is via installation of Freedom E SDK:
Instructions and the software can be found here: https://github.com/sifive/freedom-e-sdk After installation of the tools we should add them to PATH:

export FREEDOM_SDK=/path to freedom sdk/

At this stage you should unpack examples that come with SDK. Now we can debug our application. We should open two terminal windows and run there:

cd $FREEDOM_SDK/bin

In the first window we should start gdb:

$ ./riscv64-unknown-elf-gdb $EXAMPLES_V2/build/riscv32-rtems4.12-hifive1/hello/posix_hello_world/posix_hello.exe
or
$ ./riscv64-unknown-elf-gdb $EXAMPLES_V2/build/riscv32-rtems4.12-hifive1/ticker/low_ticker/low_ticker.exe

In the second window we should start openocd:

$ ./openocd -f ../SiFive/Examples/HiFive1/hello/openocd.cfg

(examples should be unpacked earlier and the board should be connected)
Now we should run a serial terminal, for example, cutecom, and open a com port (with the name like /dev/ttyUSB0).
At this stage we should go to our gdb window and run these commands there:

tar rem :3333
load
continue

For the first application, you will see the following output:

*** HELLO WORLD TEST ***
Hello World
*** END OF HELLO WORLD TEST ***
Fatal Error 5.0 Halted

And for the second one (low ticker example):

*** LOW MEMORY CLOCK TICK TEST ***
TA1 - rtems_clock_get_tod - 09:00:00 12/31/1988
TA2 - rtems_clock_get_tod - 09:00:00 12/31/1988
TA3 - rtems_clock_get_tod - 09:00:00 12/31/1988
TA1 - rtems_clock_get_tod - 09:00:05 12/31/1988
TA1 - rtems_clock_get_tod - 09:00:10 12/31/1988
TA2 - rtems_clock_get_tod - 09:00:10 12/31/1988
TA1 - rtems_clock_get_tod - 09:00:15 12/31/1988
TA3 - rtems_clock_get_tod - 09:00:15 12/31/1988
TA1 - rtems_clock_get_tod - 09:00:20 12/31/1988
TA2 - rtems_clock_get_tod - 09:00:20 12/31/1988
TA1 - rtems_clock_get_tod - 09:00:25 12/31/1988
TA1 - rtems_clock_get_tod - 09:00:30 12/31/1988
TA2 - rtems_clock_get_tod - 09:00:30 12/31/1988
TA3 - rtems_clock_get_tod - 09:00:30 12/31/1988
*** END OF LOW MEMORY CLOCK TICK TEST ***
Fatal Error 5.0 Halted

The error message “Fatal Error 5.0 Halted” means that application reached its end.

Sometimes, application may hang. It happens due to problems during context switch/interrupt handling. This is an area for further investigations. In order to overcome it, try to rebuild the applications and/or run them again.

Tackled problems and current constraints

During the project few problems were outcome. Most of them were related to memory constraints of the target. HiFive1 has only 16 KiB of RAM, while most of the current RTEMS targets has more than 32 KiB. Other issues were associated with the previous RTEMS BSPs for RISC-V architecture. This work of Hesham Almatery supported the previous ISA, thereby some commands were changed in order to provide a support for the modern ISA. Additional information about my progress during Google Summer of Code can be found in a commit history of my branch here and in my blog posts [1], [2], [3], [4], [5], [6].

The current solution’s constraints arise from the limitations of the platform. The most valuable restriction is a small memory amount which is a cause of absence of support for many significant RTEMS features. Among them are full POSIX support and network support.
Another big limitation is the fact that the current solution is a work in progress. Thus, some additional changes should be done in the near future: refactoring a linker script file, testing the current solution to the greatest possible extent with the given memory limitations, implementing an interrupt stack and implementing another hardware interfaces support (GPIO, SPI, software I2C).

Future involvement


It was very pleasant to work with RTEMS community. Thus, I am really interested in future cooperation in creation of stable and predictable real-time operating system. My big wish is to have an ability to improve my port further and at the same time to discuss new ideas with RTEMS community on related topics, like distributed real-time systems, time and space separated systems, ways of improving a configuration system, etc.

No comments:

Post a Comment