gnuk/ChibiOS_2.0.8/docs/html/article_stop_os.html

133 lines
11 KiB
HTML
Raw Normal View History

2010-08-10 03:11:02 +00:00
<!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: How to cleanly stop the OS</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">
2010-11-22 05:53:37 +00:00
<!-- Generated by Doxygen 1.7.1 -->
2010-08-10 03:11:02 +00:00
<div class="navigation" id="top">
<div class="tabs">
2010-11-22 05:53:37 +00:00
<ul class="tablist">
2010-08-10 03:11:02 +00:00
<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>
2010-11-22 05:53:37 +00:00
<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_howtos.html">How To's</a> </li>
</ul>
2010-08-10 03:11:02 +00:00
</div>
</div>
2010-11-22 05:53:37 +00:00
<div class="header">
<div class="headertitle">
<h1>How to cleanly stop the OS </h1> </div>
</div>
2010-08-10 03:11:02 +00:00
<div class="contents">
2010-11-22 05:53:37 +00:00
<p>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.<br/>
2010-08-10 03:11:02 +00:00
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.<br/>
The shutdown operation should always be implemented into the <code>main()</code> 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".<br/>
The shutdown sequence should include the following steps, some steps are optional and depend on the application:</p>
<ul>
<li>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.<br/>
2010-11-22 05:53:37 +00:00
The system should be designed to request the thread termination using <code><a class="el" href="group__threads.html#ga7ea7371fa41598ebd523622587ce3f22" title="Requests a thread termination.">chThdTerminate()</a></code> and then wait its termination using <code><a class="el" href="group__threads.html#ga94a5727ecdbe0f738dfc8e1ede1c3409" title="Blocks the execution of the invoking thread until the specified thread terminates then the exit code ...">chThdWait()</a></code>. This phase can be skipped for non-critical threads.</li>
2010-08-10 03:11:02 +00:00
<li>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.</li>
<li>Invoke <a class="el" href="group__system.html#ga0f6e07fb701e2006ba40db2ede3a4b5b" title="Raises the system interrupt priority mask to the maximum level.">chSysDisable()</a>.</li>
<li>Stop the system timer whose service routine invokes <code><a class="el" href="group__system.html#ga1e42ee112f4a5d2c95be07d523c247be" title="Handles time ticks for round robin preemption and timer increments.">chSysTimerHandlerI()</a></code>.</li>
<li>Disable any other interrupt source that may invoke OS APIs. In general all the interrupt sources that have handlers declared by using the <code><a class="el" href="group__system.html#ga52426c607fac82b1e0ad975b367f95e9" title="Standard normal IRQ handler declaration.">CH_IRQ_HANDLER()</a></code> macro.</li>
<li>Perform any application related de-initialization.</li>
<li>Invoke <a class="el" href="group__system.html#ga2f54701f43490a5de272cc3d32962b51" title="Lowers the system interrupt priority mask to user level.">chSysEnable()</a>.</li>
</ul>
<p>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:</p>
<ul>
<li>Invoke <a class="el" href="group__system.html#ga0f6e07fb701e2006ba40db2ede3a4b5b" title="Raises the system interrupt priority mask to the maximum level.">chSysDisable()</a>.</li>
<li>Restart the system timer.</li>
<li>Reinitialize the OS by invoking <code><a class="el" href="group__system.html#gafe2c7de6567e98e487e009e81e3be10b" title="ChibiOS/RT initialization.">chSysInit()</a></code>.</li>
<li>Restart your device drivers using the <code>xxxStart()</code> methods.</li>
<li>Restart all your threads.</li>
</ul>
<h2>Example</h2>
<p>This is an example of an hypothetical application that have to shutdown the OS when a certain event is generated. </p>
<div class="fragment"><pre class="fragment"><span class="preprocessor">#include &quot;<a class="code" href="ch_8h.html" title="ChibiOS/RT main include file.">ch.h</a>&quot;</span>
<span class="preprocessor">#include &quot;<a class="code" href="hal_8h.html" title="HAL subsystem header.">hal.h</a>&quot;</span>
<span class="comment">/* A shutdown flag.*/</span>
<a class="code" href="group__types.html#ga7556af1cb61728b53228fa3af1c851de" title="Boolean, recommended the fastest signed.">bool_t</a> shutdown_required;
<span class="comment">/* Critical thread.*/</span>
<span class="keyword">static</span> <span class="keywordtype">void</span> my_thread(<span class="keywordtype">void</span> *p) {
<span class="keywordflow">while</span> (!<a class="code" href="group__threads.html#ga5591a9f97ff77b40bd5fc29f16f12a6b" title="Verifies if the current thread has a termination request pending.">chThdShouldTerminate</a>()) {
<span class="comment">/* Normal thread activity code.*/</span>
}
<span class="comment">/* Thread de-initialization before terminating, here you put the critical</span>
<span class="comment"> thread finalization code.*/</span>
<span class="keywordflow">return</span> 0;
}
<span class="comment">/* Main program, it is entered with interrupts disabled.*/</span>
<span class="keywordtype">void</span> main(<span class="keywordtype">void</span>) {
<span class="comment">/* HAL initialization, you need to do this just once.*/</span>
<a class="code" href="group___h_a_l.html#gafd89c1650df524d95aef39b8bc38170d" title="HAL initialization.">halInit</a>();
<span class="comment">/* Main loop, the main() function never exits.*/</span>
<span class="keywordflow">while</span> (TRUE) {
<a class="code" href="struct_thread.html" title="Structure representing a thread.">Thread</a> *tp;
shutdown_required = FALSE;
<span class="comment">/* ChibiOS/RT initialization. This function becomes an OS thread.*/</span>
<a class="code" href="group__system.html#gafe2c7de6567e98e487e009e81e3be10b" title="ChibiOS/RT initialization.">chSysInit</a>();
<span class="comment">/* Starting a device driver, SD2 in this case.*/</span>
<a class="code" href="group___s_e_r_i_a_l.html#ga5e77658b4f3b559927705dc8fbfbdfad" title="Configures and starts the driver.">sdStart</a>(&amp;<a class="code" href="group___a_t91_s_a_m7___s_e_r_i_a_l.html#ga12c0b7545295eca6231d6126153c86f0" title="USART1 serial driver identifier.">SD2</a>, NULL);
<span class="comment">/* Starting our critical thread.*/</span>
tp = <a class="code" href="group__threads.html#ga50b84e3e82a4e09c1066e1d422e4c780" title="Creates a new thread allocating the memory from the heap.">chThdCreateFromHeap</a>(NULL, <a class="code" href="group__core.html#gaf7a83c1c8bde96b77299c36dc598d33d" title="Computes the thread working area global size.">THD_WA_SIZE</a>(256),
<a class="code" href="group__scheduler.html#gad6a6b28f0c1cf8e0da714ef771fb90a0" title="Normal user priority.">NORMALPRIO</a>, my_thread, &amp;<a class="code" href="group___a_t91_s_a_m7___s_e_r_i_a_l.html#ga12c0b7545295eca6231d6126153c86f0" title="USART1 serial driver identifier.">SD2</a>);
<span class="comment">/* Main thread activity into a loop.*/</span>
<span class="keywordflow">while</span> (!shutdown_required) {
<span class="comment">/* Main activity, OS active until a shutdown becomes necessary.*/</span>
}
<span class="comment">/* Starting the shutdown sequence.*/</span>
<a class="code" href="group__threads.html#ga7ea7371fa41598ebd523622587ce3f22" title="Requests a thread termination.">chThdTerminate</a>(tp); <span class="comment">/* Requesting termination. */</span>
2010-11-22 05:53:37 +00:00
<a class="code" href="group__threads.html#ga94a5727ecdbe0f738dfc8e1ede1c3409" title="Blocks the execution of the invoking thread until the specified thread terminates then the exit code ...">chThdWait</a>(tp); <span class="comment">/* Waiting for the actual termination. */</span>
2010-08-10 03:11:02 +00:00
<a class="code" href="group___s_e_r_i_a_l.html#gacb106a30f8007afdf9eeaf8681dbd3cf" title="Stops the driver.">sdStop</a>(&amp;<a class="code" href="group___a_t91_s_a_m7___s_e_r_i_a_l.html#ga12c0b7545295eca6231d6126153c86f0" title="USART1 serial driver identifier.">SD2</a>); <span class="comment">/* Stopping serial port 2. */</span>
<a class="code" href="group__system.html#ga0f6e07fb701e2006ba40db2ede3a4b5b" title="Raises the system interrupt priority mask to the maximum level.">chSysDisable</a>();
stop_system_timer();
stop_any_other_interrupt();
<a class="code" href="group__system.html#ga2f54701f43490a5de272cc3d32962b51" title="Lowers the system interrupt priority mask to user level.">chSysEnable</a>();
<span class="comment">/* Now the main function is again a normal function, no more a</span>
<span class="comment"> OS thread.*/</span>
do_funny_stuff();
<span class="comment">/* Restarting the OS but you could also stop the system or trigger a</span>
<span class="comment"> reset instead.*/</span>
<a class="code" href="group__system.html#ga0f6e07fb701e2006ba40db2ede3a4b5b" title="Raises the system interrupt priority mask to the maximum level.">chSysDisable</a>();
}
}
</pre></div><p> 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. </p>
</div>
<hr size="1"><address style="text-align: right;"><small>
2010-11-30 04:54:43 +00:00
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>
2010-08-10 03:11:02 +00:00
</body>
</html>