This blog was originally published on the Codasip blog.
For each embedded product, software developers need to consider whether they need an operating system; and if so, what type of an OS. Operating systems vary considerably, from real-time operating systems with a very small memory footprint to general-purpose OSes such as Linux with a rich set of features.
Choosing a proper type of operating system for your product – and consequently working out the required features of the embedded processor – depends significantly on whether you face a hard real-time requirement. Safety-critical and industrial systems such as an anti-lock braking system or motor control will have hard maximum response times. At the other end of the spectrum, consumer systems such as audio or gaming devices may be able to tolerate buffering, as long as the average performance is adequate. Such systems are said to have soft real-time requirements.
A hard real-time requirement can be achieved by writing so called bare-metal software that directly controls the underlying hardware. Bare-metal programming is typically utilized when the processor resources are very limited, the software is simple enough, and/or the real-time requirements are so tight that introduction of a further abstraction layer would complicate meeting these hard real-time requirements. The disadvantage to this approach is that such bare-metal software needs to be written as a single task (plus interrupt routines), making it difficult for programmers to maintain the software as its complexity grows.
Real-Time Operating Systems
When dealing with more complex embedded software, it is often advantageous to employ a Real-Time Operating System (RTOS). It allows the programmer to split the embedded software into multiple threads whose execution is managed by the small, low-overhead “kernel” of the RTOS. The use of the multi-threaded paradigm enables developers to create and maintain more complex software while still allowing for a sufficient reactivity. RTOSes typically operate with a concept of “priority” assigned to individual threads. The RTOS can then “pre-empt” (temporarily halt) lower-priority threads in favour of those with higher priority, so that the required real-time constraints can be met. The use of an RTOS often becomes necessary when adopting complex libraries or protocol stacks (such as TCP/IP or Bluetooth) as this third-party software normally consists of multiple threads already. Today there is a wide choice of open source and commercially licensed RTOSes.
The embedded processor requirements of a simple RTOS, such as FreeRTOS or Zephyr, are truly modest. It is sufficient to have a RISC-V processor with just machine mode (M) and a timer peripheral. These RTOSes can therefore run on any of the Codasip RISC-V cores or Western Digital SweRV Cores. However, rigorous software development is needed as machine mode offers unconstrained access to all memory and peripherals with associated risks. Extra protection is possible through a specialized RTOS such as those developed for functional safety, like SAFERTOS, or for security.
If a processor core supports both machine (M) and user (U) privilege modes and has physical memory protection (PMP), it is possible to establish separation between trusted code (with unconstrained access) and other application code. With PMP, the trusted code sets up rules for each portion of the application code, saying which parts of memory (or peripherals) it is allowed to access. PMP can for instance be used to prevent third-party code from interfering with the data of the rest of the application, or to detect stack overflows. Employing PMP therefore increases the safety and security of a system, but at the cost of additional hardware required for its support.
Rich Operating Systems
For applications requiring a more advanced user interface, sophisticated I/O and networking, such as in set-top boxes or entertainment systems, an RTOS is likely to be too simplistic. The same applies if there are complex computations, requirements for a full process isolation and multitasking, filesystem & storage support, or a full separation of application code from hardware via device drivers. Systems like these generally have soft real-time requirements and can be best served by a general-purpose rich operating system such as Linux. As noted in an earlier post, Linux requires multiple RISC-V privilege modes – machine, supervisor, and user modes (M, S, U) – as well as a memory management unit (MMU) for virtual-to-physical address translation. Also, the memory footprint of such system is significantly larger compared to a simple RTOS.
Finally, for embedded systems that require both hard real-time responses and features of a rich operating system like Linux, it is common to design them with two communicating processor subsystems, one supporting an RTOS and the other running Linux.