gnuk/ChibiOS_2.0.8/docs/html/article_timing.html
2010-11-30 13:54:43 +09:00

92 lines
6.7 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: Reliable timings using Threads</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>Reliable timings using Threads </h1> </div>
</div>
<div class="contents">
<p>One common task is to have threads do something at regular, scheduled, intervals. An obvious solution is to write something like this: </p>
<div class="fragment"><pre class="fragment"><a class="code" href="group__types.html#ga35bcb0c321cd7bc45bf1a11fa17ebdd3" title="Message, use signed pointer equivalent.">msg_t</a> my_thread(<span class="keywordtype">void</span> *param) {
<span class="keywordflow">while</span> (TRUE) {
do_something();
<a class="code" href="group__threads.html#ga5aebc25e053a0094714abce4cad9f56f" title="Delays the invoking thread for the specified number of milliseconds.">chThdSleepMilliseconds</a>(1000); <span class="comment">// Fixed interval</span>
}
}
</pre></div><p> This example works well assuming that the <code>do_something()</code> execution time is well below the system tick period and that <code>my_thread()</code> is not preempted by other threads that could insert long intervals.<br/>
If the above conditions are not satisfied you may have <code>do_something()</code> executed at irregular intervals, as example:<br/>
<br/>
T0...T0+1000...T0+2002...T0+3002...T0+4005...etc.<br/>
<br/>
Also note that the error increases over time and this kind of behavior can lead to anomalies really hard to debug. </p>
<h2>A better solution</h2>
<p>It is possible to rewrite the above code using absolute deadlines rather than fixed intervals: </p>
<div class="fragment"><pre class="fragment"><a class="code" href="group__types.html#ga35bcb0c321cd7bc45bf1a11fa17ebdd3" title="Message, use signed pointer equivalent.">msg_t</a> my_thread(<span class="keywordtype">void</span> *param) {
systick_t time = <a class="code" href="group__time.html#ga137c8f67c450f34416a786d169be90e2" title="Current system time.">chTimeNow</a>(); <span class="comment">// T0</span>
<span class="keywordflow">while</span> (TRUE) {
time += <a class="code" href="group__time.html#ga0a7e7bc6c6225bd9652c4f1567f1bc6a" title="Time conversion utility.">MS2ST</a>(1000); <span class="comment">// Next deadline</span>
do_something();
<a class="code" href="group__threads.html#ga9e6e2f8d46d415e8f0862daf0be1d984" title="Suspends the invoking thread until the system time arrives to the specified value.">chThdSleepUntil</a>(time);
}
}
</pre></div><p> Using this code <code>do_something()</code> will always be executed at an absolute deadline time and the error will not accumulate over time regardless of the execution time and delays inserted by other threads.<br/>
Note that this solution requires that the <code>do_something()</code> execution time must not exceed the deadline or the thread would stay sleeping into <code><a class="el" href="group__threads.html#ga9e6e2f8d46d415e8f0862daf0be1d984" title="Suspends the invoking thread until the system time arrives to the specified value.">chThdSleepUntil()</a></code>.</p>
<h2>A different way</h2>
<p>Another way to perform activities at regular intervals is the use of a virtual timer. Virtual timers are able to generate callbacks at scheduled intervals. Virtual timers are one shot timers so you need to restart them from within the callback if you need a periodic timer like in this case. </p>
<div class="fragment"><pre class="fragment"><a class="code" href="struct_virtual_timer.html" title="Virtual Timer descriptor structure.">VirtualTimer</a> vt;
<span class="keywordtype">void</span> do_something(<span class="keywordtype">void</span> *p) {
<a class="code" href="group__time.html#ga1c44c3a0bc64b2954d95cd98b2e7124e" title="Enables a virtual timer.">chVTSetI</a>(&amp;vt, <a class="code" href="group__time.html#ga0a7e7bc6c6225bd9652c4f1567f1bc6a" title="Time conversion utility.">MS2ST</a>(1000), do_something, p); <span class="comment">// Restarts the timer.</span>
<span class="comment">// Periodic code here.</span>
}
<span class="keywordtype">int</span> main(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span> **argv) {
<a class="code" href="group__system.html#ga9f6573c0763d1e4e97c63c62edad6e42" title="Enters the kernel lock mode.">chSysLock</a>();
<a class="code" href="group__time.html#ga1c44c3a0bc64b2954d95cd98b2e7124e" title="Enables a virtual timer.">chVTSetI</a>(&amp;vt, <a class="code" href="group__time.html#ga0a7e7bc6c6225bd9652c4f1567f1bc6a" title="Time conversion utility.">MS2ST</a>(1000), do_something, NULL); <span class="comment">// Starts the timer.</span>
<a class="code" href="group__system.html#ga5a257fa58a09815eb64a45e2dfbdc22e" title="Leaves the kernel lock mode.">chSysUnlock</a>();
...
}
</pre></div><p> Note that the callback code is executed from within the I-Locked state (see <a class="el" href="concepts.html#system_states">System States</a>) so you can only execute I-Class APIs from there (see <a class="el" href="concepts.html#api_suffixes">API Names Suffixes</a>).<br/>
This solution has the advantage to not require a dedicated thread and thus uses much less RAM but the periodic code must have a very short execution time or it would degrade the overall system response time. </p>
</div>
<hr size="1"><address style="text-align: right;"><small>
Generated on Sun Nov 28 2010 14:09:56 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>