Implement a fault-tolerant and diagnosable RTOS on RISC-V + QEMU — Part 1

ztex, Tony, Liu
3 min readDec 20, 2023

--

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

  1. go to FreeRTOS/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC
  2. make -C build/gcc
  3. 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

--

--

ztex, Tony, Liu

Incoming-Intern, CPU emulation software @Apple, Ex-SDE @Amazon. Working on embedded system, Free-RTOS, RISC-V etc.