ChibiOS General Architecture

In this chapter we will start describing specifically ChibiOS in its high level details. The first thing that should be specified is that ChibiOS does not refer to just an RTOS scheduler but to a set of embedded components part of an overall architecture defining a typical embedded system:

  • RT, the RTOS scheduler. RT is a very high performance RTOS with a complete set of features and small footprint. It is what we cover in this book.
  • NIL, an alternate RTOS. NIL is compatible with RT but its internal architecture is completely different, It is designed for minimal code size.
  • OSLIB, an RTOS extension library. It sits on top of RT or NIL and adds an incredible set of higher level services.
  • HAL, the Hardware Abstraction Layer enclosing abstract drivers for most common peripherals.
  • SB, an extension for RT or NIL offering isolated sandboxes where to run “unsafe” code. The code in the sandbox is unable to crash the whole system.

Application Model

Now we need to define the kind of applications we can create with ChibiOS, the application model is: Single Application with Multiple Threads. This means:

  • The runtime environment is trusted, the application does not need to defend from itself. Non-trusted code can be handled using the SB subsystem.
  • Multiple threads are part of the application and share the address space. There is no protection between thread and thread and no virtualization.
  • Application and Operating System are linked together into a single memory image, a single program.
  • There is no concept of “loading an application”.

The Big Picture

The ChibiOS system is strongly layered, the structure is always the same regardless of the target architecture:

The various elements will be described in greater details in next chapters, this is a brief description:

Startup Code

It is the code executed after the reset. The startup code is responsible for:

  1. Core initialization.
  2. Stacks initialization.
  3. C Runtime initialization.
  4. Calling the main() function.

In ChibiOS the startup code is provided with the OS and is located under ./os/common/ports for the various supported architectures and compilers, scatter files and everything else is required for system startup are also provided.

Application

It is the user code, ChibiOS provides a simple template of main() function, everything else starts from there.

ChibiOS/RT

This is the RT scheduler kernel which is divided in two internal layers:

  • RT Portable Kernel. It is the part of the RTOS kernel which is architecture and compiler independent. The RT code is located under ./os/rt.
  • RT Port Layer. It is the part of the RTOS kernel specific for one architecture and one or more compilers. The RT port code is located under ./os/common/ports.

ChibiOS/HAL

HAL is the acronym for Hardware Abstraction Layer, a set of device drivers for the peripherals most commonly found in micro-controllers. The HAL is split in several layers:

  • HAL API Layer. This layer contains a series of portable device drivers. The HAL portable code is located under ./os/hal.
  • HAL Port Layer. This is the device driver implementations for a specific micro-controller or family of micro-controllers. The HAL port code is located under ./os/hal/ports.
  • HAL Board Layer. This module contains all details of a specific board mounting the micro-controller. Board level initialization is performed in this module. The HAL boards code is located under ./os/hal/boards.
  • HAL OSAL Layer. This is the Operating System Abstraction Layer. The HAL has to use some RTOS services in order to implement its functionality. The access to the RTOS services is done through this abstraction layer in order to not lock the HAL to a specific RTOS. The HAL OSAL code is located under ./os/hal/osal.

Considerations

Note that in the above architecture it is clear that RT does not need HAL and can be used alone if HAL is not required. On the other hand, in this architecture HAL uses RT's services through the OSAL but it could use another RTOS or even work without RTOS by implementing an OSAL over the bare metal machine. The examples in this book will cover RT and HAL both together and alone.

Abstraction of Details

An important point about having an Operating System is the abstraction of the inner details in order to keep the general application code as portable as possible. Code written over well designed abstractions increase the portability of applications to newer micro-controllers, even from different vendors. Code portability is hard in embedded software, there are an amazing series of details which are specific of the compiler, the architecture and the specific micro-controllers. An incomplete list is:

  • Non-standard C constructs required in order to do even simple things like writing ISRs.
  • ISRs themselves differ from architecture to architecture.
  • Interrupts architecture is often different.
  • Peripheral interfaces are different.
  • Vendor-provided libraries are incompatible even remaining within the same vendor.

In general there is lack of complete solutions, developers are responsible for integrating bits and pieces of code from different sources into a working system, often most effort goes into resolving integration problems.

ChibiOS offers an end-to-end solution, the provided components are already well integrated each other and the application can be written to ignore most HW details using the provided high level API. In ChibiOS the API is constant, the HW-specific details do exist, of course, but are encapsulated into platform-dependent configuration files. The application can be ported as long there are equivalent features and new configuration files are created, the rest of the code remains the same. Among the abstractions provided by RT and HAL:

  • Peripherals seen as “streams” or “block devices” using C++/Java-like interfaces (but still written in C).
  • Standard API for most common peripherals like: ADC, CAN, DAC, GPIO, I2C, Input Caputure, PWM, SPI, Timers, UART, USB, Ethernet and many others.
  • No need to write interrupt handlers, everything is encapsulated into drivers, drivers expose notification callbacks to the application where required. Optimal use of DMA, or other performance-enhancing features, is performed in the drivers transparently to the user, where applicable.
  • If an ISR is needed, even the ISR code is abstracted into macro constructs and is platform-independent.
  • The RTOS API is exactly the same across all architectures.
  • Timeout handling at API level for all primitives and peripheral drivers where applicable.