How to cleanly stop the OS

Stopping the OS should not be normally required but there are scenarios where one might want the complete control over the system again, for example entering into a bootload mode, or invoking some flashing algorithm locked in ROM.

The Problem

ChibiOS/RT does not have a shutdown API and there is a reason for this, stopping the kernel would not be enough, a well defined operations sequence is required.
The shutdown operation should always be implemented into the main() function because in that context the stack pointer is guaranteed to be in the area allocated by the startup code. Stopping from a thread would leave the stack pointer “somewhere”.

Stop Procedure

The shutdown sequence should include the following steps, some steps are optional and depend on the application:

  • Safely stop critical threads. For example a thread that uses a File System should flush all the modified buffers to the persistent storage before terminating.
    The system should be designed to request the thread termination using chThdTerminate() and then wait its termination using chThdWait(). This phase can be skipped for non-critical threads.
  • Invoke the xxxStop() method on all the active device drivers, this disables the interrupt sources used by the various peripherals. This is required in order to not have interrupts after the shutdown that may invoke OS primitives.
  • Invoke chSysDisable().
  • Stop the system timer whose service routine invokes chSysTimerHandlerI().
  • Disable any other interrupt source that may invoke OS APIs. In general all the interrupt sources that have handlers declared by using the CH_IRQ_HANDLER() macro must be disabled or system code could be invoked while the OS is inactive.
  • Perform any application related de-initialization.
  • Invoke chSysEnable().

Now the OS is stopped and you can safely assume there are nothing going on under the hood.

Restart Procedure

It is also possible to restart the OS after finishing your critical operations using the following sequence:

  • Invoke chSysDisable().
  • Restart the system timer.
  • Reinitialize the OS by invoking chSysInit().
  • Restart your device drivers using the various xxxStart() methods.
  • Restart all your threads.


This is an example of an hypothetical application that have to shutdown the OS when a certain event is generated.

#include "ch.h"
#include "hal.h"
/* A shutdown flag.*/
bool_t shutdown_required;
/* Critical thread.*/
static void my_thread(void *p) {
  while (!chThdShouldTerminate()) {
    /* Normal thread activity code.*/
  /* Thread de-initialization before terminating, here you put the critical
     thread finalization code.*/
  return 0;
/* Main program, it is entered with interrupts disabled.*/
void main(void) {
  /* HAL initialization, you need to do this just once.*/
  /* Main loop, the main() function never exits.*/
  while (TRUE) {
    Thread *tp;
    shutdown_required = FALSE;
    /* ChibiOS/RT initialization. This function becomes an OS thread.*/
    /* Starting a device driver, SD2 in this case.*/
    sdStart(&SD2, NULL);
    /* Starting our critical thread.*/
    tp = chThdCreateFromHeap(NULL, THD_WA_SIZE(256),
                             NORMALPRIO, my_thread, &SD2);
    /* Main thread activity into a loop.*/
    while (!shutdown_required) {
      /* Main activity, OS active until a shutdown becomes necessary.*/
    /* Starting the shutdown sequence.*/
    chThdTerminate(tp);     /* Requesting termination.                  */
    chThdWait(tp);          /* Waiting for the actual termination.      */
    sdStop(&SD2);           /* Stopping serial port 2.                  */
    /* Now the main function is again a normal function, no more a
       OS thread.*/
    /* Restarting the OS but you could also stop the system or trigger a
       reset instead.*/

As you can see it is possible to jump in and out of the “OS mode” quite easily. Note that this is just an example, the real code could be very different depending on your requirements.

chibios/howtos/stop_os.txt · Last modified: 2011/10/03 20:50 by giovanni
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.3