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 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.
- Obtain source code of RTEMS and tools.
- Build the toolchain.
- Configure RTEMS.
- Build and install RTEMS.
- (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