/* ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. This file is part of ChibiOS/RT. ChibiOS/RT is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. ChibiOS/RT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /** * @page article_stop_os 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. * As example entering into a bootload mode, or invoking some flashing * algorithm locked in ROM.
* 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 @p 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".
* The shutdown sequence should include the following steps, some steps * are optional and depend on the application: * - Safely stop critical threads. As 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 * @p chThdTerminate() and then wait its termination using @p 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 * @p chSysTimerHandlerI(). * - Disable any other interrupt source that may invoke OS APIs. In general * all the interrupt sources that have handlers declared by using the * @p CH_IRQ_HANDLER() macro. * - 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. From here you can also restart the OS after finishing your * critical operations using the following sequence: * - Invoke chSysDisable(). * - Restart the system timer. * - Reinitialize the OS by invoking @p chSysInit(). * - Restart your device drivers using the @p xxxStart() methods. * - Restart all your threads. * . *

Example

* This is an example of an hypothetical application that have to shutdown * the OS when a certain event is generated. * @code #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.*/ halInit(); /* Main loop, the main() function never exits.*/ while (TRUE) { Thread *tp; shutdown_required = FALSE; /* ChibiOS/RT initialization. This function becomes an OS thread.*/ chSysInit(); /* 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. */ chSysDisable(); stop_system_timer(); stop_any_other_interrupt(); chSysEnable(); /* Now the main function is again a normal function, no more a OS thread.*/ do_funny_stuff(); /* Restarting the OS but you could also stop the system or trigger a reset instead.*/ chSysDisable(); } } * @endcode * 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. */