Previous Work

In the first of two preceding projects [16] a comparison of established RTOS written in the C language revealed that there is a division into general purpose RTOS (μC/OS-III, FreeRTOS) and IoT-centric RTOS (Contiki, Mynewt, Zephyr), although the border is blurry. In recent years, the orientation of RTOS has shifted from general purpose to internet of things (IoT). This was indicated by the increasing number of network stacks and support for cloud infrastructure integrated in RTOS. The work featured insight into μC/OS-III, an extensively documented RTOS similar to FreeRTOS. Furthermore, the tools and structure of the Zephyr project from the Linux Foundation were reviewed.

As a result, it was decided that the Bern RTOS should implement similar features to those of μC/OS-III and FreeRTOS. Network stacks and hardware access will not be integrated into the RTOS but rather offered as separate modules at some point. A first draft of the system architecture and design ideas were created.

Besides the RTOS comparison, an introduction into the Rust programming language was provided in the work. It became evident that Rust is indeed a suitable language for embedded systems because modern programming paradigms (e.g. generics, traits, closures) allow for abstraction while being efficient. Memory-safety and thread-safety guaranteed by the Rust compiler increase the safety and security of embedded systems, especially if dynamic memory allocation is used. Many software bugs are already caught at compile time and safe hours of debugging on the hardware.

The second project consisted of software requirements specification and the implementation of core kernel components. The specifications compromise the whole RTOS. It focuses on memory-safety, timeliness and the overall feature set.

Based on the specifications, the architecture was adapted from the previous project and a first revision of the preemptive scheduler was implemented for the Armv7E-M CPU architecture. The kernel was based on a widespread task model. However, every task was limited to either access its own stack, a shared memory section or peripherals. That approach also prevents data corruption from a stack overflow. In order for multiple tasks to work together, the synchronization primitives mutex and semaphore were added to the kernel. The primitives had to be allocated statically in the shared memory section.

The correct behavior of the kernel was tested using a three-level system. Individual units are tested in insolation, architecture-dependent integration is tested against the target hardware and system-level tests are conducted to evaluate real-time capabilities.

At the end of the project, it became evident that the memory protection concept was flawed. In part because the memory protection unit of Armv7E-M based microcontrollers is too restrictive. Additionally, keeping all shared data in one globally accessible section meant that shared data cannot be trusted. One task might manipulate or corrupt all shared data. Therefore, the memory protection model must be changed.

This document is based on the second project documentation. Its contents have been reworked and extended.