gnuk/ChibiOS_2.0.8/docs/html/article_wakeup.html

143 lines
12 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 wake up a thread from an interrupt handler</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 wake up a thread from an interrupt handler </h1> </div>
</div>
2010-08-10 03:11:02 +00:00
<div class="contents">
2010-11-22 05:53:37 +00:00
<p>Waking up a thread after an hardware event is one of the most common tasks that an RTOS must be able to perform efficiently. In ChibiOS/RT there are several mechanisms that can be used, often each mechanism is best suited in a specific scenario.</p>
2010-08-10 03:11:02 +00:00
<h2>Synchronously waking up a specific thread</h2>
<p>A common situation is to have to synchronously wake up a specific thread. This can be accomplished without the use of any specific synchronization primitive, it uses the very efficient low level scheduler APIs, note that you can also optionally send a simple message from the IRQ handler to the thread. </p>
<div class="fragment"><pre class="fragment"><span class="keyword">static</span> <a class="code" href="struct_thread.html" title="Structure representing a thread.">Thread</a> *tp = NULL;
<span class="keywordtype">void</span> mythread(<span class="keywordtype">void</span> *p) {
<span class="keywordflow">while</span> (TRUE) {
<a class="code" href="group__types.html#ga35bcb0c321cd7bc45bf1a11fa17ebdd3" title="Message, use signed pointer equivalent.">msg_t</a> msg;
<span class="comment">// Waiting for the IRQ to happen.</span>
<a class="code" href="group__system.html#ga9f6573c0763d1e4e97c63c62edad6e42" title="Enters the kernel lock mode.">chSysLock</a>();
tp = <a class="code" href="group__threads.html#gaa36662628234799d205ff8c0cc6745c5" title="Returns a pointer to the current Thread.">chThdSelf</a>();
<a class="code" href="group__scheduler.html#ga97c1c514b755a1e71caf2f19c1ccf986" title="Puts the current thread to sleep into the specified state.">chSchGoSleepS</a>(PRSUSPENDED);
msg = <a class="code" href="group__threads.html#gaa36662628234799d205ff8c0cc6745c5" title="Returns a pointer to the current Thread.">chThdSelf</a>()-&gt;p_rdymsg; <span class="comment">// Retrieving the message, optional</span>
<a class="code" href="group__system.html#ga5a257fa58a09815eb64a45e2dfbdc22e" title="Leaves the kernel lock mode.">chSysUnlock</a>();
<span class="comment">// Perform processing here.</span>
}
}
<a class="code" href="group__system.html#ga52426c607fac82b1e0ad975b367f95e9" title="Standard normal IRQ handler declaration.">CH_IRQ_HANDLER</a>(myIRQ) {
<a class="code" href="group__system.html#ga0d78c6e90e5f0a4eb52aaab37e45a494" title="IRQ handler enter code.">CH_IRQ_PROLOGUE</a>();
<span class="comment">// Wakes up the thread.</span>
<a class="code" href="group__system.html#gab826c6d946aa1eb839751246ea158a72" title="Enters the kernel lock mode from within an interrupt handler.">chSysLockFromIsr</a>();
<span class="keywordflow">if</span> (tp != NULL) {
2010-11-22 05:53:37 +00:00
tp-&gt;p_rdymsg = (msg_t)55; <span class="comment">// Sending the message, optional</span>
2010-08-10 03:11:02 +00:00
<a class="code" href="group__scheduler.html#ga535d58cfb3436c8d4e4586c31c062298" title="Inserts a thread in the Ready List.">chSchReadyI</a>(tp);
tp = NULL;
}
<a class="code" href="group__system.html#ga984fb4af1420b6a217714ed317224ec0" title="Leaves the kernel lock mode from within an interrupt handler.">chSysUnlockFromIsr</a>().
<a class="code" href="group__system.html#ga864d6b8056d7d8f56322bbfcc8515d77" title="IRQ handler exit code.">CH_IRQ_EPILOGUE</a>();
}
</pre></div><h2>Synchronously waking up one of the waiting threads</h2>
<p>Lets assume you have a queue of waiting threads, you want to wake up the threads one by one in FIFO order, if there are no waiting threads then nothing happens.<br/>
This can be accomplished using a <code><a class="el" href="struct_semaphore.html" title="Semaphore structure.">Semaphore</a></code> object initialized to zero: </p>
<div class="fragment"><pre class="fragment"><a class="code" href="group__system.html#ga52426c607fac82b1e0ad975b367f95e9" title="Standard normal IRQ handler declaration.">CH_IRQ_HANDLER</a>(myIRQ) {
<a class="code" href="group__system.html#ga0d78c6e90e5f0a4eb52aaab37e45a494" title="IRQ handler enter code.">CH_IRQ_PROLOGUE</a>();
<span class="comment">// If there is at least one waiting thread then signal it.</span>
<a class="code" href="group__system.html#gab826c6d946aa1eb839751246ea158a72" title="Enters the kernel lock mode from within an interrupt handler.">chSysLockFromIsr</a>();
<span class="keywordflow">if</span> (<a class="code" href="group__semaphores.html#gadab3ccf8a34988ef6d410354b2648327" title="Returns the semaphore counter current value.">chSemGetCounterI</a>(&amp;mysem) &lt; 0)
<a class="code" href="group__semaphores.html#gaca0b70cf495a9cb7569e1cf5b07e2b3d" title="Performs a signal operation on a semaphore.">chSemSignalI</a>(&amp;mysem);
<a class="code" href="group__system.html#ga984fb4af1420b6a217714ed317224ec0" title="Leaves the kernel lock mode from within an interrupt handler.">chSysUnlockFromIsr</a>().
<a class="code" href="group__system.html#ga864d6b8056d7d8f56322bbfcc8515d77" title="IRQ handler exit code.">CH_IRQ_EPILOGUE</a>();
}
</pre></div><h2>Synchronously waking up all the waiting threads</h2>
<p>In this scenario you want to synchronously wake up all the waiting threads, if there are no waiting threads then nothing happens.<br/>
This can be accomplished using a <code><a class="el" href="struct_semaphore.html" title="Semaphore structure.">Semaphore</a></code> object initialized to zero: </p>
<div class="fragment"><pre class="fragment"><a class="code" href="group__system.html#ga52426c607fac82b1e0ad975b367f95e9" title="Standard normal IRQ handler declaration.">CH_IRQ_HANDLER</a>(myIRQ) {
<a class="code" href="group__system.html#ga0d78c6e90e5f0a4eb52aaab37e45a494" title="IRQ handler enter code.">CH_IRQ_PROLOGUE</a>();
<span class="comment">// Wakes up all the threads waiting on the semaphore.</span>
<a class="code" href="group__system.html#gab826c6d946aa1eb839751246ea158a72" title="Enters the kernel lock mode from within an interrupt handler.">chSysLockFromIsr</a>();
<a class="code" href="group__semaphores.html#gae7972b6b22b80ac09bac5a186277ab81" title="Performs a reset operation on the semaphore.">chSemResetI</a>(&amp;mysem);
<a class="code" href="group__system.html#ga984fb4af1420b6a217714ed317224ec0" title="Leaves the kernel lock mode from within an interrupt handler.">chSysUnlockFromIsr</a>().
<a class="code" href="group__system.html#ga864d6b8056d7d8f56322bbfcc8515d77" title="IRQ handler exit code.">CH_IRQ_EPILOGUE</a>();
}
</pre></div><h2>Asynchronously waking up a specific thread</h2>
<p>If you have to asynchronously wake up a specific thread then a simple event flags can be used. </p>
<div class="fragment"><pre class="fragment"><span class="keyword">static</span> <a class="code" href="struct_thread.html" title="Structure representing a thread.">Thread</a> *tp;
<span class="keywordtype">void</span> mythread(<span class="keywordtype">void</span> *p) {
tp = <a class="code" href="group__threads.html#gaa36662628234799d205ff8c0cc6745c5" title="Returns a pointer to the current Thread.">chThdSelf</a>();
<span class="keywordflow">while</span> (TRUE) {
<span class="comment">// Checks if an IRQ happened else wait.</span>
<a class="code" href="group__events.html#gabd731d3ed2f037b2409e370676575f8d" title="Waits for any of the specified events.">chEvtWaitAny</a>((<a class="code" href="group__types.html#gabff0c32475baf20ea8c5c710d6e8b708" title="Event Mask, recommended fastest unsigned.">eventmask_t</a>)1);
<span class="comment">// Perform processing here.</span>
}
}
<a class="code" href="group__system.html#ga52426c607fac82b1e0ad975b367f95e9" title="Standard normal IRQ handler declaration.">CH_IRQ_HANDLER</a>(myIRQ) {
<a class="code" href="group__system.html#ga0d78c6e90e5f0a4eb52aaab37e45a494" title="IRQ handler enter code.">CH_IRQ_PROLOGUE</a>();
<span class="comment">// Wakes up the thread.</span>
<a class="code" href="group__system.html#gab826c6d946aa1eb839751246ea158a72" title="Enters the kernel lock mode from within an interrupt handler.">chSysLockFromIsr</a>();
<a class="code" href="group__events.html#ga6c219038c3e618e2142c6e1601997907" title="Pends a set of event flags on the specified Thread.">chEvtSignalI</a>(tp, (<a class="code" href="group__types.html#gabff0c32475baf20ea8c5c710d6e8b708" title="Event Mask, recommended fastest unsigned.">eventmask_t</a>)1);
<a class="code" href="group__system.html#ga984fb4af1420b6a217714ed317224ec0" title="Leaves the kernel lock mode from within an interrupt handler.">chSysUnlockFromIsr</a>().
<a class="code" href="group__system.html#ga864d6b8056d7d8f56322bbfcc8515d77" title="IRQ handler exit code.">CH_IRQ_EPILOGUE</a>();
}
</pre></div><h2>Asynchronously waking up one or more threads</h2>
<p>By using event sources it is possible to asynchronously wake up one or more listener threads. The mechanism requires a single initialized <code><a class="el" href="struct_event_source.html" title="Event Source structure.">EventSource</a></code> object, all the threads registered as listeners on the event source will be broadcasted. </p>
<div class="fragment"><pre class="fragment"><a class="code" href="group__system.html#ga52426c607fac82b1e0ad975b367f95e9" title="Standard normal IRQ handler declaration.">CH_IRQ_HANDLER</a>(myIRQ) {
<a class="code" href="group__system.html#ga0d78c6e90e5f0a4eb52aaab37e45a494" title="IRQ handler enter code.">CH_IRQ_PROLOGUE</a>();
<span class="comment">// Pends an event flag on all the listening threads.</span>
<a class="code" href="group__system.html#gab826c6d946aa1eb839751246ea158a72" title="Enters the kernel lock mode from within an interrupt handler.">chSysLockFromIsr</a>();
<a class="code" href="group__events.html#gaa24d9bed5b676b577200c4a8ebe3b8a3" title="Signals all the Event Listeners registered on the specified Event Source.">chEvtBroadcastI</a>(&amp;my_event_source);
<a class="code" href="group__system.html#ga984fb4af1420b6a217714ed317224ec0" title="Leaves the kernel lock mode from within an interrupt handler.">chSysUnlockFromIsr</a>().
<a class="code" href="group__system.html#ga864d6b8056d7d8f56322bbfcc8515d77" title="IRQ handler exit code.">CH_IRQ_EPILOGUE</a>();
}
</pre></div> </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>