Implement a fault-tolerant and diagnosable RTOS on RISC-V + QEMU — Part 1
Abstraction
In this series of articles, I want to talk about, based on FreRTOS, what we should do to enable a fault-tolerant and diagnosable system on it.
The experiment will be conducted on the QEMU emulator, and it will be based on RISC-V architecture.
This article will first introduce the fundamentals of FreeRTOS, RISC-V, and QEMU.
FreeRTOS
FreeRTOS is a real-time operating system kernel for embedded devices that has been ported to 35 microcontroller platforms. It is distributed under the MIT License.
FreeRTOS implements multiple threads by having the host program call a thread tick method at regular short intervals. The thread tick method switches tasks depending on priority and a round-robin scheduling scheme.
To discover FreeRTOS, let’s start with RISC-V_RV32_QEMU_VIRT_GCC demo.
Goto this repo, you should see a implementation for RISC-V + QEMU
[ ] main.c: the entry of the kernel logic
pay attention to the following snippet
void main( void )
{
/* See https://www.freertos.org/freertos-on-qemu-mps2-an385-model.html for
instructions. */
#if( mainVECTOR_MODE_DIRECT == 1 )
{
__asm__ volatile( "csrw mtvec, %0" :: "r"( freertos_risc_v_trap_handler ) );
}
#else
{
__asm__ volatile( "csrw mtvec, %0" :: "r"( ( uintptr_t )freertos_vector_table | 0x1 ) );
}
#endif
/* The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is described at the top
of this file. */
#if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 )
{
main_blinky();
}
#else
{
main_full();
}
#endif
}
freertos_risc_v_trap_handler
is the handler who takes care of every interrupt (timer, software interrupt, etc) and is also the key to our fault-tolerant and diagnosable system.
mainCREATE_SIMPLE_BLINKY_DEMO_ONLY
determines which demo mode we go for, the default is full mode.
[] ns16550.[c/h] + riscv-virt.[c/h]
This is an easy driver implementation for a well-known UART chip, ns16550
and riscv-virt
is an abstraction between the application layer and the hardware layer
[] main_full.c
I encourage everyone to check it out. There are two main tasks.
One checks the register's integrity by writing known values onto registers and verifying them.
The other task is triggered for 5000 ms. If the RTOS states are right, it outputs a successful message; otherwise, it indicates where it goes wrong.
RISC-V toolchain
To install the RISC-V toolchain, I chose to download the prebuilt Sifive freedom tools.
Go to https://github.com/sifive/freedom-tools, download the release package, untar it under any directory (/opt/riscv/ for instance), and add the path to the environment variable $PATH
QEMU
QEMU is a generic and open-source machine emulator and virtualizer.
When used as a machine emulator, QEMU can run OSes and programs made for one machine (e.g. an ARM board) on a different machine (e.g. your own PC). By using dynamic translation, it achieves very good performance.
You can build it from source code, download it prebuilt, or use the package manager (brew, apt-get, yum, etc.) to install it.
Build and Run
- go to
FreeRTOS/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC
make -C build/gcc
- run the following command:
qemu-system-riscv32 -nographic -machine virt -net none \
-chardev stdio,id=con,mux=on -serial chardev:con \
-mon chardev=con,mode=readline -bios none \
-smp 4 -kernel ./build/gcc/output/RTOSDemo.elf
and the message are like this:
FreeRTOS Demo Start
FreeRTOS Demo SUCCESS: : 5031
FreeRTOS Demo SUCCESS: : 10032
FreeRTOS Demo SUCCESS: : 15031
...
(There could be some error messages)
Conclusion
In this article, we briefly talk about how to install, build, and run a simple FreeRTOS-RISC-V kernel and run it on QEMU
In the next article, we will talk about the trap mechanism in RISC-V and how we can build a fault-tolerant and diagnosable system based on trap handler