- Stefan Lüthi
This work is licensed under a Creative Commons Attribution 4.0 International License.
This document specifies and tracks the status of the requirements for all components that make up the Bern RTOS kernel. Other parts of the Bern RTOS are not part of this SRS.
This document provides the Bern RTOS maintainer a complete set of features that are to be implemented tested. Users of the Bern RTOS can look-up which features are planned and request new ones. There is a GitLab issue for every functional requirement. Issues are used to discuss the content of a requirement and contain additional information for development.
To request a new requirement you can create an issue here. To change of the current behavior of the kernel create an enhancement issue here. Issues are tracked on GitLab but you can also use your GitHub or BitBucket account to log in.
Be advised that feature requests might be deferred until the end of Stefan Lüthi (@luethi) master thesis (summer 2022).
In general this document intends serve as a summary what the Bern RTOS can and will be able to do and why it is part of the RTOS.
The kernel is the core part of any RTOS. It schedules tasks, enables communication between them and manages resources. The Bern RTOS kernel aims to make highly concurrent applications safer than a bare-metal implementation.
A requirement can be in one of the following states:
to review: The requirement was recently added and needs discussing first.
planned: The implementation of the requirement is planned within the current project scope.
done: The requirement is fulfilled (implemented and tested).
invalid: The requirement is no longer relevant or valid.
Requirements are grouped by topic and represented with an epic, which can have one of three states:
draft: All requirements within this epic are to be reviewed.
active: The epic is active. The requirement state applies.
inactive: The epic is no longer relevant or valid. All requirement states are invalid.
|MPU||Memory Protection Unit|
|RTOS||real-time operating system|
|SRS||software requirements specification|
The objective of the Bern RTOS project is to implement a safe and secure RTOS for microcontrollers from scratch in the Rust programming language. The core part of the RTOS is the kernel. The figure below shows the kernel components and interfaces to other parts of the system.
Black: kernel components and interfaces, gray: external components
The kernel provides features to:
- Schedule tasks
- Synchronize resource accesses and tasks
- Send messages between tasks
- Use dynamic memory (heap)
- Separate safe and unsafe code
- Protect access of peripherals
- Print log messages
Maintainer: Project maintainer contribute to the Bern RTOS codebase. Their interest is in making embedded systems safe and secure.
Maker: A hobbyist who wants to write applications quickly without any fuss. The maker expects an RTOS that just works, supports the major platforms and provides many examples.
Developer: Developers use the Bern RTOS in products because it provides features that increase the safety and security of the overall system. They expect the kernel to run stable and with minimal overhead. The API documentation must be complete and examples must also cover complex scenarios.
Company: A company is interested in profit and in a safe/secure system. It will only use the Bern RTOS if safety/security features are built-in and thus can safe time in the development process. A company also expects minimal memory footprint in order for the kernel to run on low-cost hardware.
The kernel is intended to run on microcontrollers. In contrast to general purpose operating systems the kernel cannot rely on memory management unit.
The kernel documentation consists of:
- User level online documentation with details about the kernel internals.
- API documentation on docs.rs.
- Code example repository.
It is assumed that a microcontroller provides a mechanism that allows the kernel to trap access from unprivileged tasks to restricted memory sections. This hardware feature is required for memory partitioning.
The peripheral manager aims to restrict access to peripherals and shared buses. The manager must work with different HALs. Thus, it is assumed that Rust generics will allow for easy integration of different HAL into the peripheral manager.
The functional requirements specify what the kernel is supposed to do. The requirements are grouped by kernel components. Each requirement has a user story and a priority. The acceptance criteria are refined before a sprint in the linked issue. At a later stage test should automatically update the verification status indicator.
A task is an entity of work. It is the basis of any RTOS. A task can be run periodically, on a specific event or only once.
|F001-1||Tasks||As a developer, I want to create tasks, so that I can separate independent code sections.||high||done|
|F001-2||Task Priorities||As a developer, I want to assign priorities to tasks, so that important tasks run on time.||high||done|
|F001-3||Task Privileges||As a developer, I want to give tasks privileges, so that only certain tasks can access resources.||low||to review|
|F001-4||Time Slicing||As a developer, I want the CPU to be shared between tasks with equal priority, so that I don't have to bother with switching active tasks.||medium||done|
|F001-5||Scheduling Algorithms||As a developer, I want to select a scheduling algorithm at compile time, so that configure the RTOS to my needs.||low||to review|
|F001-6||Tickless||As a developer, I want to disable time slicing in the scheduler, so that I can use the RTOS on ultra low power systems.||low||to review|
|F001-7||Async/Await||As a developer, I want to use Rusts async/await features, so that I can write code that is easier to understand than with callbacks.||low||to review|
|F001-8||Software One-Shot Timer||As a developer, I want to schedule an event at some specific time, so that I can defer an action with little overhead.||medium||to review|
|F001-9||Software Repetitive Timer||As a developer, I want to schedule periodic events in some interval, so that I can trigger short actions with little overhead.||medium||to review|
|F001-10||Kernel ISR||As a maintainer, I want to handle interrupts in the kernel, so that I can check that context and permissions are correct.||medium||done|
|F001-11||User ISR||As a developer, I want to register interrupt service routines, so that I can handle interrupt driven events.||medium||planned|
|F001-12||Low Latency ISR||As a developer, I want to handle time critical events without kernel interference, so that my system can react with minimal latency.||low||to review|
- The worst case execution time (WCET) model will not be covered
Synchronization primitives provide the most basic and essential form of communication between tasks. They protect resources, synchronize work and trigger actions.
|F002-1||Mutex||As a developer, I want that a single resource can only access from one task at a time, so that I can share resources between tasks without data hazards.||high||done|
|F002-2||Priority Inversion||As a developer, I want no unbounded priority inversion to occur when a tasks tries to access a shared resource, so that a task doesn't starve.||medium||planned|
|F002-3||Counting Semaphore||As a developer, I want to create an object that can be taken/given a multiple times, so that I can synchronize multiple tasks.||high||done|
|F002-4||Event Flags||As a developer, I want to trigger an action on a combination of events, so that I can react to system events efficiently.||low||planned|
Data can be transferred safely between tasks with message queues.
|F003-1||Message Queue||As a developer, I want to send messages from one task to another, so that I can communicate data between tasks.||high||done|
|F003-2||Message Queue Size||As a developer, I want to allocate a queue of fixed size within a task, so that no messages get lost when they're not read immediately.||medium||done|
|F003-3||Message Queue Access||As a developer, I want to send messages from multiple tasks to one queue, so that the memory overhead from the queues is minimal.||medium||done|
|F003-4||FIFO Message Queue||As a developer, I want the queue to be of FIFO manner, so that the order of messages is preserved.||medium||done|
|F003-5||Reference Messaging||As a developer, I want to send data efficiently, so that large data blocks can be exchanged without excessive overhead of copying data.||low||done|
Volatile and non-volatile memory are critical components for safety and security. This component is responsible for managing access to any memory.
|F004-1||Stack Overflow||As a maintainer, I want to trap stack overflows, so that no other task gets corrupted.||high||done|
|F004-2||Heap||As a maker, I want to use Rusts dynamic container types, so that I can use modern programming paradigms.||medium||done|
|F004-3||Memory Pool||As a developer, I want to use a deterministic dynamic memory (heap) without fragmentation, so that I don't get fragmentation issues from long run times.||medium||done|
|F004-4||Pool Configuration||As a developer, I want to structure the heap at run time, so that I have maximum flexibility in my code.||low||done|
|F004-5||Unsafe Isolation||As a developer, I want to run unsafe libraries in isolation, so that I can use preexisting code without corruption of my safe application.||low||to review|
|F004-6||Kernel Isolation||As a maintainer, I want to isolate the kernel memory from user code, so that an error in user code cannot corrupt the whole system.||medium||done|
Peripherals are hardware components integrated in the MCU which are not part of the CPU core. They drive board components and form an interface to physical world outside the embedded system. This management component assures that access to the peripherals is easy, safe and secure.
|F005-1||Peripheral Access||As a developer, I want to choose which parts of the software are allowed to access peripherals at compile time, so that rogue/malicious task destablizes the embedded system.||low||to review|
|F005-2||Peripheral Sharing||As a developer, I want to share bus interfaces amongst multiple tasks, so that separate drivers for hardware components that run on the same bus.||medium||to review|
|F005-3||Power Management||As a maintainer, I want the RTOS to track the power state of each peripheral, so that the kernel can select sleep modes autonomously.||low||to review|
|F005-4||Embedded HAL||As a maker, I want to use the embedded-hal, so that I can use existing device drivers.||medium||to review|
Logs are essential for system and application debugging. They provide information after a failure occurred even if no debug interface was connected.
|F006-1||Log Sources||As a developer, I want to post log messages from any part of the application, so that I can track down software bugs.||high||done|
|F006-2||Log Message||As a developer, I want any log message to state its origin, time and severity, so that I can filter irrelevant messages out.||high||done|
|F006-3||Log Backends||As a developer, I want to select the log backends at compile time, so that I can use any hardware interface to output log information.||meidum||done|
|F006-4||Log Run Time Filter||As a developer, I want to filter log messages per backend at run time, so that I only receive message that are important for me.||low||done|
|F006-5||Log Compile Time Filter||As a developer, I want to filter log messages at compile time, so that I only the necessary log code is added to flash memory.||medium||done|
|F006-6||RTOS Tracing||As a developer, I want the kernel to provide a generic interface for event tracing, so that I can use any software to trace my application.||medium||done|
|F006-7||SEGGER SystemView||As a developer, I want the tracing backend to support SEGGER SystemView, so that I can use a simple GUI to analyze my application.||medium||done|
The non-functional requirements specify how the kernel is supposed to be. These quality attribute apply to all components of the system. They have no definition of done, as non-functional requirements apply for every release.
The priority refers to the importance for the project that the requirement is met. All non-functional requirements should be met, but if two are contradicting the one with higher priority will be preferred.
A kernel runs on different platforms. A modular design allows the user to scale the kernel for its application. Modularity also increases flexibility because components can be replaced.
|N001-1||Kernel Dependencies||As a maintainer, I want the dependencies between the kernel components to be kept at a minimum, so that I can rewrite/replace components.||high|
|N001-3||Application Dependencies||As a company, we want to keep RTOS specific code to a minimum, so we can switch to another RTOS if we need to.||low|
|N001-4||HAL Interface||As a developer, I want to use my own HAL, so that I can reuse preexisting code.||high|
|N001-5||Kernel Configuration||As a developer, I want to enable/disable individual kernel components, so that I can tailor the kernel to my needs.||medium|
The amount of memory and safety features depend on the MCU in use. A small memory footprint will allow the kernel to run on any system.
|N002-1||ST Nucleo Support||As a maker, I want to run a preconfigured RTOS on an STM32-Nucleo Board, so that I can start coding my application.||low|
|N002-2||Flash Requirements||As a developer, I want to kernel with all components enabled to use < 20kB of flash memory, so that the kernel uses <10% of a medium-sized MCU with 256kB flash memory.||medium|
|N002-3||RAM Requirements||As a developer, I want to kernel with all components enabled to use < 5kB of RAM, so that the kernel uses < 10% of a medium-sized MCU with 56kB RAM.||medium|
|N002-4||Min. Flash Requirements||As a developer, I want to a minimal version of the kernel to use < 5kB of flash memory, so that the kernel uses < 10% of a small-sized MCU with 64kB flash memory.||low|
|N002-5||Min. RAM Requirements||As a developer, I want to kernel with all components enabled to use < 2kB of RAM, so that the kernel uses < 10% of a medium-sized MCU with 36kB RAM.||low|
|N002-6||ARMv7E-M Support||As a company, we want to kernel to support ARMv7E-M (ARM Cortex-M4/M7) MCU with MPU, so that we can choose from many high-performance MCUs and have a stable supply chain.||high|
|N002-7||ARMv7-M Support||As a company, we want to kernel to support ARMv7-M (ARM Cortex-M3) MCU with MPU, so that we can choose from many medium-performance MCUs and have a stable supply chain.||medium|
- ARMv6-M (ARM Cortex-M0+) support is not of priority for the moment, as its MPU and atomic operation instructions are limited
- ARMv8-M (ARM Cortex-M23/M33) support will be added at some point in the future
- RISC-V support is currently not planned, because they have a small market share
The kernel safety mechanism provide reliable system performance. Its security mechanisms protect the system from attacks on interfaces.
|N003-1||Application Security||As a developer, I want that code from an unsafe partition cannot corrupt my application.||high|
|N003-2||Kernel Security||As a maintainer, I want that no code outside the kernel space can crash the kernel.||high|
|N003-3||Toolchain||As a maintainer, I want to use Rusts stable toolchain, so that the kernel doesn't rely on unstable language features.||medium|
- Ferrocene (formerly Sealed Rust) - a Rust subset for safety critical applications - might become a requirement at some point in the future
Embedded systems react to their environment. They must do so in a timely manner, or the system as a whole might become unstable.
|N004-1||Task Latency||As a developer, I want high-priority tasks to be called within 1 us after an event occurs (on an ARM Cortex-M4 @ 72 MHz).||medium|
|N004-2||ISR Latency||As a developer, I want time-critical user ISR to be called within 1 us after the interrupt occurred (on an ARM Cortex-M4 @ 72 MHz).||medium|
The kernel aims to be easy-to-use, so that new users can accommodate to its API fast and to reduce the number bugs overall.
|N005-1||Multi-Threading Syntax||As a developer, I want to use common Rust multi-threading syntax, so that I can get started easily.||high|
|N005-2||Kernel Tool Integration||As a developer, I want that kernel tools are integrated into Cargo, so that I can use a system I'm familiar with.||low|
|N005-3||Examples||As a maker, I want to build my application on existing examples, so that I have a running application with little effort.||low|
Requirement changes of the Bern RTOS kernel will be tracked in this document. See Commits in GitLab for details.
- Update issue states
- Add changelog
- Update issue states and links
- All requirements