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. In this book we will cover:

  • ChibiOS/RT, the RTOS scheduler. RT is a very high performance RTOS with a complete set of features and small footprint.
  • ChibiOS/HAL, the Hardware Abstraction Layer enclosing abstract drivers for most common peripherals.

System Requirements

The first thing to explain are the target systems for ChibiOS application. ChibiOS is meant to be used in 8, 16 and 32 bits micro-controllers starting from 2KB of RAM and 16KB of flash. It can be ported to any CPU architecture as long:

  • There is a real stack pointer.
  • There is support for a C99 compiler.

A clean CPU architecture usually makes the porting process easier.

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.
  • 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 “application load” except a bootloader is used that can take care of that.

The Big Picture

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

General 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/rt/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 with 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 peripheral drivers where applicable.