/* ChibiOS/RT - Copyright (C) 2006-2007 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_stacks Stacks and stack sizes * In a RTOS like ChibiOS/RT there are several dedicated stacks, each stack * has a dedicated RAM space that must have a correctly sized assigned area. *

The stacks

* There are several stacks in the systems, some are always present, some * others are present only in some architectures: * - Main stack, this stack is used by the @p main() function and the * thread that execute it. It is not a normal thread stack because it is * initialized in the startup code and its size is defined in a port * dependent way. Details are in the various ports documentation. * - Interrupt Stack, some architectures have a dedicated interrupt * stack. This is an important feature in a multithreaded environment, * without a dedicated interrupt stack each thread has to reserve * enough space, for interrupts servicing, within its own stack. This space, * multiplied by the total threads number, can amount to a significant RAM * overhead. * - Thread Stack, each thread has a dedicated stack for its own * execution and context switch. * - Other Stacks, some architectures (ARM) can have other stacks but * the OS does not directly use any of them. * . *

Risks

* The most critical thing when writing an embedded multithreaded application * is to determine the correct stack size for main, threads and, when present, * interrupts.
* Assign too much space to a stack wastes RAM, assign too little space * leads to crashes or, worst scenario, hard to track instability. * *

Assigning the correct size

* You may try to examine the asm listings in order to calculate the exact * stack requirements but this requires much time, experience and patience.
* An alternative way is to use an interactive method. Follow this procedure * for each thread in the system: * - Enable the following debug options in the kernel: * - @p CH_DBG_ENABLE_STACK_CHECK, this enables a stack check before any * context switch. This option halts the system in @p chSysHalt() just * before a stack overflow happens. The halt condition is caused by * a stack overflow when the global variable @p panic_msg is set to * @p NULL, normally it would point to a panic message. * - @p CH_DBG_FILL_THREADS, this option fills the threads working area * with an easily recognizable pattern (0x55). * - Assign a large and safe size to the thread stack, as example 256 bytes * on 32 MCUs, 128 bytes on 8/16 bit MCUs. This is almost always too much * for simple threads. * - Run the application, if the application crashes or halts then increase * the stack size and repeat (you know how to use the debugger right?). * - Let the application run and make sure to trigger the thread in a way to * make it follow most or all its code paths. If the application crashes or * halts then increase the stack size and repeat. * - Stop the application using the debugger and examine the thread working * area (you know what a map file is, right?). You can see that the thread * stack overwrote the fill pattern (0x55) from the top of the working area * downward. You can estimate the excess stack by counting the untouched * locations. * - Trim down the stack size and repeat until the application still runs * correctly and you have a decent margin in the stack. * - Repeat for all the thread classes in the system. * - Turn off the debug options. * - Done. * . *

Final Notes

* Some useful info: * - Stack overflows are the most common problems source during development, * when in trouble with crashes or anomalous behaviors always first verify * stack sizes. * - The required stack size can, and very often does change when changing * compiler vendor, compiler version, compiler options, code type (ARM * or THUMB as example). * - Code compiled in THUMB mode uses more stack space compared to the * same code compiled in ARM mode. In GCC this is related to lack of tail * calls optimizations in THUMB mode, this is probably true also in other * compilers. * - Speed optimized code often requires less stack space compared to space * optimized code. Be careful when changing optimizations. * - The interrupts space overhead on the thread stacks (@p INT_REQUIRED_STACK * defined in @p chcore.h) is included in the total working area size * by the system macros @p THD_WA_SIZE() and @p WORKING_AREA().
* The correct way to reserve space into the thread stacks for interrupts * processing is to override the @p INT_REQUIRED_STACK default value. * Architectures with a dedicated interrupt stack do not require changes * to this value. Resizing of the global interrupt stack may be required * instead. * - Often is a good idea to have some extra space in stacks unless you * are really starved on RAM. Anyway optimize stack space at the very * end of your development cycle. * . */