ChibiOS/RT  6.1.2
Kernel Concepts

ChibiOS Kernel Concepts This article applies to both RT and NIL kernels, many concepts are also applicable to HAL (states and API classes).

Naming Conventions

ChibiOS/RT and ChibiOS/NIL APIs are named following this convention: ch<group><action><suffix>(). Examples of groups are: Sys, Sch, Time, VT, Thd, Sem, etc.

API Name Suffixes

The suffix can be one of the following:

  • None, APIs without any suffix can be invoked only from the user code in the Normal state unless differently specified. See System States.
  • "I", I-Class APIs are invokable only from the I-Locked or S-Locked states. See System States. This kind of functions never reschedule internally and are meant to be used from interrupt handlers. If used from thread level then an explicit reschedule operation could be necessary before leaving the containing critical zone.
  • "S", S-Class APIs are invokable only from the S-Locked state. See System States. This kind of functions can reschedule internally but are not guaranteed to do so necessarily. For example a wait function on a semaphore can reschedule or not reschedule depending on the semaphore state.
  • "X", X-Class APIs are invokable from any context.

Examples: chThdCreateStatic(), chSemSignalI(), chThdCreateStatic().

Interrupt Classes

In ChibiOS/RT there are three logical interrupt classes:

  • Regular Interrupts. Maskable interrupt sources that cannot preempt (small parts of) the kernel code and are thus able to invoke operating system APIs from within their handlers. The interrupt handlers belonging to this class must be written following some rules. See the system APIs group and the web article How to write interrupt handlers.
  • Fast Interrupts. Maskable interrupt sources with the ability to preempt the kernel code and thus have a lower latency and are less subject to jitter, see the web article Response Time and Jitter. Such sources are not supported on all the architectures.
    Fast interrupts are not allowed to invoke any operating system API from within their handlers. Fast interrupt sources may, however, pend a lower priority regular interrupt where access to the operating system is possible.
  • Non Maskable Interrupts. Non maskable interrupt sources are totally out of the operating system control and have the lowest latency. Such sources are not supported on all the architectures.

The mapping of the above logical classes into physical interrupts priorities is, of course, port dependent. See the documentation of the various ports for details.

System States

When using ChibiOS/RT the system can be in one of the following logical operating states:

  • Init. When the system is in this state all the maskable interrupt sources are disabled. In this state it is not possible to use any system API except chSysInit(). This state is entered after a physical reset.
  • Normal. All the interrupt sources are enabled and the system APIs are accessible, threads are running.
  • Suspended. In this state the fast interrupt sources are enabled but the regular interrupt sources are not. In this state it is not possible to use any system API except chSysDisable() or chSysEnable() in order to change state.
  • Disabled. When the system is in this state both the maskable regular and fast interrupt sources are disabled. In this state it is not possible to use any system API except chSysSuspend() or chSysEnable() in order to change state.
  • Sleep. Architecture-dependent low power mode, the idle thread goes in this state and waits for interrupts, after servicing the interrupt the Normal state is restored and the scheduler has a chance to reschedule.
  • S-Locked. Kernel locked and regular interrupt sources disabled. Fast interrupt sources are enabled. S-Class and I-Class APIs are invokable in this state.
  • I-Locked. Kernel locked and regular interrupt sources disabled. I-Class APIs are invokable from this state.
  • Serving Regular Interrupt. No system APIs are accessible but it is possible to switch to the I-Locked state using chSysLockFromIsr() and then invoke any I-Class API. Interrupt handlers can be preemptable on some architectures thus is important to switch to I-Locked state before invoking system APIs.
  • Serving Fast Interrupt. System APIs are not accessible.
  • Serving Non-Maskable Interrupt. System APIs are not accessible.
  • Halted. All interrupt sources are disabled and system stopped into an infinite loop. This state can be reached if the debug mode is activated and an error is detected or after explicitly invoking chSysHalt().

Note that the above states are just Logical States that may have no real associated machine state on some architectures. The following diagram shows the possible transitions between the states:

dot_inline_dotgraph_1.png

Note, the SFI, Halted and SNMI states were not shown because those are reachable from most states:

dot_inline_dotgraph_2.png
dot_inline_dotgraph_3.png
Attention
* except: Init, Halt, SNMI, Disabled.

Scheduling

The strategy is very simple the currently ready thread with the highest priority is executed. If more than one thread with equal priority are eligible for execution then they are executed in a round-robin way, the CPU time slice constant is configurable. The ready list is a double linked list of threads ordered by priority.

dot_inline_dotgraph_4.png


Note that the currently running thread is not in the ready list, the list only contains the threads ready to be executed but still actually waiting.

Thread States

The image shows how threads can change their state in ChibiOS/RT.

dot_inline_dotgraph_5.png

Priority Levels

Priorities in ChibiOS/RT are a contiguous numerical range but the initial and final values are not enforced.
The following table describes the various priority boundaries (from lowest to highest):

  • IDLEPRIO, this is the lowest priority level and is reserved for the idle thread, no other threads should share this priority level. This is the lowest numerical value of the priorities space.
  • LOWPRIO, the lowest priority level that can be assigned to an user thread.
  • NORMALPRIO, this is the central priority level for user threads. It is advisable to assign priorities to threads as values relative to NORMALPRIO, as example NORMALPRIO-1 or NORMALPRIO+4, this ensures the portability of code should the numerical range change in future implementations.
  • HIGHPRIO, the highest priority level that can be assigned to an user thread.
  • ABSPRO, absolute maximum software priority level, it can be higher than HIGHPRIO but the numerical values above HIGHPRIO up to ABSPRIO (inclusive) are reserved. This is the highest numerical value of the priorities space.

Thread Working Area

Each thread has its own stack, a Thread structure and some preemption areas. All the structures are allocated into a "Thread Working Area", a thread private heap, usually statically declared in your code. Threads do not use any memory outside the allocated working area except when accessing static shared data.

workspace.png


Note that the preemption area is only present when the thread is not running (switched out), the context switching is done by pushing the registers on the stack of the switched-out thread and popping the registers of the switched-in thread from its stack. The preemption area can be divided in up to three structures:

  • External Context.
  • Interrupt Stack.
  • Internal Context.

See the port documentation for details, the area may change on the various ports and some structures may not be present (or be zero-sized).