# Embedded RTOS design : insights and implementation / Colin Walls > Used to describe the general architecture and purpose of an RTOS ## Chapter 1 ## Program structure and real time An embedded system is often refered to as > Any electronic device that contains a microprocessor (CPU) that would not normally be described as a computer. The use for operating systems in embedded applications have had an upswing in the last decade, and is now very common for higher-end applications. ### Why use an operating system - An embedded system normally runs a single software application from the moment it is switched on until it is shut down. - Embedded systems have limited resources. Memory space may be large enough, but it is unlikely to be extensible; the CPU is probably just powerful enough, but with no extra capacity to spare. - Many embedded applications are "real time". - Embedded software development tools are quite specialized and run on a "host" computer for example a PC. - The updating of embedded software in service is challenging. Although, with connected devices, possibillities are beginning to emerge, in-field updates are still not the norm (compared with the regular updates and patched applied to the desktop software). The author specifies that, as we will see the use for an embedded OS provides a useful programming model to the developer, which can make its use very attractive. ### Software structure #### Here the author takes a closer look on different software structures, for example DOS, iOS and windows. Can be interesting to write about, but can take examples from other sources. ### Embedded program models > Desktop systems are all much the same. From an application program’s point of view, every Windows of PC is identical. Embedded systems are unique—everyone is different from every other one. Some things that make embedded systems unique are - Memory size - Peripherals - CPU Other things, that differs are: - execution speed - power consumption - security - reliabillity Accounting for these differences have many implications for developers. The author then continues to describe different embedded software structures. #### Bare metal The simplest form of application is a loop, running program segments. The second is loop with interrupts. The loop will hold all the nontime-critical code, and the ISR's will handle the time-critical code. This ofcourse adds complexity. #### RTOS The third step on the complexity ladder is to split up different tasks, into psuedo-parallel segments. This requires an OS, or at minimum a kernel. This model is called multithreading. ### What is real time? > A real-time system is one in which the correctness of the computations not only depends on the logical correctness of the computation but also on the time at which the result is produced. If the timing constraints of the system are not met, system failure is said to have occurred. The most important characteristic of a real-time system, according to the author is determinism. This means that the system not-necessarily needs to execute fast, but fast enough to meet its deadlines. Here he implies that an RTOS (if used the correct way) can: > provide precise control over the allocation of CPU time to tasks and hence, render an application entirely deterministic. He also states that the use of interrupts can become an issue, as ISR's takes up time. Some RTOS's accounts for this and includes them in their scheduling scheme, but with an expense in terms of overhead, as the complexity of such algorithms is large. ## Chapter 2 ## Multitasking and scheduling Multitasking or multithreading is simply the term used to describe **multiple quasi-independent** programs that runs in "parallell". ### Tasks, threads and processes One can use the word task to describe both threads and processes. However, it is not very precise. This is because threads and processes are very different in terms of execution. > Most often, a real time operating system (RTOS) used in an embedded application will employ a multithread model. Several threads may be running and they all share the same address space (Fig. 2.1). This means that a context swap is primarily a change from one set of central processing unit (CPU) register values to another. This is quite simple and fast. A potential hazard is the ability of each thread to access memory belonging to the others or to the RTOS itself. > The alternative is the multiprocess model. If several processes are running, each one has its own address space and cannot access the memory associated with other processes or the RTOS (Fig. 2.2). This makes the context swap more complex and timeconsuming, as the OS needs to set up the memory management unit (MMU) appropriately. Of course, this architecture is only possible with a processor that supports an MMU. Processes are supported by “high end” RTOSes and most desktop operating systems. To further complicate matters, there may be support for multiple threads within each process. This latter capability is rarely exploited in conventional embedded applications. Make sure to check up the term MMU from a reliable source. Can be interesting to discuss, if we even need it. How ever the author further states that the use of an MMU in RTOS context is often to protect memory from unautorized access. This makes only the wanted parts of the memory parts visible, and the rest disabled throwing exceptions when trying to access it. Using an MMU for this reason is often referred to as **Thread protected mode**. ### Schedulers Schedulers are complex, and a vital part of the kernel. It is the scheduler that makes the appearance of concurrently running threads. We can also choose between a alot of different schedulers, allowing us the fit the deadlines for our application. The different schedulers discussed in this book are: - Run to completion (RTC) - Round Robin (RR) - Time Slice (TS) - Priority scheduler (PS) - Composite schedulers #### Run To Completion scheduler Often used for simpler applications. This is the simplest form of scheduling. Each task gets to finish. #### Round robin scheduler Similar to RTC but with the extension of context saving. The RR scheduler allows the program to save current stack pointer and program counter, making it possible to return to saved context during next round. This makes the scheduler a bit more complex, as each task needs its own stack. #### Time slice scheduler One more step up the complexity ladder lies the TS scheduler. This scheduler makes the program very predictable, as each program runs during its time slice. However if the application is complex enough, Deadlines would be at risk of failing. #### Priority scheduler The priority scheduler is very straight forward. Each task has its priority, and everytime an event that will trigger a higher prioritized thread to runoccurs, the scheduler is called. These events or interrupts consists of: - Task suspension - The running task, readies another task through the use of high priority API's - an ISR readies another task of higher priority. #### Composite scheduler More often than not, an RTOS will allow the developer to use a composite scheduler which is a composition of the above mentioned algorithms. ### Task states There is almost always one task running. However theres is also only one task running. The only time no task is running is in the case of an ISR being ran. #### Task suspend Task suspension can happen two ways. Either the running task suspends itself through the usage of an API. Or it can be suspended by another task. look up **unconditional suspend** vs **sleep suspend** vs **blocking suspend**. #### Other task Aside from **running** and **suspend** a task can also be **finished** or **terminated**. A finished task can be reset in some way, where as the terminated task acts as a **pure suspend** but with the difference that the task has to be reseted into its inital state. In case of dynamic creation and deletion of tasks, tasks can also be **deleted**. ### Task identifiers Tasks identifiers are used to identify and specify all the tasks in a system. According to the book there are four broad strategies that are used within different RTOSs: 1. A task is identified by means of a pointer to its “control block.” This approach seems sensible; such a pointer would always be unique to a specific task and is useful, as access to the control block is required by many API calls. The downside is that this implies that all the data about a task are held in contiguous memory (RAM), which may be inefficient. A pointer is also likely to require 32 bits of storage. 2. A task may be identified by an arbitrary “index number.” This value may be useful by giving access to entries in specific tables. Such an identifier may only require eight bits or less of storage, depending on any limitations on the number of tasks that are supported by the RTOS. 3. Some RTOSes only allow one task per priority level and, hence, use the priority to uniquely identify the task. This implies that a task’s priority may not be changed. This approach is really a variation of (2). 4. Tasks might have names which are character strings. This may be useful for debugging, but is unlikely to be an efficient means of uniquely identifying a task otherwise. RTOSes that support task naming generally have an additional identifier (like a pointer), which is used by API calls, etc. For most embedded systems, textual names are an unnecessary overhead on the target; a good debugger would allow naming locally on the host Im fairly sure that most sofisticated RTOS's uses the first strategy, and is what we refer to as handles. ### Context switching Simply put, context switching is when the scheduler changes what tasks are running. can be looked up from a better source! ### What is a task Here the author describes more carefully what the characteristics of a task is. However here we could look for other sources aswell! #### Register set > A task is ultimately a unique set of processor register values. These are either loaded into the CPU registers (i.e., the task is current) or stored somewhere ready to be loaded when the task is scheduled. In an ideal world, a CPU would have multiple sets of registers, such that one may be allocated to each task. #### Local data > A task will probably have its own stack, the size of which may be set on a task-by-task basis or may be a global setting for all tasks in the system. This, along with the registers, provides task-specific data storage. There may be other data storage memory areas that are dedicated to a specific task. #### Shared resources According to the book. Everything else except the things mentioned above, are shared resources. These included code, variables etc. Here one needs to makesure that we dont end up in **deadlocks** etc. ### Saving Context Whenever a task goes from running to suspended, i.e. context switching, its context needs to be saved for future use. According to the book there are two common options. - Task-specific tables. usally a part of a Task Control Block (TCB). - The registers can also be pushed onto the task's stack. ### Dynamic task creation Some RTOSs are static, other are dynamic. Static refers to that everything needs to be defined at build time, especially the number of tasks in the system. For most embedded applications, this approach would work. Dynamicy, refers to the possibillity of dynamically creating and destroying tasks. Usally through the use of a master task, that is defined at build time. The later is more in line with how a desktop system operates. #### Requirements for dynamic task creation Nothing super interesting here. #### Implications of dynamic task creation Nothing super interesting here. Except that dynamic RTOSs may introduce an overhead in terms of memory footprint, due to the use of pointers. ### Interrupts Basically jst stating that an RTOS needs interrupts. #### Interrupts and the kernel In RTOS design, the ISR's are usally lightweight. This is due to them stealing time from scheduled tasks. #### Context save It is important that the ISR saves the context, so that the interrupted code is unaffected by the ISR. in bare-metal applications this is done simply by preserving registers. #### Interrupts and the scheduler Interrupts can lead to context switching, if the ISR for example makes a high priority thread ready. ### Tick clock A tick clock is very common for all embedded applications. Most RTOSs provides one. The tick clock is usally incremented by an ISR. **Can look this up more closesly from another source** ## Chapter 3 ## Rtos services and facilities Besides the abillity to support a multithreaded model, RTOSs also needs to support services, often via so called **API's**. ### Intertask communication services ICS are used to communicate between different tasks. according to the book there are three main categories: - Task-owned facilities—attributes that an RTOS imparts to tasks that provide communication (input) facilities. The example that I will look at some more is signals. - Kernel objects-facillities provided by the RTOS which represents stand-alone communication or synchronization facilites. Example include: event flags, mailboxes, queues/pipes, semaphores and mutexes. - Message passing-a rationalized scheme where an RTOS allows the creation of message objects, which may be sent from one task to another, or to several others. This is fundamental to the kernel design and leads to the description of such a product as being a "message passing RTOS". Here the developer can thinks of some things. For example: > If an application needs several queues, but just a single mailbox, it may be more efficient to realize the mailbox with a single-entry queue. This object will be slightly nonoptimal, but all the mailbox handling code will not be included in the application and, hence, scalability will reduce the RTOS memory footprint. **All intertask-communication should be backed by further sources.** #### Shared variables or memory areas Here we refered to a memory area that is shared between tasks. Its a simple approach, but can lead to certain race conditions. This implies that all the shared resources are locked while used. How ever locking a resource can lead to a deadlock. This can be solved by disabling interrupts whilst accessing the resource inside the lock. #### Signals According to the author, signals is probably the simplest intertask communication facility. > They consist of a set of bit flags—there may be 8, 16, or 32, depending on the specific implementation—which is associated with a specific task. A signal flag (or several flags) may be set by any task using an OR type of operation. Only the task that owns the signals can read them. The reading process is generally destructive—that is, the flags are also cleared. #### Event flag groups Event flags are just as signals, bit oriented. However, they do not belong to any task and can therefore be refered to as **Independent kernel objects** Here i could maybe source the CDIO report aswell. > ny task may set and clear event flags using OR and AND operations. Likewise, any task may interrogate event flags using the same kind of operation. In many RTOSes, it is possible to make a blocking API call on an event flag combination; this means that a task may be suspended until a specific combination of event flags has been set. There may also be a “consume” option available, when interrogating event flags, such that all read flags are cleared. #### Semaphores Semaphores are also independent kernel objects. They provide a flagging mechanism which can be used to access a resource. Two main categories of semaphores include **Binary semaphores (0 or 1)**, **Counting semaphores**. #### Mailboxes also IKO. Used to transfer messages between tasks. #### Queues Kind of like a mailbox #### Mutexes Mutex stans for mutual exclusion semaphores. The implementation is similar to the one of a binary semaphore, but slightly more complex. A mutex is used to get a temporary ownership of a resource i.e. a lock to a resource. Only the task that locks the resource can unlock it. ### Other RTOS services Alongside task communication and synchronization, most RTOS's offer other services aswell. #### Task control This includes things such as, task creation and deletion. task suspend and resume. Task sleep. Task termination, etc... #### System information - Task information - Information about other kernel objects - RTOS version information #### Memory allocation Most RTOSes has its own implementation of memory allocation ***malloc() and free()***. Most embedded applications needs this. However, there could be problems with malloc and free in embedded applications. This i have read on many places. Make sure t o find a realiable source to support this claim, or atleast describe it. #### Memory partitions This is according to the author, a soltuion to dynamic memory allocation for real-time systems. it uses a memory block-based approach. where the blocks are referred to as partitions. #### Time - System time: for example a tick clock. - Service call timeouts: - Task sleep: - Application timers: #### Interrupts, drivers and I/O **Interrupts:** For interrupts, as stated before, every RTOS handles them differently. However, without some "safeguards" an ISR will simply steal CPU time and thus compromising the real-time behaviour of the RTOS. If an ISR makes API calls to for example ready another thread, the scheduler must be notified, in order for the program to function properly. **Drivers:** Each RTOS follows some kind of driver structure. Here we can take a look at different RTOS's for example zephyr and idk. FreeRTOS or NuttX. **I/O:** For example stream IO is used to make the connection between device drivers and for example printf(). see zephyr printk(). #### Diagnostics - API call parameter checks - Stack checking - Application diagnostics ### Beyond the kernel Mostly focused on networking and connectivity. Most RTOSs supports networking protocols such as **TCP/IP**, **USB**, **IEEE1394**, **Wireless**. This is necessary as most embedded systems are networking in one way or another, and in modern systems IoT applications are very commonly used. Also talks some about graphics, not interesting for us. Lastly talks about file systems, can be interesting for us, atleast to some extent.