gnuk/ChibiOS_2.0.6/docs/html/article_stacks.html
2010-11-22 14:53:37 +09:00

87 lines
7.0 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>ChibiOS/RT: Stacks and stack sizes</title>
<link href="custom.css" rel="stylesheet" type="text/css">
<link href="tabs.css" rel="stylesheet" type="text/css">
</head><body>
<table style="text-align: center; width: 100%;" border="0"
cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="width: 80px;"><img alt="ChibiOS/RT Logo" src="logo_small.png"></td>
<td><big><big>ChibiOS/RT</big></big><br><br>Architecture - Reference Manual - Guides</td>
<td style="width: 80px;"></td>
</tr>
</tbody>
</table>
<hr size="1">
<!-- Generated by Doxygen 1.7.1 -->
<div class="navigation" id="top">
<div class="tabs">
<ul class="tablist">
<li><a href="main.html"><span>Main&nbsp;Page</span></a></li>
<li><a href="modules.html"><span>Modules</span></a></li>
<li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
<li><a href="files.html"><span>Files</span></a></li>
</ul>
</div>
<div class="navpath">
<ul>
<li><a class="el" href="main.html">ChibiOS/RT</a> </li>
<li><a class="el" href="articles.html">Articles and Code Samples</a> </li>
<li><a class="el" href="page_kb.html">Knowledge Base</a> </li>
</ul>
</div>
</div>
<div class="header">
<div class="headertitle">
<h1>Stacks and stack sizes </h1> </div>
</div>
<div class="contents">
<p>In an RTOS like ChibiOS/RT there are several dedicated stacks, each stack has a dedicated RAM space that must have a correctly sized assigned area. </p>
<h2>The stacks</h2>
<p>There are several stacks in the systems, some are always present, some others are present only in some architectures:</p>
<ul>
<li><b>Main stack</b>, this stack is used by the <code>main()</code> 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.</li>
<li><b>Interrupt Stack</b>, 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.</li>
<li><b><a class="el" href="struct_thread.html" title="Structure representing a thread.">Thread</a> Stack</b>, each thread has a dedicated stack for its own execution and context switch.</li>
<li><b>Other Stacks</b>, some architectures (ARM) can have other stacks but the OS does not directly use any of them.</li>
</ul>
<h2>Risks</h2>
<p>The most critical thing when writing an embedded multithreaded application is to determine the correct stack size for main, threads and, when present, interrupts.<br/>
Assigning too much space to a stack is a waste of RAM, assigning too little space leads to crashes or, worst scenario, hard to track instability.</p>
<h2>Assigning the correct size</h2>
<p>You may try to examine the asm listings in order to calculate the exact stack requirements but this requires much time, experience and patience.<br/>
An alternative way is to use an interactive method. Follow this procedure for each thread in the system:</p>
<ul>
<li>Enable the following debug options in the kernel:<ul>
<li><code>CH_DBG_ENABLE_STACK_CHECK</code>, this enables a stack check before any context switch. This option halts the system in <code><a class="el" href="group__system.html#gad43b78f160a2c983792af3041cc4a536" title="Halts the system.">chSysHalt()</a></code> just before a stack overflow happens. The halt condition is caused by a stack overflow when the global variable <code>panic_msg</code> is set to <code>NULL</code>, normally it would point to a panic message.</li>
<li><code>CH_DBG_FILL_THREADS</code>, this option fills the threads working area with an easily recognizable pattern (0x55).</li>
</ul>
</li>
<li>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.</li>
<li>Run the application, if the application crashes or halts then increase the stack size and repeat (you know how to use the debugger right?).</li>
<li>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.</li>
<li>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.</li>
<li>Trim down the stack size and repeat until the application still runs correctly and you have a decent margin in the stack.</li>
<li>Repeat for all the thread classes in the system.</li>
<li>Turn off the debug options.</li>
<li>Done.</li>
</ul>
<h2>Final Notes</h2>
<p>Some useful info:</p>
<ul>
<li>Stack overflows are the most common problems source during development, when in trouble with crashes or anomalous behaviors always first verify stack sizes.</li>
<li>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).</li>
<li>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.</li>
<li>Speed optimized code often requires less stack space compared to space optimized code. Be careful when changing optimizations.</li>
<li>The interrupts space overhead on the thread stacks (<code>INT_REQUIRED_STACK</code> defined in <code>chcore.h</code>) is included in the total working area size by the system macros <code><a class="el" href="group__core.html#gaf7a83c1c8bde96b77299c36dc598d33d" title="Computes the thread working area global size.">THD_WA_SIZE()</a></code> and <code><a class="el" href="group__core.html#gac8b681d521d3b6c25e7a0304674732c9" title="Static working area allocation.">WORKING_AREA()</a></code>.<br/>
The correct way to reserve space into the thread stacks for interrupts processing is to override the <code>INT_REQUIRED_STACK</code> 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.</li>
<li>Often is a good idea to have some extra space in stacks unless you are really starved on RAM. Anyway, it is best to optimize stack space at the very end of your development cycle.</li>
</ul>
</div>
<hr size="1"><address style="text-align: right;"><small>
Generated on Sun Oct 24 2010 09:40:45 for ChibiOS/RT by&nbsp;<a href="http://www.doxygen.org/index.html"><img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.7.1</small></address>
</body>
</html>