gnuk/ChibiOS_2.0.2/docs/html/article__saveram.html
2010-08-10 12:11:02 +09:00

84 lines
5.5 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: Saving RAM by declaring thread functions &quot;noreturn&quot;</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.6.3 -->
<div class="navigation" id="top">
<div class="tabs">
<ul>
<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"><a class="el" href="main.html">ChibiOS/RT</a>&nbsp;&raquo;&nbsp;<a class="el" href="articles.html">Articles and Code Samples</a>&nbsp;&raquo;&nbsp;<a class="el" href="page__kb.html">Knowledge Base</a>
</div>
</div>
<div class="contents">
<h1><a class="anchor" id="article_saveram">Saving RAM by declaring thread functions "noreturn" </a></h1><p>One of the problems, when writing embedded multi-threaded applications, is that the thread functions do save the registers in the function entry code even if the system does not require it, exiting such a function would terminate the thread so there is no need to preserve the register values. This can waste tens of bytes for each thread.<br/>
Consider the following code: </p>
<div class="fragment"><pre class="fragment"><span class="preprocessor">#include &lt;<a class="code" href="ch_8h.html" title="ChibiOS/RT main include file.">ch.h</a>&gt;</span>
<span class="keyword">static</span> <a class="code" href="group__core.html#gac8b681d521d3b6c25e7a0304674732c9" title="Static working area allocation.">WORKING_AREA</a>(waMyThread, 64);
<span class="keyword">static</span> t_msg MyThread(<span class="keywordtype">void</span> *arg) {
<span class="keywordflow">while</span> (!chThdShoudTerminate()) {
<span class="comment">/* Do thread inner work */</span>
}
<span class="keywordflow">return</span> 1;
}
main() {
<a class="code" href="group__system.html#gafe2c7de6567e98e487e009e81e3be10b" title="ChibiOS/RT initialization.">chSysInit</a>();
...
<a class="code" href="group__threads.html#ga048e588238dd336c6059133b3d0c3435" title="Creates a new thread into a static memory area.">chThdCreateStatic</a>(waMyThread, <span class="keyword">sizeof</span>(waMyThread), <a class="code" href="group__scheduler.html#gad6a6b28f0c1cf8e0da714ef771fb90a0" title="Normal user priority.">NORMALPRIO</a>, MyThread, NULL);
...
}
</pre></div><p> The resulting ASM code for the thread function would be something like this: </p>
<div class="fragment"><pre class="fragment">MyThread:
stmfd sp!, {r4, r5, r6, lr}
...
ldmfd sp!, {r4, r5, r6, pc}
</pre></div><p> Being that function a thread there is no need to save those registers, in embedded applications often the RAM is a scarce resource. That space can be saved by modifying the code as follow, using some advanced GCC extensions: </p>
<div class="fragment"><pre class="fragment"><span class="preprocessor">#include &lt;<a class="code" href="ch_8h.html" title="ChibiOS/RT main include file.">ch.h</a>&gt;</span>
<span class="keyword">static</span> <a class="code" href="group__core.html#gac8b681d521d3b6c25e7a0304674732c9" title="Static working area allocation.">WORKING_AREA</a>(waMyThread, 64);
<a class="code" href="group___a_r_m_c_mx___c_o_r_e.html#gadb1276c6bdf715206ee694f223112e30" title="Stack and memory alignment enforcement.">__attribute__</a>((noreturn))
static <span class="keywordtype">void</span> MyThread(<span class="keywordtype">void</span> *arg) {
<span class="keywordflow">while</span> (!chThdShoudTerminate()) {
<span class="comment">/* Do thread inner work */</span>
}
<a class="code" href="group__threads.html#ga24ab3a3a4d70214ee360867a1c3c75ac" title="Terminates the current thread by specifying an exit status code.">chThdExit</a>(1);
}
main() {
<a class="code" href="group__system.html#gafe2c7de6567e98e487e009e81e3be10b" title="ChibiOS/RT initialization.">chSysInit</a>();
...
<a class="code" href="group__threads.html#ga048e588238dd336c6059133b3d0c3435" title="Creates a new thread into a static memory area.">chThdCreateStatic</a>(waMyThread, <span class="keyword">sizeof</span>(waMyThread), <a class="code" href="group__scheduler.html#gad6a6b28f0c1cf8e0da714ef771fb90a0" title="Normal user priority.">NORMALPRIO</a>,
(<a class="code" href="group__threads.html#gabfe59aa7d2ed1b8e57a2ce17bcbc1189" title="Thread function.">tfunc_t</a>)MyThread, NULL);
...
}
</pre></div><p> This will make GCC believe that the function cannot return and there is no need to save registers. The code will be a bit less readable and less portable on other compilers however. </p>
</div>
<hr size="1"><address style="text-align: right;"><small>
Generated on Sun Jul 11 13:13:10 2010 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.6.3</small></address>
</body>
</html>