]> begriffs open source - cmsis/blob - main/RTOS2/html/rtos2_tutorial.html
Initial contribution
[cmsis] / main / RTOS2 / html / rtos2_tutorial.html
1 <!-- HTML header for doxygen 1.9.6-->
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
4 <head>
5 <meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
6 <meta http-equiv="X-UA-Compatible" content="IE=11"/>
7 <meta name="viewport" content="width=device-width, initial-scale=1"/>
8 <title>CMSIS-RTOS2: Tutorial</title>
9 <link href="doxygen.css" rel="stylesheet" type="text/css"/>
10 <link href="tabs.css" rel="stylesheet" type="text/css"/>
11 <link href="extra_navtree.css" rel="stylesheet" type="text/css"/>
12 <link href="extra_stylesheet.css" rel="stylesheet" type="text/css"/>
13 <link href="extra_search.css" rel="stylesheet" type="text/css"/>
14 <script type="text/javascript" src="jquery.js"></script>
15 <script type="text/javascript" src="dynsections.js"></script>
16 <script type="text/javascript" src="printComponentTabs.js"></script>
17 <script type="text/javascript" src="footer.js"></script>
18 <script type="text/javascript" src="navtree.js"></script>
19 <link href="navtree.css" rel="stylesheet" type="text/css"/>
20 <script type="text/javascript" src="resize.js"></script>
21 <script type="text/javascript" src="navtreedata.js"></script>
22 <script type="text/javascript" src="navtree.js"></script>
23 <link href="search/search.css" rel="stylesheet" type="text/css"/>
24 <script type="text/javascript" src="search/searchdata.js"></script>
25 <script type="text/javascript" src="search/search.js"></script>
26 <script type="text/javascript">
27 /* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
28   $(document).ready(function() { init_search(); });
29 /* @license-end */
30 </script>
31 <script type="text/javascript" src="darkmode_toggle.js"></script>
32 <link href="extra_stylesheet.css" rel="stylesheet" type="text/css"/>
33 <link href="extra_navtree.css" rel="stylesheet" type="text/css"/>
34 <link href="extra_search.css" rel="stylesheet" type="text/css"/>
35 <link href="version.css" rel="stylesheet" type="text/css" />
36 <script type="text/javascript" src="../../version.js"></script>
37 </head>
38 <body>
39 <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
40 <div id="titlearea">
41 <table cellspacing="0" cellpadding="0">
42  <tbody>
43  <tr style="height: 55px;">
44   <td id="projectlogo" style="padding: 1.5em;"><img alt="Logo" src="cmsis_logo_white_small.png"/></td>
45   <td style="padding-left: 1em; padding-bottom: 1em;padding-top: 1em;">
46    <div id="projectname">CMSIS-RTOS2
47    &#160;<span id="projectnumber"><script type="text/javascript">
48      <!--
49      writeHeader.call(this);
50      writeVersionDropdown.call(this, "CMSIS-RTOS2");
51      //-->
52     </script>
53    </span>
54    </div>
55    <div id="projectbrief">Real-Time Operating System: API and RTX Reference Implementation</div>
56   </td>
57    <td>        <div id="MSearchBox" class="MSearchBoxInactive">
58         <span class="left">
59           <span id="MSearchSelect"                onmouseover="return searchBox.OnSearchSelectShow()"                onmouseout="return searchBox.OnSearchSelectHide()">&#160;</span>
60           <input type="text" id="MSearchField" value="" placeholder="Search" accesskey="S"
61                onfocus="searchBox.OnSearchFieldFocus(true)" 
62                onblur="searchBox.OnSearchFieldFocus(false)" 
63                onkeyup="searchBox.OnSearchFieldChange(event)"/>
64           </span><span class="right">
65             <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
66           </span>
67         </div>
68 </td>
69   <!--END !PROJECT_NAME-->
70  </tr>
71  </tbody>
72 </table>
73 </div>
74 <!-- end header part -->
75 <div id="CMSISnav" class="tabs1">
76   <ul class="tablist">
77     <script type="text/javascript">
78       writeComponentTabs.call(this);
79     </script>
80   </ul>
81 </div>
82 <!-- Generated by Doxygen 1.9.6 -->
83 <script type="text/javascript">
84 /* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
85 var searchBox = new SearchBox("searchBox", "search/",'.html');
86 /* @license-end */
87 </script>
88 </div><!-- top -->
89 <div id="side-nav" class="ui-resizable side-nav-resizable">
90   <div id="nav-tree">
91     <div id="nav-tree-contents">
92       <div id="nav-sync" class="sync"></div>
93     </div>
94   </div>
95   <div id="splitbar" style="-moz-user-select:none;" 
96        class="ui-resizable-handle">
97   </div>
98 </div>
99 <script type="text/javascript">
100 /* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
101 $(document).ready(function(){initNavTree('rtos2_tutorial.html',''); initResizable(); });
102 /* @license-end */
103 </script>
104 <div id="doc-content">
105 <!-- window showing the filter options -->
106 <div id="MSearchSelectWindow"
107      onmouseover="return searchBox.OnSearchSelectShow()"
108      onmouseout="return searchBox.OnSearchSelectHide()"
109      onkeydown="return searchBox.OnSearchSelectKey(event)">
110 </div>
111
112 <!-- iframe showing the search results (closed by default) -->
113 <div id="MSearchResultsWindow">
114 <div id="MSearchResults">
115 <div class="SRPage">
116 <div id="SRIndex">
117 <div id="SRResults"></div>
118 <div class="SRStatus" id="Loading">Loading...</div>
119 <div class="SRStatus" id="Searching">Searching...</div>
120 <div class="SRStatus" id="NoMatches">No Matches</div>
121 </div>
122 </div>
123 </div>
124 </div>
125
126 <div><div class="header">
127   <div class="headertitle"><div class="title">Tutorial </div></div>
128 </div><!--header-->
129 <div class="contents">
130 <div class="textblock"><p>This tutorial is an introduction to using a small footprint real-time operating system on an Arm Cortex-M microcontroller. If you are used to writing procedural-based 'C' code on small 8-/16-bit microcontrollers, you may be doubtful about the need for such an operating system. If you are not familiar with using an RTOS in real-time embedded systems, you should read this chapter before dismissing the idea. The use of an RTOS represents a more sophisticated design approach, inherently fostering structured code development which is enforced by the RTOS application programming interface (API).</p>
131 <p>The RTOS structure allows you to take a more object-orientated design approach, while still programming in 'C'. The RTOS also provides you with multithreaded support on a small microcontroller. These two features actually create quite a shift in design philosophy, moving us away from thinking about procedural ‘C’ code and flow charts. Instead we consider the fundamental program threads and the flow of data between them. The use of an RTOS also has several additional benefits which may not be immediately obvious. Since an RTOS based project is composed of well-defined threads, it helps to improve project management, code reuse, and software testing.</p>
132 <p>The tradeoff for this is that an RTOS has additional memory requirements and increased interrupt latency. Typically, the Keil RTX5 RTOS will require 500 bytes of RAM and 5k bytes of code, but remember that some of the RTOS code would be replicated in your program anyway. We now have a generation of small low-cost microcontrollers that have enough on-chip memory and processing power to support the use of an RTOS. Developing using this approach is therefore much more accessible.</p>
133 <p>We will first look at setting up an introductory RTOS project for a Cortex-M based microcontroller. Next, we will go through each of the RTOS primitives and how they influence the design of our application code. Finally, when we have a clear understanding of the RTOS features, we will take a closer look at the RTOS configuration options. If you are used to programming a microcontroller without using an RTOS i.e. bare metal, there are two key things to understand as you work through this tutorial. In the first section, we will focus on creating and managing Threads. The key concept here is to consider them running as parallel concurrent objects. In the second section, we will look at how to communicate between threads. In this section the key concept is synchronization of the concurrent threads.</p>
134 <h1><a class="anchor" id="rtos2_tutorial_pre"></a>
135 Prerequisites</h1>
136 <p>It is assumed that you have Keil MDK installed on your PC. For download and installation instructions, please visit the <a href="https://www2.keil.com/mdk5/install/" target="_blank">Getting Started</a> page. Once you have set up the tool, open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
137 <li>Use the <b>Search</b> box on the <b>Devices</b> tab to look for the <b>STM32F103</b> device.</li>
138 <li>On the <b>Packs</b> tab, download and install the latest <b>Keil:STM32F1xx_DFP</b> pack and the latest <b>Hitex:CMSIS_RTOS2_Turorial</b> pack.</li>
139 </ul>
140 <dl class="section note"><dt>Note</dt><dd>It is assumed that you are familiar with Arm Keil MDK and have basic 'C' programming knowledge.</dd></dl>
141 <h1><a class="anchor" id="rtos2_tutorial_first_steps"></a>
142 First Steps with Keil RTX5</h1>
143 <p>The RTOS itself consists of a scheduler which supports round-robin, pre-emptive and co-operative multitasking of program threads, as well as time and memory management services. Inter-thread communication is supported by additional RTOS objects, including signal thread and event flags, semaphores, mutex, message passing and a memory pool system. As we will see, interrupt handling can also be accomplished by prioritized threads which are scheduled by the RTOS kernel.</p>
144 <div class="image">
145 <img src="rtos_components.png" alt=""/>
146 </div>
147 <h1><a class="anchor" id="rtos2_tutorial_access"></a>
148 Accessing the CMSIS-RTOS2 API</h1>
149 <p>To access any of the CMSIS-RTOS2 features in our application code, it is necessary to include the following header file. </p><div class="fragment"><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="cmsis__os2_8h.html">cmsis_os2.h</a>&gt;</span></div>
150 <div class="ttc" id="acmsis__os2_8h_html"><div class="ttname"><a href="cmsis__os2_8h.html">cmsis_os2.h</a></div></div>
151 </div><!-- fragment --><p> This header file is maintained by Arm as part of the CMSIS-RTOS2 standard. For Keil RTX5, this is the default API. Other RTOS will have their own proprietary API but may provide a wrapper layer to implement the CMSIS-RTOS2 API so they can be used where compatibility with the CMSIS standard is required.</p>
152 <h1><a class="anchor" id="rtos2_tutorial_threads"></a>
153 Threads</h1>
154 <p>The building blocks of a typical 'C' program are functions which we call to perform a specific procedure and which then return to the calling function. In CMSIS-RTOS2, the basic unit of execution is a "Thread". A Thread is very similar to a 'C' procedure but has some very fundamental differences. </p><div class="fragment"><div class="line"><span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> procedure (<span class="keywordtype">void</span>) {</div>
155 <div class="line">  ...</div>
156 <div class="line">  <span class="keywordflow">return</span>(ch);         </div>
157 <div class="line">}</div>
158 <div class="line"> </div>
159 <div class="line"><span class="keywordtype">void</span> thread (<span class="keywordtype">void</span>) {</div>
160 <div class="line">  <span class="keywordflow">while</span>(1) {</div>
161 <div class="line">    ...</div>
162 <div class="line">  }</div>
163 <div class="line">} </div>
164 <div class="line"> </div>
165 <div class="line"><a class="code hl_define" href="cmsis__os2_8h.html#a153a4a31b276a9758959580538720a51">__NO_RETURN</a> <span class="keywordtype">void</span> Thread1(<span class="keywordtype">void</span>*argument) {</div>
166 <div class="line">  <span class="keywordflow">while</span>(1) {</div>
167 <div class="line">    ...</div>
168 <div class="line">  }</div>
169 <div class="line">}</div>
170 <div class="ttc" id="acmsis__os2_8h_html_a153a4a31b276a9758959580538720a51"><div class="ttname"><a href="cmsis__os2_8h.html#a153a4a31b276a9758959580538720a51">__NO_RETURN</a></div><div class="ttdeci">#define __NO_RETURN</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:76</div></div>
171 </div><!-- fragment --><p> While we always return from our 'C' function, once started an RTOS thread must contain a loop so that it never terminates and thus runs forever. You can think of a thread as a mini self-contained program that runs within the RTOS. With the Arm Compiler, it is possible to optimize a thread by using a <code>__NO_RETURN</code> macro. This attribute reduces the cost of calling a function that never returns.</p>
172 <p>An RTOS program is made up of a number of threads, which are controlled by the RTOS scheduler. This scheduler uses the SysTick timer to generate a periodic interrupt as a time base. The scheduler will allot a certain amount of execution time to each thread. So <code>thread1</code> will run for 5 ms then be de-scheduled to allow <code>thread2</code> to run for a similar period; <code>thread2</code> will give way to <code>thread3</code> and finally control passes back to <code>thread1</code>. By allocating these slices of runtime to each thread in a round-robin fashion, we get the appearance of all three threads running in parallel to each other.</p>
173 <p>Conceptually we can think of each thread as performing a specific functional unit of our program with all threads running simultaneously. This leads us to a more object-orientated design, where each functional block can be coded and tested in isolation and then integrated into a fully running program. This not only imposes a structure on the design of our final application but also aids debugging, as a particular bug can be easily isolated to a specific thread. It also aids code reuse in later projects. When a thread is created, it is also allocated its own thread ID. This is a variable which acts as a handle for each thread and is used when we want to manage the activity of the thread. </p><div class="fragment"><div class="line"><a class="code hl_typedef" href="group__CMSIS__RTOS__ThreadMgmt.html#gaa6c32fe2a3e0a2e01f212d55b02e51c7">osThreadId_t</a> id1, id2, id3;</div>
174 <div class="ttc" id="agroup__CMSIS__RTOS__ThreadMgmt_html_gaa6c32fe2a3e0a2e01f212d55b02e51c7"><div class="ttname"><a href="group__CMSIS__RTOS__ThreadMgmt.html#gaa6c32fe2a3e0a2e01f212d55b02e51c7">osThreadId_t</a></div><div class="ttdeci">void * osThreadId_t</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:253</div></div>
175 </div><!-- fragment --><p> In order to make the thread-switching process happen, we have the code overhead of the RTOS and we have to dedicate a CPU hardware timer to provide the RTOS time reference. In addition, each time we switch running threads, we have to save the state of all the thread variables to a thread stack. Also, all the runtime information about a thread is stored in a thread control block, which is managed by the RTOS kernel. Thus the “context switch time”, that is, the time to save the current thread state and load up and start the next thread, is a crucial figure and will depend on both the RTOS kernel and the design of the underlying hardware.</p>
176 <p>The Thread Control Block contains information about the status of a thread. Part of this information is its run state. In a given system, only one thread can be running and all the others will be suspended but ready to run. The RTOS has various methods of inter-thread communication (signals, semaphores, messages). Here, a thread may be suspended to wait to be signaled by another thread or interrupt before it resumes its ready state, whereupon it can be placed into running state by the RTOS scheduler.</p>
177 <table class="markdownTable">
178 <tr class="markdownTableHead">
179 <th class="markdownTableHeadNone">State   </th><th class="markdownTableHeadNone">Description    </th></tr>
180 <tr class="markdownTableRowOdd">
181 <td class="markdownTableBodyNone">Running   </td><td class="markdownTableBodyNone">The currently running thread    </td></tr>
182 <tr class="markdownTableRowEven">
183 <td class="markdownTableBodyNone">Ready   </td><td class="markdownTableBodyNone">Threads ready to run    </td></tr>
184 <tr class="markdownTableRowOdd">
185 <td class="markdownTableBodyNone">Wait   </td><td class="markdownTableBodyNone">Blocked threads waiting for an OS event   </td></tr>
186 </table>
187 <p>At any given moment a single thread may be running. The remaining threads will be ready to run and will be scheduled by the kernel. Threads may also be waiting pending an OS event. When this occurs they will return to the ready state and be scheduled by the kernel.</p>
188 <h1><a class="anchor" id="rtos2_tutorial_start"></a>
189 Starting the RTOS</h1>
190 <p>To build a simple RTOS, program we declare each thread as a standard 'C' function and also declare a thread ID variable for each function. </p><div class="fragment"><div class="line"><span class="keywordtype">void</span> thread1 (<span class="keywordtype">void</span>);  </div>
191 <div class="line"><span class="keywordtype">void</span> thread2 (<span class="keywordtype">void</span>);</div>
192 <div class="line"> </div>
193 <div class="line">osThreadId thrdID1, thrdID2;</div>
194 </div><!-- fragment --><p> Once the processor leaves the reset vector, we will enter the <code>main()</code> function as normal. Once in <code>main()</code>, we must call <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#gae818f6611d25ba3140bede410a52d659">osKernelInitialize()</a> to setup the RTOS. It is not possible to call any RTOS function before the <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#gae818f6611d25ba3140bede410a52d659">osKernelInitialize()</a> function has successfully completed. Once <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#gae818f6611d25ba3140bede410a52d659">osKernelInitialize()</a> has completed, we can create further threads and other RTOS objects. This can be done by creating a launcher thread, in the example below this is called <code>app_main()</code>. Inside the <code>app_main()</code> thread, we create all the RTOS threads and objects we need to start our application running. As we will see later, it is also possible to dynamically create and destroy RTOS objects as the application is running. Next, we can call <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#ga9ae2cc00f0d89d7b6a307bba942b5221">osKernelStart()</a> to start the RTOS and the scheduler task switching. You can run any initializing code you want before starting the RTOS to setup peripherals and initialize the hardware. </p><div class="fragment"><div class="line"><span class="keywordtype">void</span> app_main(<span class="keywordtype">void</span> *argument) {</div>
195 <div class="line">  T_led_ID1 = <a class="code hl_function" href="group__CMSIS__RTOS__ThreadMgmt.html#ga48d68b8666d99d28fa646ee1d2182b8f">osThreadNew</a>(led_Thread1, NULL, &amp;ThreadAttr_LED1);</div>
196 <div class="line">  T_led_ID2 = <a class="code hl_function" href="group__CMSIS__RTOS__ThreadMgmt.html#ga48d68b8666d99d28fa646ee1d2182b8f">osThreadNew</a>(led_Thread2, NULL, &amp;ThreadAttr_LED2);</div>
197 <div class="line">  <a class="code hl_function" href="group__CMSIS__RTOS__Wait.html#gaf6055a51390ef65b6b6edc28bf47322e">osDelay</a>(<a class="code hl_define" href="group__CMSIS__RTOS__Definitions.html#ga9eb9a7a797a42e4b55eb171ecc609ddb">osWaitForever</a>);</div>
198 <div class="line">  <span class="keywordflow">while</span> (1)</div>
199 <div class="line">    ;</div>
200 <div class="line">}</div>
201 <div class="line"> </div>
202 <div class="line"><span class="keywordtype">void</span> main(<span class="keywordtype">void</span>) {</div>
203 <div class="line">  IODIR1 = 0x00FF0000;               <span class="comment">// Do any C code you want</span></div>
204 <div class="line">  <a class="code hl_function" href="group__CMSIS__RTOS__KernelCtrl.html#gae818f6611d25ba3140bede410a52d659">osKernelInitialize</a>();              <span class="comment">// Initialize the kernel</span></div>
205 <div class="line">  <a class="code hl_function" href="group__CMSIS__RTOS__ThreadMgmt.html#ga48d68b8666d99d28fa646ee1d2182b8f">osThreadNew</a>(app_main, NULL, NULL); <span class="comment">// Create the app_main() launcher thread</span></div>
206 <div class="line">  <a class="code hl_function" href="group__CMSIS__RTOS__KernelCtrl.html#ga9ae2cc00f0d89d7b6a307bba942b5221">osKernelStart</a>();                   <span class="comment">// Start the RTOS</span></div>
207 <div class="line">}</div>
208 <div class="ttc" id="agroup__CMSIS__RTOS__Definitions_html_ga9eb9a7a797a42e4b55eb171ecc609ddb"><div class="ttname"><a href="group__CMSIS__RTOS__Definitions.html#ga9eb9a7a797a42e4b55eb171ecc609ddb">osWaitForever</a></div><div class="ttdeci">#define osWaitForever</div><div class="ttdoc">Wait forever timeout value.</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:189</div></div>
209 <div class="ttc" id="agroup__CMSIS__RTOS__KernelCtrl_html_ga9ae2cc00f0d89d7b6a307bba942b5221"><div class="ttname"><a href="group__CMSIS__RTOS__KernelCtrl.html#ga9ae2cc00f0d89d7b6a307bba942b5221">osKernelStart</a></div><div class="ttdeci">osStatus_t osKernelStart(void)</div><div class="ttdoc">Start the RTOS Kernel scheduler.</div></div>
210 <div class="ttc" id="agroup__CMSIS__RTOS__KernelCtrl_html_gae818f6611d25ba3140bede410a52d659"><div class="ttname"><a href="group__CMSIS__RTOS__KernelCtrl.html#gae818f6611d25ba3140bede410a52d659">osKernelInitialize</a></div><div class="ttdeci">osStatus_t osKernelInitialize(void)</div><div class="ttdoc">Initialize the RTOS Kernel.</div></div>
211 <div class="ttc" id="agroup__CMSIS__RTOS__ThreadMgmt_html_ga48d68b8666d99d28fa646ee1d2182b8f"><div class="ttname"><a href="group__CMSIS__RTOS__ThreadMgmt.html#ga48d68b8666d99d28fa646ee1d2182b8f">osThreadNew</a></div><div class="ttdeci">osThreadId_t osThreadNew(osThreadFunc_t func, void *argument, const osThreadAttr_t *attr)</div><div class="ttdoc">Create a thread and add it to Active Threads.</div></div>
212 <div class="ttc" id="agroup__CMSIS__RTOS__Wait_html_gaf6055a51390ef65b6b6edc28bf47322e"><div class="ttname"><a href="group__CMSIS__RTOS__Wait.html#gaf6055a51390ef65b6b6edc28bf47322e">osDelay</a></div><div class="ttdeci">osStatus_t osDelay(uint32_t ticks)</div><div class="ttdoc">Wait for Timeout (Time Delay).</div></div>
213 </div><!-- fragment --><p> When threads are created they are also assigned a priority. If there are a number of threads ready to run and they all have the same priority, they will be allotted run time in a round-robin fashion. However, if a thread with a higher priority becomes ready to run, the RTOS scheduler will de-schedule the currently running thread and start the high priority thread running. This is called pre-emptive priority-based scheduling. When assigning priorities, you have to be careful because the high priority thread will continue to run until it enters a waiting state or until a thread of equal or higher priority is ready to run.</p>
214 <h2><a class="anchor" id="rtos2_tutorial_ex1"></a>
215 Exercise 1 - A First CMSIS-RTOS2 Project</h2>
216 <p>Open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
217 <li>Use the <b>Search</b> box on the <b>Boards</b> tab to look for the <b>CMSIS_RTOS_Tutorial (V2.1)</b> "board".</li>
218 <li>On the <b>Examples</b> tab, copy <b>Ex 01 First Project</b> to your PC and start Keil MDK.</li>
219 <li>In the project folder, you will find a file called "Instructions.pdf" that explains the setup and the steps you need to take to successfully finish the exercise.</li>
220 </ul>
221 <h1><a class="anchor" id="rtos2_tutorial_thread_create"></a>
222 Creating Threads</h1>
223 <p>Once the RTOS is running, there are a number of system calls that are used to manage and control the active threads. The documentation lists <a class="el" href="group__CMSIS__RTOS__ThreadMgmt.html">all thread management functions</a>.</p>
224 <p>As we saw in the first example, the <code>app_main()</code> thread is used as a launcher thread to create the application threads. This is done in two stages. First a thread structure is defined; this allows us to define the thread operating parameters. </p><div class="fragment"><div class="line">osThreadId thread1_id; <span class="comment">// thread handle</span></div>
225 <div class="line"> </div>
226 <div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <a class="code hl_struct" href="group__CMSIS__RTOS__ThreadMgmt.html#structosThreadAttr__t">osThreadAttr_t</a> threadAttr_thread1 = {</div>
227 <div class="line">  “Name_String <span class="stringliteral">&quot;,      //Human readable Name for debugger</span></div>
228 <div class="line"><span class="stringliteral">    Attribute_bits Control_Block_Memory,</span></div>
229 <div class="line"><span class="stringliteral">    Control_Block_Size,</span></div>
230 <div class="line"><span class="stringliteral">    Stack_Memory,</span></div>
231 <div class="line"><span class="stringliteral">    Stack_Size,</span></div>
232 <div class="line"><span class="stringliteral">    Priority,</span></div>
233 <div class="line"><span class="stringliteral">    TrustZone_ID,</span></div>
234 <div class="line"><span class="stringliteral">    reserved};</span></div>
235 <div class="ttc" id="agroup__CMSIS__RTOS__ThreadMgmt_html_structosThreadAttr__t"><div class="ttname"><a href="group__CMSIS__RTOS__ThreadMgmt.html#structosThreadAttr__t">osThreadAttr_t</a></div><div class="ttdoc">Attributes structure for thread.</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:282</div></div>
236 </div><!-- fragment --><p> The thread structure requires us to define the name of the thread function, its thread priority, any special attribute bits, its TrustZone_ID and its memory allocation. This is quite a lot of detail to go through but we will cover everything by the end of this application note. Once the thread structure has been defined, the thread can be created using the <a class="el" href="group__CMSIS__RTOS__ThreadMgmt.html#ga48d68b8666d99d28fa646ee1d2182b8f">osThreadNew()</a> API call. Then the thread is created from within the application code, this is often the within the <code>app_main()</code> thread but a thread can be created at any point within any thread. </p><div class="fragment"><div class="line">thread1_id = <a class="code hl_function" href="group__CMSIS__RTOS__ThreadMgmt.html#ga48d68b8666d99d28fa646ee1d2182b8f">osThreadNew</a>(name_Of_C_Function, argument,&amp;threadAttr_thread1);</div>
237 </div><!-- fragment --><p> This creates the thread and starts it running. It is also possible to pass a parameter to the thread when it starts. </p><div class="fragment"><div class="line">uint32_t startupParameter = 0x23;</div>
238 <div class="line">thread1_id = <a class="code hl_function" href="group__CMSIS__RTOS__ThreadMgmt.html#ga48d68b8666d99d28fa646ee1d2182b8f">osThreadNew</a>(name_Of_C_Function, (uint32_t)startupParameter,&amp;threadAttr_thread1);</div>
239 </div><!-- fragment --><h2><a class="anchor" id="rtos2_tutorial_ex2"></a>
240 Exercise 2 - Creating and Managing Threads</h2>
241 <p>Open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
242 <li>Use the <b>Search</b> box on the <b>Boards</b> tab to look for the <b>CMSIS_RTOS_Tutorial (V2.1)</b> "board".</li>
243 <li>On the <b>Examples</b> tab, copy <b>Ex 02 Threads</b> to your PC and start Keil MDK.</li>
244 <li>In the project folder, you will find a file called "Instructions.pdf" that explains the setup and the steps you need to take to successfully finish the exercise.</li>
245 </ul>
246 <h1><a class="anchor" id="rtos2_tutorial_thread_mgmt"></a>
247 Thread Management and Priority</h1>
248 <p>When a thread is created it is assigned a priority level. The RTOS scheduler uses a thread’s priority to decide which thread should be scheduled to run. If a number of threads are ready to run, the thread with the highest priority will be placed in the run state. If a high priority thread becomes ready to run it will preempt a running thread of lower priority. Importantly, a high priority thread running on the CPU will not stop running unless it blocks on an RTOS API call or is preempted by a higher priority thread. A thread's priority is defined in the thread structure and the following priority definitions are available. The default priority is <a class="el" href="cmsis__os2_8h.html#gad4e3e0971b41f2d17584a8c6837342eca45a2895ad30c79fb97de18cac7cc19f1">osPriorityNormal</a>. The <a class="el" href="group__CMSIS__RTOS__ThreadMgmt.html#gad4e3e0971b41f2d17584a8c6837342ec">osPriority_t</a> value specifies the priority for a thread.</p>
249 <p>Once the threads are running, there are a small number of RTOS system calls which are used to manage the running threads. It is also then possible to elevate or lower a thread’s priority either from another function or from within its own code. </p><div class="fragment"><div class="line">osStatus   <a class="code hl_function" href="group__CMSIS__RTOS__ThreadMgmt.html#ga861a420fb2d643115b06622903fb3bfb">osThreadSetPriority</a>(threadID, priority);</div>
250 <div class="line">osPriority <a class="code hl_function" href="group__CMSIS__RTOS__ThreadMgmt.html#ga0aeaf349604f456e68e78f9d3b42e44b">osThreadGetPriority</a>(threadID);</div>
251 <div class="ttc" id="agroup__CMSIS__RTOS__ThreadMgmt_html_ga0aeaf349604f456e68e78f9d3b42e44b"><div class="ttname"><a href="group__CMSIS__RTOS__ThreadMgmt.html#ga0aeaf349604f456e68e78f9d3b42e44b">osThreadGetPriority</a></div><div class="ttdeci">osPriority_t osThreadGetPriority(osThreadId_t thread_id)</div><div class="ttdoc">Get current priority of a thread.</div></div>
252 <div class="ttc" id="agroup__CMSIS__RTOS__ThreadMgmt_html_ga861a420fb2d643115b06622903fb3bfb"><div class="ttname"><a href="group__CMSIS__RTOS__ThreadMgmt.html#ga861a420fb2d643115b06622903fb3bfb">osThreadSetPriority</a></div><div class="ttdeci">osStatus_t osThreadSetPriority(osThreadId_t thread_id, osPriority_t priority)</div><div class="ttdoc">Change priority of a thread.</div></div>
253 </div><!-- fragment --><p> As well as creating threads, it is also possible for a thread to delete another active thread from the RTOS. Again, we use the thread ID rather than the function name of the thread. </p><div class="fragment"><div class="line">osStatus = <a class="code hl_function" href="group__CMSIS__RTOS__ThreadMgmt.html#ga2f8ba6dba6e9c065a6e236ffd410d74a">osThreadTerminate</a> (threadID1);</div>
254 <div class="ttc" id="agroup__CMSIS__RTOS__ThreadMgmt_html_ga2f8ba6dba6e9c065a6e236ffd410d74a"><div class="ttname"><a href="group__CMSIS__RTOS__ThreadMgmt.html#ga2f8ba6dba6e9c065a6e236ffd410d74a">osThreadTerminate</a></div><div class="ttdeci">osStatus_t osThreadTerminate(osThreadId_t thread_id)</div><div class="ttdoc">Terminate execution of a thread.</div></div>
255 </div><!-- fragment --><p> If a thread wants to terminate itself then there is a dedicated exit function. </p><div class="fragment"><div class="line"><a class="code hl_function" href="group__CMSIS__RTOS__ThreadMgmt.html#gaddaa452dd7610e4096647a566d3556fc">osThreadExit</a> (<span class="keywordtype">void</span>)</div>
256 <div class="ttc" id="agroup__CMSIS__RTOS__ThreadMgmt_html_gaddaa452dd7610e4096647a566d3556fc"><div class="ttname"><a href="group__CMSIS__RTOS__ThreadMgmt.html#gaddaa452dd7610e4096647a566d3556fc">osThreadExit</a></div><div class="ttdeci">__NO_RETURN void osThreadExit(void)</div><div class="ttdoc">Terminate execution of current running thread.</div></div>
257 </div><!-- fragment --><p> Finally, there is a special case of thread switching where the running thread passes control to the next ready thread of the same priority. This is used to implement a third form of scheduling called co-operative thread switching. </p><div class="fragment"><div class="line">osStatus <a class="code hl_function" href="group__CMSIS__RTOS__ThreadMgmt.html#gad01c7ec26535b1de6b018bb9466720e2">osThreadYield</a>();   <span class="comment">//switch to next ready to run thread at the same priority</span></div>
258 <div class="ttc" id="agroup__CMSIS__RTOS__ThreadMgmt_html_gad01c7ec26535b1de6b018bb9466720e2"><div class="ttname"><a href="group__CMSIS__RTOS__ThreadMgmt.html#gad01c7ec26535b1de6b018bb9466720e2">osThreadYield</a></div><div class="ttdeci">osStatus_t osThreadYield(void)</div><div class="ttdoc">Pass control to next thread that is in state READY.</div></div>
259 </div><!-- fragment --><h1><a class="anchor" id="rtos2_tutorial_ex2_mem_mgmt"></a>
260 Memory Management</h1>
261 <p>When each thread is created, it is assigned its own stack for storing data during the context switch. This should not be confused with the native Cortex-M processor stack; it is really a block of memory that is allocated to the thread. A default stack size is defined in the RTOS configuration file (we will see this later) and this amount of memory will be allocated to each thread unless we override it to allocate a custom size. The default stack size will be assigned to a thread if the stack size value in the thread definition structure is set to zero. If necessary a thread can be given additional memory resources by defining a bigger stack size in the thread structure. Keil RTX5 supports several memory models to assign this thread memory. The default model is a global memory pool. In this model each RTOS object that is created (threads, message queues, semaphores etc.) are allocated memory from a single block of memory.</p>
262 <p>If an object is destroyed the memory it has been assigned is returned to the memory pool. This has the advantage of memory reuse but also introduces the possible problem of memory fragmentation.</p>
263 <p>The size of the global memory pool is defined in the configuration file: </p><div class="fragment"><div class="line"><span class="preprocessor">#define OS_DYNAMIC_MEM_SIZE         4096</span></div>
264 </div><!-- fragment --><p> And the default stack size for each thread is defined in the threads section: </p><div class="fragment"><div class="line"><span class="preprocessor">#define OS_STACK_SIZE               256</span></div>
265 </div><!-- fragment --><p> It is also possible to define object specific memory pools for each different type of RTOS object. In this model you define the maximum number of a specific object type and its memory requirements. The RTOS then calculates and reserves the required memory usage.</p>
266 <p>The object specific model is again defined in the RTOS configuration file by enabling the "object specific memory" option provided in each section of the configuration file: </p><div class="fragment"><div class="line"><span class="preprocessor">#define OS_SEMAPHORE_OBJ_MEM        1</span></div>
267 <div class="line"><span class="preprocessor">#define OS_SEMAPHORE_NUM            1</span></div>
268 </div><!-- fragment --><p> In the case of simple object which requires a fixed memory allocation we just need to define the maximum number of a given object type. In the case of more complex objects such as threads we will need to define the required memory usage: </p><div class="fragment"><div class="line"><span class="preprocessor">#define OS_THREAD_OBJ_MEM           1</span></div>
269 <div class="line"><span class="preprocessor">#define OS_THREAD_NUM               1</span></div>
270 <div class="line"><span class="preprocessor">#define OS_THREAD_DEF_STACK_NUM     0</span></div>
271 <div class="line"><span class="preprocessor">#define OS_THREAD_USER_STACK_SIZE   1024</span></div>
272 </div><!-- fragment --><p> To use the object specific memory allocation model with threads we must provide details of the overall thread memory usage. Finally it is possible to statically allocate the thread stack memory. This is important for safety related systems where memory usage has to be rigorously defined.</p>
273 <h2><a class="anchor" id="rtos2_tutorial_ex3"></a>
274 Exercise 3 - Memory Model</h2>
275 <p>Open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
276 <li>Use the <b>Search</b> box on the <b>Boards</b> tab to look for the <b>CMSIS_RTOS_Tutorial (V2.1)</b> "board".</li>
277 <li>On the <b>Examples</b> tab, copy <b>Ex 03 Memory Model</b> to your PC and start Keil MDK.</li>
278 <li>In the project folder, you will find a file called "Instructions.pdf" that explains the setup and the steps you need to take to successfully finish the exercise.</li>
279 </ul>
280 <h1><a class="anchor" id="rtos2_tutorial_multi_inst"></a>
281 Multiple Instances</h1>
282 <p>One of the interesting possibilities of an RTOS is that you can create multiple running instances of the same base thread code. For example, you could write a thread to control a UART and then create two running instances of the same thread code. Here, each instance of the UART code could manage a different UART. Then we can create two instances of the thread assigned to different thread handles. A parameter is also passed to allow each instance to identify which UART it is responsible for. </p><div class="fragment"><div class="line"><span class="preprocessor">#define UART1 (void *) 1UL</span></div>
283 <div class="line"><span class="preprocessor">#define UART2 (void *) 2UL</span></div>
284 <div class="line"> </div>
285 <div class="line">ThreadID_1_0 = <a class="code hl_function" href="group__CMSIS__RTOS__ThreadMgmt.html#ga48d68b8666d99d28fa646ee1d2182b8f">osThreadNew</a> (thread1, UART1, &amp;ThreadAttr_Task1);</div>
286 <div class="line">ThreadID_1_1 = <a class="code hl_function" href="group__CMSIS__RTOS__ThreadMgmt.html#ga48d68b8666d99d28fa646ee1d2182b8f">osThreadNew</a> (thread1, UART0, &amp;ThreadAttr_Task1);</div>
287 </div><!-- fragment --><h2><a class="anchor" id="rtos2_tutorial_multi_inst_ex4"></a>
288 Exercise 4 - Multiple Instances</h2>
289 <p>Open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
290 <li>Use the <b>Search</b> box on the <b>Boards</b> tab to look for the <b>CMSIS_RTOS_Tutorial (V2.1)</b> "board".</li>
291 <li>On the <b>Examples</b> tab, copy <b>Ex 04 Multiple Instances</b> to your PC and start Keil MDK.</li>
292 <li>In the project folder, you will find a file called "Instructions.pdf" that explains the setup and the steps you need to take to successfully finish the exercise.</li>
293 </ul>
294 <h1><a class="anchor" id="rtos2_tutorial_thread_join"></a>
295 Joinable Threads</h1>
296 <p>A new feature in CMSIS-RTOS2 is the ability to create threads in a 'joinable' state. This allows a thead to be created and executed as a standard thread. In addition, a second thread can join it by calling <a class="el" href="group__CMSIS__RTOS__ThreadMgmt.html#ga3fca90fb0679afeb968aa8c3d5874487">osThreadJoin()</a>. This will cause the second thread to deschedule and remain in a waiting state until the thread which has been joined is terminated. This allows a temporary joinable thread to be created, which would acquire a block of memory from the global memory pool, this thread could perform some processing and then terminate, releasing the memory back to the memory pool. A joinable thread can be created by setting the joinable attribute bit in the thread attributes structure as shown below: </p><div class="fragment"><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <a class="code hl_struct" href="group__CMSIS__RTOS__ThreadMgmt.html#structosThreadAttr__t">osThreadAttr_t</a> ThreadAttr_worker = {</div>
297 <div class="line">  .<a class="code hl_variable" href="group__CMSIS__RTOS__ThreadMgmt.html#a6e93b49cb79c12f768d72580c7731f30">attr_bits</a> = <a class="code hl_define" href="group__CMSIS__RTOS__ThreadMgmt.html#ga249499c519f3f8eef5673009ab6cfcbe">osThreadJoinable</a></div>
298 <div class="line">};</div>
299 <div class="ttc" id="agroup__CMSIS__RTOS__ThreadMgmt_html_a6e93b49cb79c12f768d72580c7731f30"><div class="ttname"><a href="group__CMSIS__RTOS__ThreadMgmt.html#a6e93b49cb79c12f768d72580c7731f30">osThreadAttr_t::attr_bits</a></div><div class="ttdeci">uint32_t attr_bits</div><div class="ttdoc">attribute bits</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:284</div></div>
300 <div class="ttc" id="agroup__CMSIS__RTOS__ThreadMgmt_html_ga249499c519f3f8eef5673009ab6cfcbe"><div class="ttname"><a href="group__CMSIS__RTOS__ThreadMgmt.html#ga249499c519f3f8eef5673009ab6cfcbe">osThreadJoinable</a></div><div class="ttdeci">#define osThreadJoinable</div><div class="ttdoc">Thread created in joinable mode.</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:207</div></div>
301 </div><!-- fragment --><p> Once the thread has been created, it will execute following the same rules as 'normal' threads. Any other thread can then join it by using the OS call: </p><div class="fragment"><div class="line"><a class="code hl_function" href="group__CMSIS__RTOS__ThreadMgmt.html#ga3fca90fb0679afeb968aa8c3d5874487">osThreadJoin</a>(&lt;joinable_thread_handle&gt;);</div>
302 <div class="ttc" id="agroup__CMSIS__RTOS__ThreadMgmt_html_ga3fca90fb0679afeb968aa8c3d5874487"><div class="ttname"><a href="group__CMSIS__RTOS__ThreadMgmt.html#ga3fca90fb0679afeb968aa8c3d5874487">osThreadJoin</a></div><div class="ttdeci">osStatus_t osThreadJoin(osThreadId_t thread_id)</div><div class="ttdoc">Wait for specified thread to terminate.</div></div>
303 </div><!-- fragment --><p> Once <a class="el" href="group__CMSIS__RTOS__ThreadMgmt.html#ga3fca90fb0679afeb968aa8c3d5874487">osThreadJoin()</a> has been called, the thread will deschedule and enter a waiting state until the joinable thread has terminated.</p>
304 <h2><a class="anchor" id="rtos2_tutorial_ex4"></a>
305 Exercise 5 - Joinable Threads</h2>
306 <p>Open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
307 <li>Use the <b>Search</b> box on the <b>Boards</b> tab to look for the <b>CMSIS_RTOS_Tutorial (V2.1)</b> "board".</li>
308 <li>On the <b>Examples</b> tab, copy <b>Ex 05 Join</b> to your PC and start Keil MDK.</li>
309 <li>In the project folder, you will find a file called "Instructions.pdf" that explains the setup and the steps you need to take to successfully finish the exercise.</li>
310 </ul>
311 <h1><a class="anchor" id="rtos2_tutorial_time_mgmt"></a>
312 Time Management</h1>
313 <p>As well as running your application code as threads, the RTOS also provides some timing services which can be accessed through RTOS system calls.</p>
314 <h2><a class="anchor" id="rtos2_tutorial_time_delay"></a>
315 Time Delay</h2>
316 <p>The most basic of these timing services is a simple timer delay function. This is an easy way of providing timing delays within your application. Although the RTOS kernel size is quoted as 5 KB, features such as delay loops and simple scheduling loops are often part of a non-RTOS application and would consume code bytes anyway, so the overhead of the RTOS can be less than it immediately appears. </p><div class="fragment"><div class="line"><span class="keywordtype">void</span> <a class="code hl_function" href="group__CMSIS__RTOS__Wait.html#gaf6055a51390ef65b6b6edc28bf47322e">osDelay</a> (uint32_t ticks)</div>
317 </div><!-- fragment --><p> This call will place the calling thread into the WAIT_DELAY state for the specified number of milliseconds. The scheduler will pass execution to the next thread in the READY state.</p>
318 <p>When the timer expires, the thread will leave the WAIT_DELAY state and move to the READY state. The thread will resume running when the scheduler moves it to the RUNNING state. If the thread then continues executing without any further blocking OS calls, it will be descheduled at the end of its time slice and be placed in the ready state, assuming another thread of the same priority is ready to run.</p>
319 <h2><a class="anchor" id="rtos2_tutorial_abs_time_delay"></a>
320 Absolute Time Delay</h2>
321 <p>In addition to the <a class="el" href="group__CMSIS__RTOS__Wait.html#gaf6055a51390ef65b6b6edc28bf47322e">osDelay()</a> function which gives a relative time delay starting from the instant it is called, there is also a delay function which halts a thread until a specific point in time: </p><div class="fragment"><div class="line">osStatus <a class="code hl_function" href="group__CMSIS__RTOS__Wait.html#ga3c807924c2d6d43bc2ffb49da3f7f3a1">osDelayUntil</a> (uint32_t ticks)   </div>
322 <div class="ttc" id="agroup__CMSIS__RTOS__Wait_html_ga3c807924c2d6d43bc2ffb49da3f7f3a1"><div class="ttname"><a href="group__CMSIS__RTOS__Wait.html#ga3c807924c2d6d43bc2ffb49da3f7f3a1">osDelayUntil</a></div><div class="ttdeci">osStatus_t osDelayUntil(uint32_t ticks)</div><div class="ttdoc">Wait until specified time.</div></div>
323 </div><!-- fragment --><p> The <a class="el" href="group__CMSIS__RTOS__Wait.html#ga3c807924c2d6d43bc2ffb49da3f7f3a1">osDelayUntil()</a> function will halt a thread until a specific value of kernel timer ticks is reached. There are a number of kernel functions that allow you to read both the current SysTick count and the kernel ticks count.</p>
324 <table class="markdownTable">
325 <tr class="markdownTableHead">
326 <th class="markdownTableHeadNone">Kernel timer functions    </th></tr>
327 <tr class="markdownTableRowOdd">
328 <td class="markdownTableBodyNone">uint64_t <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#ga84bcdbf2fb76b10c8df4e439f0c7e11b">osKernelGetTickCount(void)</a>    </td></tr>
329 <tr class="markdownTableRowEven">
330 <td class="markdownTableBodyNone">uint32_t <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#ga7a8d7bd927eaaa58999f91d7d6310cee">osKernelGetTickFreq(void)</a>    </td></tr>
331 <tr class="markdownTableRowOdd">
332 <td class="markdownTableBodyNone">uint32_t <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#gae0fcaff6cecfb4013bb556c87afcd7d2">osKernelGetSysTimerCount(void)</a>    </td></tr>
333 <tr class="markdownTableRowEven">
334 <td class="markdownTableBodyNone">uint32_t <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#ga4d69215a93220f72be3684cad582f16a">osKernelGetSysTimerFreq(void)</a>   </td></tr>
335 </table>
336 <h2><a class="anchor" id="rtos2_tutorial_ex6"></a>
337 Exercise 6 - Time Management</h2>
338 <p>Open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
339 <li>Use the <b>Search</b> box on the <b>Boards</b> tab to look for the <b>CMSIS_RTOS_Tutorial (V2.1)</b> "board".</li>
340 <li>On the <b>Examples</b> tab, copy <b>Ex 06 Time Management</b> to your PC and start Keil MDK.</li>
341 <li>In the project folder, you will find a file called "Instructions.pdf" that explains the setup and the steps you need to take to successfully finish the exercise.</li>
342 </ul>
343 <h2><a class="anchor" id="rtos2_tutorial_virtual_timers"></a>
344 Virtual Timers</h2>
345 <p>The CMSIS-RTOS API can be used to define any number of virtual timers which act as count down timers. When they expire, they will run a user call-back function to perform a specific action. Each timer can be configured as a one shot or repeat timer. A virtual timer is created by first defining a timer structure: </p><div class="fragment"><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <span class="keyword">struct </span><a class="code hl_struct" href="group__CMSIS__RTOS__TimerMgmt.html#structosTimerAttr__t">osTimerAttr_t</a> timerAttr_timer0 = {</div>
346 <div class="line">  <span class="keyword">const</span> <span class="keywordtype">char</span>* <a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#ab74e6bf80237ddc4109968cedc58c151">name</a>;      <span class="comment">///&lt; name of the timer</span></div>
347 <div class="line">  uint32_t    <a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#a6e93b49cb79c12f768d72580c7731f30">attr_bits</a>; <span class="comment">///&lt; attribute bits</span></div>
348 <div class="line">  <span class="keywordtype">void</span>*       <a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#a1e100dc33d403841ed3c344e3397868e">cb_mem</a>;    <span class="comment">///&lt; memory for control block</span></div>
349 <div class="line">  uint32_t    <a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#aa55a4335d12dc2785dc00fdc292d1159">cb_size</a>;   <span class="comment">///&lt; size of provided memory for control block</span></div>
350 <div class="line">}</div>
351 <div class="ttc" id="agroup__CMSIS__RTOS__TimerMgmt_html_a1e100dc33d403841ed3c344e3397868e"><div class="ttname"><a href="group__CMSIS__RTOS__TimerMgmt.html#a1e100dc33d403841ed3c344e3397868e">osTimerAttr_t::cb_mem</a></div><div class="ttdeci">void * cb_mem</div><div class="ttdoc">memory for control block</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:298</div></div>
352 <div class="ttc" id="agroup__CMSIS__RTOS__TimerMgmt_html_a6e93b49cb79c12f768d72580c7731f30"><div class="ttname"><a href="group__CMSIS__RTOS__TimerMgmt.html#a6e93b49cb79c12f768d72580c7731f30">osTimerAttr_t::attr_bits</a></div><div class="ttdeci">uint32_t attr_bits</div><div class="ttdoc">attribute bits</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:297</div></div>
353 <div class="ttc" id="agroup__CMSIS__RTOS__TimerMgmt_html_aa55a4335d12dc2785dc00fdc292d1159"><div class="ttname"><a href="group__CMSIS__RTOS__TimerMgmt.html#aa55a4335d12dc2785dc00fdc292d1159">osTimerAttr_t::cb_size</a></div><div class="ttdeci">uint32_t cb_size</div><div class="ttdoc">size of provided memory for control block</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:299</div></div>
354 <div class="ttc" id="agroup__CMSIS__RTOS__TimerMgmt_html_ab74e6bf80237ddc4109968cedc58c151"><div class="ttname"><a href="group__CMSIS__RTOS__TimerMgmt.html#ab74e6bf80237ddc4109968cedc58c151">osTimerAttr_t::name</a></div><div class="ttdeci">const char * name</div><div class="ttdoc">name of the timer</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:296</div></div>
355 <div class="ttc" id="agroup__CMSIS__RTOS__TimerMgmt_html_structosTimerAttr__t"><div class="ttname"><a href="group__CMSIS__RTOS__TimerMgmt.html#structosTimerAttr__t">osTimerAttr_t</a></div><div class="ttdoc">Attributes structure for timer.</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:295</div></div>
356 </div><!-- fragment --><p> This defines a name for the timer. The timer must then be instantiated by an RTOS thread providing a pointer to the callback function and its parameter.: </p><div class="fragment"><div class="line"><a class="code hl_typedef" href="group__CMSIS__RTOS__TimerMgmt.html#gaad5409379689ee27bb0a0b56ea4a4b34">osTimerId_t</a> timer0_handle;</div>
357 <div class="line">timer0_handle = <a class="code hl_function" href="group__CMSIS__RTOS__TimerMgmt.html#gad4e7f785c5f700a509f55a3bf6a62bec">osTimerNew</a>(&amp;callback, <a class="code hl_enumvalue" href="group__CMSIS__RTOS__TimerMgmt.html#gga7dc24a4c2b90334427081c3da7a71915ab3463d921dc310938094745c230f2b35">osTimerPeriodic</a>,(<span class="keywordtype">void</span> *)&lt;parameter&gt;, &amp;timerAttr_timer0);</div>
358 <div class="ttc" id="agroup__CMSIS__RTOS__TimerMgmt_html_gaad5409379689ee27bb0a0b56ea4a4b34"><div class="ttname"><a href="group__CMSIS__RTOS__TimerMgmt.html#gaad5409379689ee27bb0a0b56ea4a4b34">osTimerId_t</a></div><div class="ttdeci">void * osTimerId_t</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:256</div></div>
359 <div class="ttc" id="agroup__CMSIS__RTOS__TimerMgmt_html_gad4e7f785c5f700a509f55a3bf6a62bec"><div class="ttname"><a href="group__CMSIS__RTOS__TimerMgmt.html#gad4e7f785c5f700a509f55a3bf6a62bec">osTimerNew</a></div><div class="ttdeci">osTimerId_t osTimerNew(osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr)</div><div class="ttdoc">Create and Initialize a timer.</div></div>
360 <div class="ttc" id="agroup__CMSIS__RTOS__TimerMgmt_html_gga7dc24a4c2b90334427081c3da7a71915ab3463d921dc310938094745c230f2b35"><div class="ttname"><a href="group__CMSIS__RTOS__TimerMgmt.html#gga7dc24a4c2b90334427081c3da7a71915ab3463d921dc310938094745c230f2b35">osTimerPeriodic</a></div><div class="ttdeci">@ osTimerPeriodic</div><div class="ttdoc">Repeating timer.</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:185</div></div>
361 </div><!-- fragment --><p> This creates the timer and defines it as a periodic timer or a single shot timer (<a class="el" href="group__CMSIS__RTOS__TimerMgmt.html#gga7dc24a4c2b90334427081c3da7a71915a2e0e1f31c742c84b497c4d7143357bdb">osTimerOnce()</a>). The next parameter passes an argument to the call back function when the timer expires: </p><div class="fragment"><div class="line"><a class="code hl_function" href="group__CMSIS__RTOS__TimerMgmt.html#gab6ee2859ea657641b7adfac599b8121d">osTimerStart</a> (timer0_handle,0x100);</div>
362 <div class="ttc" id="agroup__CMSIS__RTOS__TimerMgmt_html_gab6ee2859ea657641b7adfac599b8121d"><div class="ttname"><a href="group__CMSIS__RTOS__TimerMgmt.html#gab6ee2859ea657641b7adfac599b8121d">osTimerStart</a></div><div class="ttdeci">osStatus_t osTimerStart(osTimerId_t timer_id, uint32_t ticks)</div><div class="ttdoc">Start or restart a timer.</div></div>
363 </div><!-- fragment --><p> The timer can then be started at any point in a thread the timer start function invokes the timer by its handle and defines a count period in kernel ticks.</p>
364 <h2><a class="anchor" id="rtos2_tutorial_ex7"></a>
365 Exercise 7 - Virtual Timer</h2>
366 <p>Open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
367 <li>Use the <b>Search</b> box on the <b>Boards</b> tab to look for the <b>CMSIS_RTOS_Tutorial (V2.1)</b> "board".</li>
368 <li>On the <b>Examples</b> tab, copy <b>Ex 07 Virtual Timers</b> to your PC and start Keil MDK.</li>
369 <li>In the project folder, you will find a file called "Instructions.pdf" that explains the setup and the steps you need to take to successfully finish the exercise.</li>
370 </ul>
371 <h2><a class="anchor" id="rtos2_tutorial_idle_thread"></a>
372 Idle Thread</h2>
373 <p>The final timer service provided by the RTOS isn't really a timer, but this is probably the best place to discuss it. If during our RTOS program we have no thread running and no thread ready to run (e.g. they are all waiting on delay functions), then the RTOS will start to run the Idle Thread. This thread is automatically created when the RTOS starts and runs at the lowest priority. The Idle Thread function is located in the RTX_Config.c file: </p><div class="fragment"><div class="line">__WEAK <a class="code hl_define" href="cmsis__os2_8h.html#a153a4a31b276a9758959580538720a51">__NO_RETURN</a> <span class="keywordtype">void</span> osRtxIdleThread (<span class="keywordtype">void</span> *argument) {</div>
374 <div class="line">  (void)argument;</div>
375 <div class="line"> </div>
376 <div class="line">  <span class="keywordflow">for</span> (;;) {}</div>
377 <div class="line">}</div>
378 </div><!-- fragment --><p> You can add any code to this thread, but it has to obey the same rules as user threads. The simplest use of the idle demon is to place the microcontroller into a low-power mode when it is not doing anything. </p><div class="fragment"><div class="line">__WEAK <a class="code hl_define" href="cmsis__os2_8h.html#a153a4a31b276a9758959580538720a51">__NO_RETURN</a> <span class="keywordtype">void</span> osRtxIdleThread (<span class="keywordtype">void</span> *argument) {</div>
379 <div class="line">  (void)argument;</div>
380 <div class="line"> </div>
381 <div class="line">  <span class="keywordflow">for</span> (;;) {</div>
382 <div class="line">    __WFE();</div>
383 <div class="line">  }</div>
384 <div class="line">}</div>
385 </div><!-- fragment --><p> What happens next depends on the power mode selected in the microcontroller. At a minimum, the CPU will halt until an interrupt is generated by the SysTick timer and execution of the scheduler will resume. If there is a thread ready to run, then execution of the application code will resume. Otherwise, the idle demon will be reentered and the system will go back to sleep.</p>
386 <h2><a class="anchor" id="rtos2_tutorial_ex8"></a>
387 Exercise 8 - Idle Thread</h2>
388 <p>Open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
389 <li>Use the <b>Search</b> box on the <b>Boards</b> tab to look for the <b>CMSIS_RTOS_Tutorial (V2.1)</b> "board".</li>
390 <li>On the <b>Examples</b> tab, copy <b>Ex 08 Idle Thread</b> to your PC and start Keil MDK.</li>
391 <li>In the project folder, you will find a file called "Instructions.pdf" that explains the setup and the steps you need to take to successfully finish the exercise.</li>
392 </ul>
393 <h1><a class="anchor" id="rtos2_tutorial_interthread_com"></a>
394 Inter-thread Communication</h1>
395 <p>So far, we have seen how application code can be defined as independent threads and how we can access the timing services provided by the RTOS. In a real application, we need to be able to communicate between threads in order to make an application useful. To this end, a typical RTOS supports several different communication objects which can be used to link the threads together to form a meaningful program. The CMSIS-RTOS2 API supports inter-thread communication with thread and event flags, semaphores, mutexes, mailboxes and message queues. In the first section, the key concept was concurrency. In this section, the key concept is synchronizing the activity of multiple threads.</p>
396 <h2><a class="anchor" id="rtos2_tutorial_thread_flags"></a>
397 Thread Flags</h2>
398 <p>Keil RTX5 supports up to thirty two thread flags for each thread. These thread flags are stored in the thread control block. It is possible to halt the execution of a thread until a particular thread flag or group of thread flags are set by another thread in the system.</p>
399 <p>The <a class="el" href="group__CMSIS__RTOS__ThreadFlagsMgmt.html#gac11542ad6300b600f872fc96e340ec2b">osThreadFlagsWait()</a> system calls will suspend execution of the thread and place it into the wait_evnt state. Execution of the thread will not start until at least one the flags set in the <a class="el" href="group__CMSIS__RTOS__ThreadFlagsMgmt.html#gac11542ad6300b600f872fc96e340ec2b">osThreadFlagsWait()</a> API call have been set. It is also possible to define a periodic timeout after which the waiting thread will move back to the ready state, so that it can resume execution when selected by the scheduler. A value of <a class="el" href="group__CMSIS__RTOS__Definitions.html#ga9eb9a7a797a42e4b55eb171ecc609ddb">osWaitForever</a> (0xFFFF) defines an infinite timeout period. </p><div class="fragment"><div class="line">osEvent <a class="code hl_function" href="group__CMSIS__RTOS__ThreadFlagsMgmt.html#gac11542ad6300b600f872fc96e340ec2b">osThreadFlagsWait</a> (int32_t flags,int32_t options,uint32_t timeout);</div>
400 <div class="ttc" id="agroup__CMSIS__RTOS__ThreadFlagsMgmt_html_gac11542ad6300b600f872fc96e340ec2b"><div class="ttname"><a href="group__CMSIS__RTOS__ThreadFlagsMgmt.html#gac11542ad6300b600f872fc96e340ec2b">osThreadFlagsWait</a></div><div class="ttdeci">uint32_t osThreadFlagsWait(uint32_t flags, uint32_t options, uint32_t timeout)</div><div class="ttdoc">Wait for one or more Thread Flags of the current running thread to become signaled.</div></div>
401 </div><!-- fragment --><p> The thread flag options are as follows: </p><table class="markdownTable">
402 <tr class="markdownTableHead">
403 <th class="markdownTableHeadNone">Options   </th><th class="markdownTableHeadNone">Description    </th></tr>
404 <tr class="markdownTableRowOdd">
405 <td class="markdownTableBodyNone"><a class="el" href="group__CMSIS__RTOS__Definitions.html#ga18e63587b8450d5b8798b6f6ec04e012">osFlagsWaitAny</a>   </td><td class="markdownTableBodyNone">Wait for any flag to be set(default)    </td></tr>
406 <tr class="markdownTableRowEven">
407 <td class="markdownTableBodyNone"><a class="el" href="group__CMSIS__RTOS__Definitions.html#ga8b6f562736fbfb5428940e0c017dec24">osFlagsWaitAll</a>   </td><td class="markdownTableBodyNone">Wait for all flags to be set    </td></tr>
408 <tr class="markdownTableRowOdd">
409 <td class="markdownTableBodyNone"><a class="el" href="group__CMSIS__RTOS__Definitions.html#gaade844a42237d8c37569d4d9b16b9f1c">osFlagsNoClear</a>   </td><td class="markdownTableBodyNone">Do not clear flags that have been specified to wait for   </td></tr>
410 </table>
411 <p>If a pattern of flags is specified, the thread will resume execution when any one of the specified flags is set (Logic OR). If the <a class="el" href="group__CMSIS__RTOS__Definitions.html#ga8b6f562736fbfb5428940e0c017dec24">osFlagsWaitAll</a> option is used, then all the flags in the pattern must be set (Logic AND). Any thread can set a flag on any other thread and a thread may clear its own flags: </p><div class="fragment"><div class="line">int32_t osThredFlagsSet (<a class="code hl_typedef" href="group__CMSIS__RTOS__ThreadMgmt.html#gaa6c32fe2a3e0a2e01f212d55b02e51c7">osThreadId_t</a>  thread_id, int32_t flags);</div>
412 <div class="line">int32_t <a class="code hl_function" href="group__CMSIS__RTOS__ThreadFlagsMgmt.html#ga656abc1c862c5b9a2b13584c42cc0bfa">osThreadFlagsClear</a> (int32_t signals);</div>
413 <div class="ttc" id="agroup__CMSIS__RTOS__ThreadFlagsMgmt_html_ga656abc1c862c5b9a2b13584c42cc0bfa"><div class="ttname"><a href="group__CMSIS__RTOS__ThreadFlagsMgmt.html#ga656abc1c862c5b9a2b13584c42cc0bfa">osThreadFlagsClear</a></div><div class="ttdeci">uint32_t osThreadFlagsClear(uint32_t flags)</div><div class="ttdoc">Clear the specified Thread Flags of current running thread.</div></div>
414 </div><!-- fragment --><h3><a class="anchor" id="rtos2_tutorial_ex9"></a>
415 Exercise 9 - Thread Flags</h3>
416 <p>Open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
417 <li>Use the <b>Search</b> box on the <b>Boards</b> tab to look for the <b>CMSIS_RTOS_Tutorial (V2.1)</b> "board".</li>
418 <li>On the <b>Examples</b> tab, copy <b>Ex 09 Thread Flags</b> to your PC and start Keil MDK.</li>
419 <li>In the project folder, you will find a file called "Instructions.pdf" that explains the setup and the steps you need to take to successfully finish the exercise.</li>
420 </ul>
421 <h2><a class="anchor" id="rtos2_tutorial_event_flags"></a>
422 Event Flags</h2>
423 <p>Event flags operate in a similar fashion to thread flags but must be created and then act as a global RTOS object that can be used by all the running threads.</p>
424 <p>First, we need to create a set of event flags, this is a similar process to creating a thread. We define an event flag attribute structure. The attribute structure defines an ASCII name string, attribute bits, and memory detention. If we are using the static memory model. </p><div class="fragment"><div class="line"><a class="code hl_struct" href="group__CMSIS__RTOS__EventFlags.html#structosEventFlagsAttr__t">osEventFlagsAttr_t</a> {</div>
425 <div class="line">  <span class="keyword">const</span> <span class="keywordtype">char</span> *<a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#ab74e6bf80237ddc4109968cedc58c151">name</a>;   <span class="comment">///&lt; name of the event flags</span></div>
426 <div class="line">  uint32_t <a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#a6e93b49cb79c12f768d72580c7731f30">attr_bits</a>; <span class="comment">///&lt; attribute bits (none)</span></div>
427 <div class="line">  <span class="keywordtype">void</span> *<a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#a1e100dc33d403841ed3c344e3397868e">cb_mem</a>;       <span class="comment">///&lt; memory for control block</span></div>
428 <div class="line">  uint32_t <a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#aa55a4335d12dc2785dc00fdc292d1159">cb_size</a>;   <span class="comment">///&lt; size of provided memory for control block</span></div>
429 <div class="line">};</div>
430 <div class="ttc" id="agroup__CMSIS__RTOS__EventFlags_html_structosEventFlagsAttr__t"><div class="ttname"><a href="group__CMSIS__RTOS__EventFlags.html#structosEventFlagsAttr__t">osEventFlagsAttr_t</a></div><div class="ttdoc">Attributes structure for event flags.</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:303</div></div>
431 </div><!-- fragment --><p> Next we need a handle to control access the event flags: </p><div class="fragment"><div class="line"><a class="code hl_typedef" href="group__CMSIS__RTOS__EventFlags.html#gafdbab933146d6d81d7cca7287e267a50">osEventFlagsId_t</a> EventFlag_LED;</div>
432 <div class="ttc" id="agroup__CMSIS__RTOS__EventFlags_html_gafdbab933146d6d81d7cca7287e267a50"><div class="ttname"><a href="group__CMSIS__RTOS__EventFlags.html#gafdbab933146d6d81d7cca7287e267a50">osEventFlagsId_t</a></div><div class="ttdeci">void * osEventFlagsId_t</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:259</div></div>
433 </div><!-- fragment --><p> Then we can create the event flag object: </p><div class="fragment"><div class="line">EventFlag_LED = <a class="code hl_function" href="group__CMSIS__RTOS__EventFlags.html#gab14b1caeb12ffa42cce1bfe889cd07df">osEventFlagsNew</a>(&amp;EventFlagAttr_LED);</div>
434 <div class="ttc" id="agroup__CMSIS__RTOS__EventFlags_html_gab14b1caeb12ffa42cce1bfe889cd07df"><div class="ttname"><a href="group__CMSIS__RTOS__EventFlags.html#gab14b1caeb12ffa42cce1bfe889cd07df">osEventFlagsNew</a></div><div class="ttdeci">osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t *attr)</div><div class="ttdoc">Create and Initialize an Event Flags object.</div></div>
435 </div><!-- fragment --><p> Refer to <a class="el" href="group__CMSIS__RTOS__EventFlags.html">Event Flags</a> for more information.</p>
436 <h3><a class="anchor" id="rtos2_tutorial_ex10"></a>
437 Exercise 10 - Event Flags</h3>
438 <p>Open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
439 <li>Use the <b>Search</b> box on the <b>Boards</b> tab to look for the <b>CMSIS_RTOS_Tutorial (V2.1)</b> "board".</li>
440 <li>On the <b>Examples</b> tab, copy <b>Ex 10 Event Flags</b> to your PC and start Keil MDK.</li>
441 <li>In the project folder, you will find a file called "Instructions.pdf" that explains the setup and the steps you need to take to successfully finish the exercise.</li>
442 </ul>
443 <h2><a class="anchor" id="rtos2_tutorial_semaphores"></a>
444 Semaphores</h2>
445 <p>Like thread flags, semaphores are a method of synchronizing activity between two or more threads. Put simply, a semaphore is a container that holds a number of tokens. As a thread executes, it will reach an RTOS call to acquire a semaphore token. If the semaphore contains one or more tokens, the thread will continue executing and the number of tokens in the semaphore will be decremented by one. If there are currently no tokens in the semaphore, the thread will be placed in a waiting state until a token becomes available. At any point in its execution, a thread may add a token to the semaphore causing its token count to increment by one.</p>
446 <p>The diagram above illustrates the use of a semaphore to synchronize two threads. First, the semaphore must be created and initialized with an initial token count. In this case the semaphore is initialized with a single token. Both threads will run and reach a point in their code where they will attempt to acquire a token from the semaphore. The first thread to reach this point will acquire the token from the semaphore and continue execution. The second thread will also attempt to acquire a token, but as the semaphore is empty it will halt execution and be placed into a waiting state until a semaphore token is available.</p>
447 <p>Meanwhile, the executing thread can release a token back to the semaphore. When this happens, the waiting thread will acquire the token and leave the waiting state for the ready state. Once in the ready state the scheduler will place the thread into the run state so that thread execution can continue. While semaphores have a simple set of OS calls they can be one of the more difficult OS objects to fully understand. In this section, we will first look at how to add semaphores to an RTOS program and then go on to look at the most useful semaphore applications.</p>
448 <p>To use a semaphore in the CMSIS-RTOS you must first declare a semaphore attributes: </p><div class="fragment"><div class="line"><a class="code hl_struct" href="group__CMSIS__RTOS__SemaphoreMgmt.html#structosSemaphoreAttr__t">osSemaphoreAttr_t</a> {</div>
449 <div class="line">  <span class="keyword">const</span> <span class="keywordtype">char</span> *<a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#ab74e6bf80237ddc4109968cedc58c151">name</a>;   <span class="comment">///&lt; name of the semaphore</span></div>
450 <div class="line">  uint32_t <a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#a6e93b49cb79c12f768d72580c7731f30">attr_bits</a>; <span class="comment">///&lt; attribute bits (none)</span></div>
451 <div class="line">  <span class="keywordtype">void</span> *<a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#a1e100dc33d403841ed3c344e3397868e">cb_mem</a>;       <span class="comment">///&lt; memory for control block</span></div>
452 <div class="line">  uint32_t <a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#aa55a4335d12dc2785dc00fdc292d1159">cb_size</a>;   <span class="comment">///&lt; size of provided memory for control block</span></div>
453 <div class="line">};</div>
454 <div class="ttc" id="agroup__CMSIS__RTOS__SemaphoreMgmt_html_structosSemaphoreAttr__t"><div class="ttname"><a href="group__CMSIS__RTOS__SemaphoreMgmt.html#structosSemaphoreAttr__t">osSemaphoreAttr_t</a></div><div class="ttdoc">Attributes structure for semaphore.</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:319</div></div>
455 </div><!-- fragment --><p> Next declare the semaphore handle: </p><div class="fragment"><div class="line"><a class="code hl_typedef" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga6e1c1c4b04175bb92b013c8f37249f40">osSemaphoreId_t</a> sem1;</div>
456 <div class="ttc" id="agroup__CMSIS__RTOS__SemaphoreMgmt_html_ga6e1c1c4b04175bb92b013c8f37249f40"><div class="ttname"><a href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga6e1c1c4b04175bb92b013c8f37249f40">osSemaphoreId_t</a></div><div class="ttdeci">void * osSemaphoreId_t</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:265</div></div>
457 </div><!-- fragment --><p> Then within a thread the semaphore container can be initialised with a number of tokens: </p><div class="fragment"><div class="line">sem1 = <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga2a39806ace781a0008a4374ca701b14a">osSemaphoreNew</a>(maxTokenCount,initalTokencount,&amp;<a class="code hl_struct" href="group__CMSIS__RTOS__SemaphoreMgmt.html#structosSemaphoreAttr__t">osSemaphoreAttr_t</a>);</div>
458 <div class="ttc" id="agroup__CMSIS__RTOS__SemaphoreMgmt_html_ga2a39806ace781a0008a4374ca701b14a"><div class="ttname"><a href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga2a39806ace781a0008a4374ca701b14a">osSemaphoreNew</a></div><div class="ttdeci">osSemaphoreId_t osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr)</div><div class="ttdoc">Create and Initialize a Semaphore object.</div></div>
459 </div><!-- fragment --><p> It is important to understand that semaphore tokens may also be created and destroyed as threads run. So for example you can initialise a semaphore with zero tokens and then use one thread to create tokens into the semaphore while another thread removes them. This allows you to design threads as producer and consumer threads.</p>
460 <p>Once the semaphore is initialized, tokens may be acquired and sent to the semaphore in a similar fashion to event flags. The <a class="el" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga7e94c8b242a0c81f2cc79ec22895c87b">osSemaphoreAcquire()</a> call is used to block a thread until a semaphore token is available. A timeout period may also be specified with 0xFFFF being an infinite wait. </p><div class="fragment"><div class="line">osStatus <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga7e94c8b242a0c81f2cc79ec22895c87b">osSemaphoreAcquire</a>(<a class="code hl_typedef" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga6e1c1c4b04175bb92b013c8f37249f40">osSemaphoreId_t</a> semaphore_id, uint32_t ticks);</div>
461 <div class="ttc" id="agroup__CMSIS__RTOS__SemaphoreMgmt_html_ga7e94c8b242a0c81f2cc79ec22895c87b"><div class="ttname"><a href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga7e94c8b242a0c81f2cc79ec22895c87b">osSemaphoreAcquire</a></div><div class="ttdeci">osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout)</div><div class="ttdoc">Acquire a Semaphore token or timeout if no tokens are available.</div></div>
462 </div><!-- fragment --><p> Once the thread has finished using the semaphore resource, it can send a token to the semaphore container: </p><div class="fragment"><div class="line">osStatus <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga0abcee1b5449d7a6928fb9248c690bb6">osSemaphoreRelease</a>(<a class="code hl_typedef" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga6e1c1c4b04175bb92b013c8f37249f40">osSemaphoreId_t</a> semaphore_id);</div>
463 <div class="ttc" id="agroup__CMSIS__RTOS__SemaphoreMgmt_html_ga0abcee1b5449d7a6928fb9248c690bb6"><div class="ttname"><a href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga0abcee1b5449d7a6928fb9248c690bb6">osSemaphoreRelease</a></div><div class="ttdeci">osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id)</div><div class="ttdoc">Release a Semaphore token up to the initial maximum count.</div></div>
464 </div><!-- fragment --><p> All semaphore functions are listed in the <a class="el" href="group__CMSIS__RTOS__SemaphoreMgmt.html">reference</a>.</p>
465 <h3><a class="anchor" id="rtos2_tutorial_sem_usage"></a>
466 Using Semaphores</h3>
467 <p>Although semaphores have a simple set of OS calls, they have a wide range of synchronizing applications. This makes them perhaps the most challenging RTOS object to understand. In this section we, will look at the most common uses of semaphores. These are taken from free book <a href="https://greenteapress.com/wp/semaphores/" target="_blank">"The Little Book Of Semaphores" by Allen B. Downey</a>.</p>
468 <h3><a class="anchor" id="rtos2_tutorial_sem_sig"></a>
469 Signalling</h3>
470 <p>Synchronizing the execution of two threads is the simplest use of a semaphore: </p><div class="fragment"><div class="line"><a class="code hl_typedef" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga6e1c1c4b04175bb92b013c8f37249f40">osSemaphoreId_t</a> sem1;</div>
471 <div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <a class="code hl_struct" href="group__CMSIS__RTOS__SemaphoreMgmt.html#structosSemaphoreAttr__t">osSemaphoreAttr_t</a> semAttr_SEM1 = {</div>
472 <div class="line">    .<a class="code hl_variable" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ab74e6bf80237ddc4109968cedc58c151">name</a> = <span class="stringliteral">&quot;SEM1&quot;</span>,</div>
473 <div class="line">};</div>
474 <div class="line"> </div>
475 <div class="line"><span class="keywordtype">void</span> thread1(<span class="keywordtype">void</span>) {</div>
476 <div class="line">  sem1 = <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga2a39806ace781a0008a4374ca701b14a">osSemaphoreNew</a>(5, 0, &amp;semAttr_SEM1);</div>
477 <div class="line">  <span class="keywordflow">while</span> (1) {</div>
478 <div class="line">    FuncA();</div>
479 <div class="line">    <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga0abcee1b5449d7a6928fb9248c690bb6">osSemaphoreRelease</a>(sem1)</div>
480 <div class="line">  }</div>
481 <div class="line">}</div>
482 <div class="line"> </div>
483 <div class="line"><span class="keywordtype">void</span> task2(<span class="keywordtype">void</span>) {</div>
484 <div class="line"> </div>
485 <div class="line">  <span class="keywordflow">while</span> (1) {</div>
486 <div class="line">    <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga7e94c8b242a0c81f2cc79ec22895c87b">osSemaphoreAcquire</a>(sem1, <a class="code hl_define" href="group__CMSIS__RTOS__Definitions.html#ga9eb9a7a797a42e4b55eb171ecc609ddb">osWaitForever</a>) FuncB();</div>
487 <div class="line">  }</div>
488 <div class="line">}</div>
489 <div class="ttc" id="agroup__CMSIS__RTOS__SemaphoreMgmt_html_ab74e6bf80237ddc4109968cedc58c151"><div class="ttname"><a href="group__CMSIS__RTOS__SemaphoreMgmt.html#ab74e6bf80237ddc4109968cedc58c151">osSemaphoreAttr_t::name</a></div><div class="ttdeci">const char * name</div><div class="ttdoc">name of the semaphore</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:320</div></div>
490 </div><!-- fragment --><p> In this case the semaphore is used to ensure that the code in <code>FuncA()</code> is executed before the code in <code>FuncB()</code>.</p>
491 <h3><a class="anchor" id="rtos2_tutorial_ex11"></a>
492 Exercise 11 - Semaphore Signalling</h3>
493 <p>Open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
494 <li>Use the <b>Search</b> box on the <b>Boards</b> tab to look for the <b>CMSIS_RTOS_Tutorial (V2.1)</b> "board".</li>
495 <li>On the <b>Examples</b> tab, copy <b>Ex 11 Semaphore Signalling</b> to your PC and start Keil MDK.</li>
496 <li>In the project folder, you will find a file called "Instructions.pdf" that explains the setup and the steps you need to take to successfully finish the exercise.</li>
497 </ul>
498 <h3><a class="anchor" id="rtos2_tutorial_sem_multi"></a>
499 Multiplex</h3>
500 <p>A multiplex is used to limit the number of threads that can access a critical section of code. For example, this could be a routine that accesses memory resources and can only support a limited number of calls. </p><div class="fragment"><div class="line"><a class="code hl_typedef" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga6e1c1c4b04175bb92b013c8f37249f40">osSemaphoreId_t</a> multiplex;</div>
501 <div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <a class="code hl_struct" href="group__CMSIS__RTOS__SemaphoreMgmt.html#structosSemaphoreAttr__t">osSemaphoreAttr_t</a> semAttr_Multiplex = {</div>
502 <div class="line">    .<a class="code hl_variable" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ab74e6bf80237ddc4109968cedc58c151">name</a> = <span class="stringliteral">&quot;SEM1&quot;</span>,</div>
503 <div class="line">};</div>
504 <div class="line"> </div>
505 <div class="line"><span class="keywordtype">void</span> thread1(<span class="keywordtype">void</span>) {</div>
506 <div class="line">  multiplex = osSemaphoreCreate(5, 5, &amp;semAttr_Multiplex);</div>
507 <div class="line">  <span class="keywordflow">while</span> (1) {</div>
508 <div class="line">    <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga7e94c8b242a0c81f2cc79ec22895c87b">osSemaphoreAcquire</a>(multiplex, <a class="code hl_define" href="group__CMSIS__RTOS__Definitions.html#ga9eb9a7a797a42e4b55eb171ecc609ddb">osWaitForever</a>);</div>
509 <div class="line">    processBuffer();</div>
510 <div class="line">    <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga0abcee1b5449d7a6928fb9248c690bb6">osSemaphoreRelease</a>(multiplex);</div>
511 <div class="line">  }</div>
512 <div class="line">}</div>
513 </div><!-- fragment --><p> In this example we initialise the multiplex semaphore with five tokens. Before a thread can call the <code>processBuffer()</code> function, it must acquire a semaphore token. Once the function has completed, the token is sent back to the semaphore. If more than five threads are attempting to call <code>processBuffer()</code>, the sixth must wait until a thread has finished with <code>processBuffer()</code> and returns its token. Thus, the multiplex semaphore ensures that a maximum of five threads can call the <code>processBuffer()</code> function "simultaneously".</p>
514 <h3><a class="anchor" id="rtos2_tutorial_ex12"></a>
515 Exercise 12 - Multiplex</h3>
516 <p>Open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
517 <li>Use the <b>Search</b> box on the <b>Boards</b> tab to look for the <b>CMSIS_RTOS_Tutorial (V2.1)</b> "board".</li>
518 <li>On the <b>Examples</b> tab, copy <b>Ex 12 Multiplex</b> to your PC and start Keil MDK.</li>
519 <li>In the project folder, you will find a file called "Instructions.pdf" that explains the setup and the steps you need to take to successfully finish the exercise.</li>
520 </ul>
521 <h3><a class="anchor" id="rtos2_tutorial_sem_rend"></a>
522 Rendezvous</h3>
523 <p>A more generalised form of semaphore signalling is a rendezvous. A rendezvous ensures that two threads reach a certain point of execution. Neither may continue until both have reached the rendezvous point. </p><div class="fragment"><div class="line"><a class="code hl_typedef" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga6e1c1c4b04175bb92b013c8f37249f40">osSemaphoreId_t</a> arrived1, arrived2;</div>
524 <div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <a class="code hl_struct" href="group__CMSIS__RTOS__SemaphoreMgmt.html#structosSemaphoreAttr__t">osSemaphoreAttr_t</a> semAttr_Arrived1 = {</div>
525 <div class="line">    .<a class="code hl_variable" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ab74e6bf80237ddc4109968cedc58c151">name</a> = <span class="stringliteral">&quot;Arr1&quot;</span>,</div>
526 <div class="line">};</div>
527 <div class="line"> </div>
528 <div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <a class="code hl_struct" href="group__CMSIS__RTOS__SemaphoreMgmt.html#structosSemaphoreAttr__t">osSemaphoreAttr_t</a> semAttr_Arrived2 = {</div>
529 <div class="line">    .<a class="code hl_variable" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ab74e6bf80237ddc4109968cedc58c151">name</a> = <span class="stringliteral">&quot;Arr2&quot;</span>,</div>
530 <div class="line">};</div>
531 <div class="line"> </div>
532 <div class="line"><span class="keywordtype">void</span> thread1(<span class="keywordtype">void</span>) {</div>
533 <div class="line">  arrived1 = <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga2a39806ace781a0008a4374ca701b14a">osSemaphoreNew</a>(2, 0);</div>
534 <div class="line">  arrived1 = <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga2a39806ace781a0008a4374ca701b14a">osSemaphoreNew</a>(2, 0);</div>
535 <div class="line">  <span class="keywordflow">while</span> (1) {</div>
536 <div class="line">    FuncA1();</div>
537 <div class="line">    <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga0abcee1b5449d7a6928fb9248c690bb6">osSemaphoreRelease</a>(arrived1);</div>
538 <div class="line">    <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga7e94c8b242a0c81f2cc79ec22895c87b">osSemaphoreAcquire</a>(arrived2, <a class="code hl_define" href="group__CMSIS__RTOS__Definitions.html#ga9eb9a7a797a42e4b55eb171ecc609ddb">osWaitForever</a>);</div>
539 <div class="line">    FuncA2();</div>
540 <div class="line">  }</div>
541 <div class="line">}</div>
542 <div class="line"> </div>
543 <div class="line"><span class="keywordtype">void</span> thread2(<span class="keywordtype">void</span>) {</div>
544 <div class="line">  <span class="keywordflow">while</span> (1) {</div>
545 <div class="line">    FuncB1();</div>
546 <div class="line">    os_sem_Release(arrived2);</div>
547 <div class="line">    os_sem_Acquire(arrived1, <a class="code hl_define" href="group__CMSIS__RTOS__Definitions.html#ga9eb9a7a797a42e4b55eb171ecc609ddb">osWaitForever</a>);</div>
548 <div class="line">    FuncB2();</div>
549 <div class="line">  }</div>
550 <div class="line">}</div>
551 </div><!-- fragment --><p> In the above case, the two semaphores will ensure that both threads will rendezvous and then proceed to execute <code>FuncA2()</code> and <code>FuncB2()</code>.</p>
552 <h3><a class="anchor" id="rtos2_tutorial_sem_rend_ex13"></a>
553 Exercise 13 - Rendezvous</h3>
554 <p>Open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
555 <li>Use the <b>Search</b> box on the <b>Boards</b> tab to look for the <b>CMSIS_RTOS_Tutorial (V2.1)</b> "board".</li>
556 <li>On the <b>Examples</b> tab, copy <b>Ex 13 Rendezvous</b> to your PC and start Keil MDK.</li>
557 <li>In the project folder, you will find a file called "Instructions.pdf" that explains the setup and the steps you need to take to successfully finish the exercise.</li>
558 </ul>
559 <h3><a class="anchor" id="rtos2_tutorial_sem_barr_turn"></a>
560 Barrier Turnstile</h3>
561 <p>Although a rendezvous is very useful for synchronising the execution of code, it only works for two functions. A barrier is a more generalised form of rendezvous which works to synchronise multiple threads. </p><div class="fragment"><div class="line"><a class="code hl_typedef" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga6e1c1c4b04175bb92b013c8f37249f40">osSemaphoreId_t</a> count, barrier;</div>
562 <div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <a class="code hl_struct" href="group__CMSIS__RTOS__SemaphoreMgmt.html#structosSemaphoreAttr__t">osSemaphoreAttr_t</a> semAttr_Counter = {</div>
563 <div class="line">    .<a class="code hl_variable" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ab74e6bf80237ddc4109968cedc58c151">name</a> = <span class="stringliteral">&quot;Counter&quot;</span>,</div>
564 <div class="line">};</div>
565 <div class="line"> </div>
566 <div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <a class="code hl_struct" href="group__CMSIS__RTOS__SemaphoreMgmt.html#structosSemaphoreAttr__t">osSemaphoreAttr_t</a> semAttr_Barier = {</div>
567 <div class="line">    .<a class="code hl_variable" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ab74e6bf80237ddc4109968cedc58c151">name</a> = <span class="stringliteral">&quot;Barrier&quot;</span>,</div>
568 <div class="line">};</div>
569 <div class="line"> </div>
570 <div class="line"><span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> count;</div>
571 <div class="line"> </div>
572 <div class="line"><span class="keywordtype">void</span> thread1(<span class="keywordtype">void</span>) {</div>
573 <div class="line">  Turnstile_In = <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga2a39806ace781a0008a4374ca701b14a">osSemaphoreNew</a>(5, 0, &amp;semAttr_SEM_In);</div>
574 <div class="line">  Turnstile_Out = <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga2a39806ace781a0008a4374ca701b14a">osSemaphoreNew</a>(5, 1, &amp;semAttr_SEM_Out);</div>
575 <div class="line">  Mutex = <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga2a39806ace781a0008a4374ca701b14a">osSemaphoreNew</a>(1, 1, &amp;semAttr_Mutex);</div>
576 <div class="line">  <span class="keywordflow">while</span> (1) {</div>
577 <div class="line">    <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga7e94c8b242a0c81f2cc79ec22895c87b">osSemaphoreAcquire</a>(Mutex, <a class="code hl_define" href="group__CMSIS__RTOS__Definitions.html#ga9eb9a7a797a42e4b55eb171ecc609ddb">osWaitForever</a>); <span class="comment">// Allow one task at a time to</span></div>
578 <div class="line">                                              <span class="comment">// access the first turnstile</span></div>
579 <div class="line">    count = count + 1; <span class="comment">// Increment count</span></div>
580 <div class="line">    <span class="keywordflow">if</span> (count == 5) {</div>
581 <div class="line">      <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga7e94c8b242a0c81f2cc79ec22895c87b">osSemaphoreAcquire</a>(Turnstile_Out,</div>
582 <div class="line">                         <a class="code hl_define" href="group__CMSIS__RTOS__Definitions.html#ga9eb9a7a797a42e4b55eb171ecc609ddb">osWaitForever</a>); <span class="comment">// Lock the second turnstile</span></div>
583 <div class="line">      <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga0abcee1b5449d7a6928fb9248c690bb6">osSemaphoreRelease</a>(Turnstile_In);  <span class="comment">// Unlock the first turnstile</span></div>
584 <div class="line">    }</div>
585 <div class="line">    <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga0abcee1b5449d7a6928fb9248c690bb6">osSemaphoreRelease</a>(Mutex); <span class="comment">// Allow other tasks to access the turnstile</span></div>
586 <div class="line">    <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga7e94c8b242a0c81f2cc79ec22895c87b">osSemaphoreAcquire</a>(Turnstile_In, <a class="code hl_define" href="group__CMSIS__RTOS__Definitions.html#ga9eb9a7a797a42e4b55eb171ecc609ddb">osWaitForever</a>); <span class="comment">// Turnstile Gate</span></div>
587 <div class="line">    <a class="code hl_function" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga0abcee1b5449d7a6928fb9248c690bb6">osSemaphoreRelease</a>(Turnstile_In);</div>
588 <div class="line">    critical_Function();</div>
589 <div class="line">  }</div>
590 <div class="line">}</div>
591 </div><!-- fragment --><p> In this code, we use a global variable to count the number of threads which have arrived at the barrier. As each function arrives at the barrier it will wait until it can acquire a token from the counter semaphore. Once acquired, the count variable will be incremented by one. Once we have incremented the count variable, a token is sent to the counter semaphore so that other waiting threads can proceed. Next, the barrier code reads the count variable. If this is equal to the number of threads which are waiting to arrive at the barrier, we send a token to the barrier semaphore.</p>
592 <p>In the example above we are synchronising five threads. The first four threads will increment the count variable and then wait at the barrier semaphore. The fifth and last thread to arrive will increment the count variable and send a token to the barrier semaphore. This will allow it to immediately acquire a barrier semaphore token and continue execution. After passing through the barrier, it immediately sends another token to the barrier semaphore. This allows one of the other waiting threads to resume execution. This thread places another token in the barrier semaphore which triggers another waiting thread and so on. This final section of the barrier code is called a turnstile because it allows one thread at a time to pass the barrier. In our model of concurrent execution this means that each thread waits at the barrier until the last arrives then the all resume simultaneously. In the following exercise we create five instances of one thread containing barrier code. However, the barrier could be used to synchronise five unique threads.</p>
593 <h3><a class="anchor" id="rtos2_tutorial_ex14"></a>
594 Exercise 14 - Semaphore Barrier</h3>
595 <p>Open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
596 <li>Use the <b>Search</b> box on the <b>Boards</b> tab to look for the <b>CMSIS_RTOS_Tutorial (V2.1)</b> "board".</li>
597 <li>On the <b>Examples</b> tab, copy <b>Ex 14 Barrier</b> to your PC and start Keil MDK.</li>
598 <li>In the project folder, you will find a file called "Instructions.pdf" that explains the setup and the steps you need to take to successfully finish the exercise.</li>
599 </ul>
600 <h3><a class="anchor" id="rtos2_tutorial_sem_caveats"></a>
601 Semaphore Caveats</h3>
602 <p>Semaphores are an extremely useful feature of any RTOS. However semaphores can be misused. You must always remember that the number of tokens in a semaphore is not fixed. During the runtime of a program semaphore tokens may be created and destroyed. Sometimes this is useful, but if your code depends on having a fixed number of tokens available to a semaphore you must be very careful to always return tokens back to it. You should also rule out the possibility of accidently creating additional new tokens.</p>
603 <h2><a class="anchor" id="rtos2_tutorial_mutex"></a>
604 Mutex</h2>
605 <p>Mutex stands for “Mutual Exclusion”. In reality, a mutex is a specialized version of semaphore. Like a semaphore, a mutex is a container for tokens. The difference is that a mutex can only contain one token which cannot be created or destroyed. The principle use of a mutex is to control access to a chip resource such as a peripheral. For this reason a mutex token is binary and bounded. Apart from this it really works in the same way as a semaphore. First of all we must declare the mutex container and initialize the mutex: </p><div class="fragment"><div class="line"><a class="code hl_typedef" href="group__CMSIS__RTOS__MutexMgmt.html#ga313801836c62deb23055efb55a420e42">osMutexId_t</a> uart_mutex;</div>
606 <div class="line"> </div>
607 <div class="line"><a class="code hl_struct" href="group__CMSIS__RTOS__MutexMgmt.html#structosMutexAttr__t">osMutexAttr_t</a> {</div>
608 <div class="line">  <span class="keyword">const</span> <span class="keywordtype">char</span> *<a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#ab74e6bf80237ddc4109968cedc58c151">name</a>;   <span class="comment">///&lt; name of the mutex</span></div>
609 <div class="line">  uint32_t <a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#a6e93b49cb79c12f768d72580c7731f30">attr_bits</a>; <span class="comment">///&lt; attribute bits</span></div>
610 <div class="line">  <span class="keywordtype">void</span> *<a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#a1e100dc33d403841ed3c344e3397868e">cb_mem</a>;       <span class="comment">///&lt; memory for control block</span></div>
611 <div class="line">  uint32_t <a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#aa55a4335d12dc2785dc00fdc292d1159">cb_size</a>;   <span class="comment">///&lt; size of provided memory for control block</span></div>
612 <div class="line">};</div>
613 <div class="ttc" id="agroup__CMSIS__RTOS__MutexMgmt_html_ga313801836c62deb23055efb55a420e42"><div class="ttname"><a href="group__CMSIS__RTOS__MutexMgmt.html#ga313801836c62deb23055efb55a420e42">osMutexId_t</a></div><div class="ttdeci">void * osMutexId_t</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:262</div></div>
614 <div class="ttc" id="agroup__CMSIS__RTOS__MutexMgmt_html_structosMutexAttr__t"><div class="ttname"><a href="group__CMSIS__RTOS__MutexMgmt.html#structosMutexAttr__t">osMutexAttr_t</a></div><div class="ttdoc">Attributes structure for mutex.</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:311</div></div>
615 </div><!-- fragment --><p> When a mutex is created its functionality can be modified by setting the following attribute bits: </p><table class="markdownTable">
616 <tr class="markdownTableHead">
617 <th class="markdownTableHeadNone">Bitmask   </th><th class="markdownTableHeadNone">Description    </th></tr>
618 <tr class="markdownTableRowOdd">
619 <td class="markdownTableBodyNone"><a class="el" href="group__CMSIS__RTOS__MutexMgmt.html#ga65c2482cc64a35d03871f3180f305926">osMutexRecursive</a>   </td><td class="markdownTableBodyNone">The same thread can consume a mutex multiple times without locking itself.    </td></tr>
620 <tr class="markdownTableRowEven">
621 <td class="markdownTableBodyNone"><a class="el" href="group__CMSIS__RTOS__MutexMgmt.html#ga40fba270cb31a977b3bd551d41eb9599">osMutexPrioInherit</a>   </td><td class="markdownTableBodyNone">While a thread owns the mutex it cannot be preempted by a higher priority thread.    </td></tr>
622 <tr class="markdownTableRowOdd">
623 <td class="markdownTableBodyNone"><a class="el" href="group__CMSIS__RTOS__MutexMgmt.html#gaf0e1dee376798b4d516d164981526780">osMutexRobust</a>   </td><td class="markdownTableBodyNone">Notify threads that acquire a mutex that the previous owner was terminated.   </td></tr>
624 </table>
625 <p>Once declared the mutex must be created in a thread. </p><div class="fragment"><div class="line">uart_mutex = <a class="code hl_function" href="group__CMSIS__RTOS__MutexMgmt.html#gab90920022ab944296821368ef6bb52f8">osMutexNew</a>(&amp;MutexAttr);</div>
626 <div class="ttc" id="agroup__CMSIS__RTOS__MutexMgmt_html_gab90920022ab944296821368ef6bb52f8"><div class="ttname"><a href="group__CMSIS__RTOS__MutexMgmt.html#gab90920022ab944296821368ef6bb52f8">osMutexNew</a></div><div class="ttdeci">osMutexId_t osMutexNew(const osMutexAttr_t *attr)</div><div class="ttdoc">Create and Initialize a Mutex object.</div></div>
627 </div><!-- fragment --><p> Then any thread needing to access the peripheral must first acquire the mutex token: </p><div class="fragment"><div class="line"><a class="code hl_function" href="group__CMSIS__RTOS__MutexMgmt.html#gabc54686ea0fc281823b1763422d2a924">osMutexAcquire</a>(<a class="code hl_typedef" href="group__CMSIS__RTOS__MutexMgmt.html#ga313801836c62deb23055efb55a420e42">osMutexId_t</a> mutex_id,uint32_t ticks);</div>
628 <div class="ttc" id="agroup__CMSIS__RTOS__MutexMgmt_html_gabc54686ea0fc281823b1763422d2a924"><div class="ttname"><a href="group__CMSIS__RTOS__MutexMgmt.html#gabc54686ea0fc281823b1763422d2a924">osMutexAcquire</a></div><div class="ttdeci">osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout)</div><div class="ttdoc">Acquire a Mutex or timeout if it is locked.</div></div>
629 </div><!-- fragment --><p> Finally, when we are finished with the peripheral the mutex must be released: </p><div class="fragment"><div class="line"><a class="code hl_function" href="group__CMSIS__RTOS__MutexMgmt.html#gaea629705703580ff58776bf73c8db915">osMutexRelease</a>(<a class="code hl_typedef" href="group__CMSIS__RTOS__MutexMgmt.html#ga313801836c62deb23055efb55a420e42">osMutexId_t</a> mutex_id);</div>
630 <div class="ttc" id="agroup__CMSIS__RTOS__MutexMgmt_html_gaea629705703580ff58776bf73c8db915"><div class="ttname"><a href="group__CMSIS__RTOS__MutexMgmt.html#gaea629705703580ff58776bf73c8db915">osMutexRelease</a></div><div class="ttdeci">osStatus_t osMutexRelease(osMutexId_t mutex_id)</div><div class="ttdoc">Release a Mutex that was acquired by osMutexAcquire.</div></div>
631 </div><!-- fragment --><p> Mutex use is much more rigid than semaphore use, but is a much safer mechanism when controlling absolute access to underlying chip registers.</p>
632 <h3><a class="anchor" id="rtos2_tutorial_ex15"></a>
633 Exercise 15 - Mutex</h3>
634 <p>Open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
635 <li>Use the <b>Search</b> box on the <b>Boards</b> tab to look for the <b>CMSIS_RTOS_Tutorial (V2.1)</b> "board".</li>
636 <li>On the <b>Examples</b> tab, copy <b>Ex 15 Mutex</b> to your PC and start Keil MDK.</li>
637 <li>In the project folder, you will find a file called "Instructions.pdf" that explains the setup and the steps you need to take to successfully finish the exercise.</li>
638 </ul>
639 <h3><a class="anchor" id="rtos2_tutorial_mutex_caveats"></a>
640 Mutex Caveats</h3>
641 <p>Clearly, you must take care to return the mutex token when you are finished with the chip resource, or you will have effectively prevented any other thread from accessing it. You must also be extremely careful about using the <a class="el" href="group__CMSIS__RTOS__ThreadMgmt.html#ga2f8ba6dba6e9c065a6e236ffd410d74a">osThreadTerminate()</a> call on functions which control a mutex token. Keil RTX5 is designed to be a small footprint RTOS so that it can run on even the very small Cortex-M microcontrollers. Consequently, there is no thread deletion safety. This means that if you delete a thread which is controlling a mutex token, you will destroy the mutex token and prevent any further access to the guarded peripheral.</p>
642 <h2><a class="anchor" id="rtos2_tutorial_data_exchange"></a>
643 Data Exchange</h2>
644 <p>So far, all of the inter-thread communication methods have only been used to trigger execution of threads; they do not upport the exchange of program data between threads. Clearly, in a real program we will need to move data between threads. This could be done by reading and writing to globally declared variables. In anything but a very simple program, trying to guarantee data integrity would be extremely difficult and prone to unforeseen errors. The exchange of data between threads needs a more formal asynchronous method of communication.</p>
645 <p>CMSIS-RTOS provides two methods of data transfer between threads. The first method is a message queue which creates a buffered data 'pipe' between two threads. The message queue is designed to transfer integer values.</p>
646 <p>The second form of data transfer is a mail queue. This is very similar to a message queue except that it transfers blocks of data rather than a single integer.</p>
647 <p>Message and mail queues both provide a method for transferring data between threads. This allows you to view your design as a collection of objects (threads) interconnected by data flows. The data flow is implemented by message and mail queues. This provides both a buffered transfer of data and a well defined communication interface between threads. Starting with a system level design based on threads connected by mail and message queues allows you to code different subsystems of your project, especially useful if you are working in a team. Also as each thread has well defined inputs and outputs it is easy to isolate for testing and code reuse.</p>
648 <h3><a class="anchor" id="rtos2_tutorial_msg_queue"></a>
649 Message Queue</h3>
650 <p>To setup a message queue we first need to allocate the memory resources: </p><div class="fragment"><div class="line">osMessageQId_t Q_LED;</div>
651 <div class="line"> </div>
652 <div class="line"><a class="code hl_struct" href="group__CMSIS__RTOS__Message.html#structosMessageQueueAttr__t">osMessageQueueAttr_t</a> {</div>
653 <div class="line">  <span class="keyword">const</span> <span class="keywordtype">char</span> *<a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#ab74e6bf80237ddc4109968cedc58c151">name</a>;   <span class="comment">///&lt; name of the message queue</span></div>
654 <div class="line">  uint32_t <a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#a6e93b49cb79c12f768d72580c7731f30">attr_bits</a>; <span class="comment">///&lt; attribute bits</span></div>
655 <div class="line">  <span class="keywordtype">void</span> *<a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#a1e100dc33d403841ed3c344e3397868e">cb_mem</a>;       <span class="comment">///&lt; memory for control block</span></div>
656 <div class="line">  uint32_t <a class="code hl_variable" href="group__CMSIS__RTOS__TimerMgmt.html#aa55a4335d12dc2785dc00fdc292d1159">cb_size</a>;   <span class="comment">///&lt; size of provided memory for control block</span></div>
657 <div class="line">  <span class="keywordtype">void</span> *mq_mem;       <span class="comment">///&lt; memory for data storage</span></div>
658 <div class="line">  uint32_t mq_size;   <span class="comment">///&lt; size of provided memory for data storage</span></div>
659 <div class="line">};</div>
660 <div class="ttc" id="agroup__CMSIS__RTOS__Message_html_structosMessageQueueAttr__t"><div class="ttname"><a href="group__CMSIS__RTOS__Message.html#structosMessageQueueAttr__t">osMessageQueueAttr_t</a></div><div class="ttdoc">Attributes structure for message queue.</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:337</div></div>
661 </div><!-- fragment --><p> Once the message queue handle and attributes have been declared we can create the message queue in a thread: </p><div class="fragment"><div class="line">Q_LED = osMessageNew(DepthOfMesageQueue,WidthOfMessageQueue,&amp;osMessageQueueAttr);</div>
662 </div><!-- fragment --><p> Once the message queue has been created we can put data into the queue from one thread: </p><div class="fragment"><div class="line"><a class="code hl_function" href="group__CMSIS__RTOS__Message.html#gaa515fc8b956f721a8f72b2c505813bfc">osMessageQueuePut</a>(Q_LED,&amp;dataIn,messagePrioriy,<a class="code hl_define" href="group__CMSIS__RTOS__Definitions.html#ga9eb9a7a797a42e4b55eb171ecc609ddb">osWaitForever</a>);</div>
663 <div class="ttc" id="agroup__CMSIS__RTOS__Message_html_gaa515fc8b956f721a8f72b2c505813bfc"><div class="ttname"><a href="group__CMSIS__RTOS__Message.html#gaa515fc8b956f721a8f72b2c505813bfc">osMessageQueuePut</a></div><div class="ttdeci">osStatus_t osMessageQueuePut(osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout)</div><div class="ttdoc">Put a Message into a Queue or timeout if Queue is full.</div></div>
664 </div><!-- fragment --><p> and then read if from the queue in another: </p><div class="fragment"><div class="line">result = <a class="code hl_function" href="group__CMSIS__RTOS__Message.html#gad90d4959466a7a65105061da8256ab9e">osMessageQueueGet</a>(Q_LED,&amp;dataOut,messagePriority,<a class="code hl_define" href="group__CMSIS__RTOS__Definitions.html#ga9eb9a7a797a42e4b55eb171ecc609ddb">osWaitForever</a>);</div>
665 <div class="ttc" id="agroup__CMSIS__RTOS__Message_html_gad90d4959466a7a65105061da8256ab9e"><div class="ttname"><a href="group__CMSIS__RTOS__Message.html#gad90d4959466a7a65105061da8256ab9e">osMessageQueueGet</a></div><div class="ttdeci">osStatus_t osMessageQueueGet(osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout)</div><div class="ttdoc">Get a Message from a Queue or timeout if Queue is empty.</div></div>
666 </div><!-- fragment --><h3><a class="anchor" id="rtos2_tutorial_ex16"></a>
667 Exercise 16 - Message Queue</h3>
668 <p>Open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
669 <li>Use the <b>Search</b> box on the <b>Boards</b> tab to look for the <b>CMSIS_RTOS_Tutorial (V2.1)</b> "board".</li>
670 <li>On the <b>Examples</b> tab, copy <b>Ex 16 Message Queue</b> to your PC and start Keil MDK.</li>
671 <li>In the project folder, you will find a file called "Instructions.pdf" that explains the setup and the steps you need to take to successfully finish the exercise.</li>
672 </ul>
673 <h3><a class="anchor" id="rtos2_tutorial_ext_msg_queue"></a>
674 Extended Message Queue</h3>
675 <p>In the last example we defined a word wide message queue. If you need to send a larger amount of data it is also possible to define a message queue where each slot can hold more complex data. First, we can define a structure to hold our message data: </p><div class="fragment"><div class="line"><span class="keyword">typedef</span> <span class="keyword">struct </span>{</div>
676 <div class="line">  uint32_t duration;</div>
677 <div class="line">  uint32_t ledNumber;</div>
678 <div class="line">  uint8_t priority;</div>
679 <div class="line">} message_t;</div>
680 </div><!-- fragment --><p> Then we can define a message queue which is formatted to receive this type of message: </p><div class="fragment"><div class="line">Q_LED = <a class="code hl_function" href="group__CMSIS__RTOS__Message.html#ga24e895a00f9d484db33aaf784c57bfed">osMessageQueueNew</a>(16,<span class="keyword">sizeof</span>(message_t),&amp;queueAttr_Q_LED );  </div>
681 <div class="ttc" id="agroup__CMSIS__RTOS__Message_html_ga24e895a00f9d484db33aaf784c57bfed"><div class="ttname"><a href="group__CMSIS__RTOS__Message.html#ga24e895a00f9d484db33aaf784c57bfed">osMessageQueueNew</a></div><div class="ttdeci">osMessageQueueId_t osMessageQueueNew(uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr)</div><div class="ttdoc">Create and Initialize a Message Queue object.</div></div>
682 </div><!-- fragment --><h3><a class="anchor" id="rtos2_tutorial_ex17"></a>
683 Exercise 17 - Message Queue</h3>
684 <p>Open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
685 <li>Use the <b>Search</b> box on the <b>Boards</b> tab to look for the <b>CMSIS_RTOS_Tutorial (V2.1)</b> "board".</li>
686 <li>On the <b>Examples</b> tab, copy <b>Ex 17 Extended Message Queue</b> to your PC and start Keil MDK.</li>
687 <li>In the project folder, you will find a file called "Instructions.pdf" that explains the setup and the steps you need to take to successfully finish the exercise.</li>
688 </ul>
689 <h3><a class="anchor" id="rtos2_tutorial_mem_pool"></a>
690 Memory Pool</h3>
691 <p>We can design a message queue to support the transfer of large amounts of data. However, this method has an overhead in that we are "moving" the data in the queue. In this section, we will look at designing a more efficient "zero copy" mailbox where the data remains static. CMSIS-RTOS2 supports the dynamic allocation of memory in the form of a fixed block memory pool. First, we can declare the memory pool attributes: </p><div class="fragment"><div class="line"><a class="code hl_struct" href="group__CMSIS__RTOS__PoolMgmt.html#structosMemoryPoolAttr__t">osMemoryPoolAttr_t</a> {</div>
692 <div class="line">  <span class="keyword">const</span> <span class="keywordtype">char</span> *name;   <span class="comment">///&lt; name of the memory pool</span></div>
693 <div class="line">  uint32_t attr_bits; <span class="comment">///&lt; attribute bits</span></div>
694 <div class="line">  <span class="keywordtype">void</span> *cb_mem;       <span class="comment">///&lt; memory for control block</span></div>
695 <div class="line">  uint32_t cb_size;   <span class="comment">///&lt; size of provided memory for control block</span></div>
696 <div class="line">  <span class="keywordtype">void</span> *mp_mem;       <span class="comment">///&lt; memory for data storage</span></div>
697 <div class="line">  uint32_t mp_size;   <span class="comment">///&lt; size of provided memory for data storage</span></div>
698 <div class="line">} <a class="code hl_struct" href="group__CMSIS__RTOS__PoolMgmt.html#structosMemoryPoolAttr__t">osMemoryPoolAttr_t</a>;</div>
699 <div class="ttc" id="agroup__CMSIS__RTOS__PoolMgmt_html_structosMemoryPoolAttr__t"><div class="ttname"><a href="group__CMSIS__RTOS__PoolMgmt.html#structosMemoryPoolAttr__t">osMemoryPoolAttr_t</a></div><div class="ttdoc">Attributes structure for memory pool.</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:327</div></div>
700 </div><!-- fragment --><p> And a handle for the memory pool: </p><div class="fragment"><div class="line"><a class="code hl_typedef" href="group__CMSIS__RTOS__PoolMgmt.html#ga2e44473caf338266f56800960294f960">osMemoryPoolId_t</a> mpool;</div>
701 <div class="ttc" id="agroup__CMSIS__RTOS__PoolMgmt_html_ga2e44473caf338266f56800960294f960"><div class="ttname"><a href="group__CMSIS__RTOS__PoolMgmt.html#ga2e44473caf338266f56800960294f960">osMemoryPoolId_t</a></div><div class="ttdeci">void * osMemoryPoolId_t</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:268</div></div>
702 </div><!-- fragment --><p> For the memory pool itself, we need to declare a structure which contains the memory elements we require in each memory pool lot: </p><div class="fragment"><div class="line"><span class="keyword">typedef</span> <span class="keyword">struct </span>{</div>
703 <div class="line">  uint8_t LED0;</div>
704 <div class="line">  uint8_t LED1;</div>
705 <div class="line">  uint8_t LED2;</div>
706 <div class="line">  uint8_t LED3;</div>
707 <div class="line">} memory_block_t;</div>
708 </div><!-- fragment --><p> Then we can create a memory pool in our application code: </p><div class="fragment"><div class="line">mpool = <a class="code hl_function" href="group__CMSIS__RTOS__PoolMgmt.html#ga497ced5d72dc5cd405c4c418516220dc">osMemoryPoolNew</a>(16, <span class="keyword">sizeof</span>(message_t),&amp;memorypoolAttr_mpool);</div>
709 <div class="ttc" id="agroup__CMSIS__RTOS__PoolMgmt_html_ga497ced5d72dc5cd405c4c418516220dc"><div class="ttname"><a href="group__CMSIS__RTOS__PoolMgmt.html#ga497ced5d72dc5cd405c4c418516220dc">osMemoryPoolNew</a></div><div class="ttdeci">osMemoryPoolId_t osMemoryPoolNew(uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr)</div><div class="ttdoc">Create and Initialize a Memory Pool object.</div></div>
710 </div><!-- fragment --><p> Now we can allocate a memory pool slot within a thread: </p><div class="fragment"><div class="line">memory_block_t *led_data;</div>
711 <div class="line">*led_data = (memory_block_t *) <a class="code hl_function" href="group__CMSIS__RTOS__PoolMgmt.html#ga8ead54e99ccb8f112356c88f99d38fbe">osMemoryPoolAlloc</a>(mPool,<a class="code hl_define" href="group__CMSIS__RTOS__Definitions.html#ga9eb9a7a797a42e4b55eb171ecc609ddb">osWaitForever</a>);</div>
712 <div class="ttc" id="agroup__CMSIS__RTOS__PoolMgmt_html_ga8ead54e99ccb8f112356c88f99d38fbe"><div class="ttname"><a href="group__CMSIS__RTOS__PoolMgmt.html#ga8ead54e99ccb8f112356c88f99d38fbe">osMemoryPoolAlloc</a></div><div class="ttdeci">void * osMemoryPoolAlloc(osMemoryPoolId_t mp_id, uint32_t timeout)</div><div class="ttdoc">Allocate a memory block from a Memory Pool.</div></div>
713 </div><!-- fragment --><p> and then populate it with data: </p><div class="fragment"><div class="line">led_data-&gt;LED0 = 0;</div>
714 <div class="line">led_data-&gt;LED1 = 1;</div>
715 <div class="line">led_data-&gt;LED2 = 2;</div>
716 <div class="line">led_data-&gt;LED3 = 3;</div>
717 </div><!-- fragment --><p> It is then possible to place the pointer to the memory block in a message queue: </p><div class="fragment"><div class="line">osMessagePut(Q_LED,(uint32_t)led_data,<a class="code hl_define" href="group__CMSIS__RTOS__Definitions.html#ga9eb9a7a797a42e4b55eb171ecc609ddb">osWaitForever</a>);</div>
718 </div><!-- fragment --><p> The data can now be accessed by another task: </p><div class="fragment"><div class="line">osEvent event;</div>
719 <div class="line">memory_block_t *received;</div>
720 <div class="line"><span class="keyword">event</span> = osMessageGet(Q_LED, osWatiForever);</div>
721 <div class="line">*received = (memory_block *)event.value.p;</div>
722 <div class="line">led_on(received-&gt;LED0);</div>
723 </div><!-- fragment --><p> Once the data in the memory block has been used, the block must be released back to the memory pool for reuse. </p><div class="fragment"><div class="line">osPoolFree(led_pool,received);</div>
724 </div><!-- fragment --><p> To create a zero copy mail box system, we can combine a memory pool to store the data with a message queue which is used to transfer a pointer o the allocated memory pool slot. This way the message data stays static and we pass a pointer between threads.</p>
725 <h3><a class="anchor" id="rtos2_tutorial_ex18"></a>
726 Exercise 18 - Zero Copy Mailbox</h3>
727 <p>Open <a href="https://www2.keil.com/mdk5/packinstaller" target="_blank">Pack Installer</a>:</p><ul>
728 <li>Use the <b>Search</b> box on the <b>Boards</b> tab to look for the <b>CMSIS_RTOS_Tutorial (V2.1)</b> "board".</li>
729 <li>On the <b>Examples</b> tab, copy <b>Ex 18 Zero Copy Mailbox</b> to your PC and start Keil MDK.</li>
730 <li>In the project folder, you will find a file called "Instructions.pdf" that explains the setup and the steps you need to take to successfully finish the exercise.</li>
731 </ul>
732 <h1><a class="anchor" id="rtos2_tutorial_config"></a>
733 Configuration</h1>
734 <p>So far we have looked at the CMSIS-RTOS2 API. This includes thread management functions, time management and inter-thread communication. Now that we have a clear idea of exactly what the RTOS kernel is capable of, we can take a more detailed look at the configuration file.</p>
735 <p>RTX_Config.h is the central configuration file for all of the Cortex-M based microcontrollers. Like the other configuration files, it is a template file which presents all the necessary configurations as a set of menu options (when viewed in Configuration Wizard view).</p>
736 <h2><a class="anchor" id="rtos2_tutorial_config_sys"></a>
737 System Configuration</h2>
738 <p>Before we discuss the settings in the system configuration section, it is worth mentioning what is missing. In earlier versions of CMSIS-RTOS, it was necessary to define the CPU frequency as part of the RTOS configuration. In CMSIS-RTOS2, the CPU frequency is now taken from the "SystemCoreClock" variable which is set as part of the CMSIS-Core system startup code. If you are working with a new microcontroller you will need to check that this value is being set correctly.</p>
739 <p>As we have seen earlier, we can set the amount of memory allocated to the "Global Dynamic Memory Pool". Next, we can define the tick frequency in Hertz. This defines the SysTick interrupt rate and is set to 1 ms by default. Generally, I would leave this frequency at its default setting. However, processor clock speeds are getting ever faster. If you are using a high performance device you may consider using a faster tick rate.</p>
740 <p>"Round Robin Thread" switching is also enabled by default in this section. Again, I would recommend leaving these settings in their default state unless you have a strong requirement to change them. The system configuration settings also allow us to control the range of messages sent to the event recorder as the RTOS runs.</p>
741 <p>Finally, if we are setting thread flags from an interrupt they are held in a queue until they are processed. Depending on your application you may need to increase the size of this queue.</p>
742 <h2><a class="anchor" id="rtos2_tutorial_config_thread"></a>
743 Thread Configuration</h2>
744 <p>In the Thread Configuration section, we define the basic resources which will be required by the CMSIS-RTOS2 threads. For each thread we allocate a "default thread stack space" (by default, this is 200 bytes). As you create threads, this memory will be allocated from the Global Dynamic Mmemory Pool. However, if we enable Object specific memory allocation the RTOS will define a memory region which is dedicated to thread usage only. If you switch to object specific memory allocation, it is necessary to provide details about the number and size of threads memory so the RTOS can calculate the maximum memory requirement.</p>
745 <p>For object specific memory allocation, we must define the maximum number of user threads (don’t count the idle or timer threads) which will be running. We must also define the number of threads which have a default stack size and also the total amount of memory required by threads with custom tack sizes. Once we have defined the memory used by user threads, we can allocate memory to the idle thread. During development, CMSIS-RTOS can trap stack overflows. When this option is enabled, an overflow of a thread stack space will cause the RTOS kernel to call the osRtxErrorNotify() function which is located in the RTX_Config.c file. This function gets an error code and then sits in an infinite loop. The stack checking option is intended for use during debugging and should be disabled on the final application to minimize the kernel overhead. However, it is possible to modify the osRtxErrorNotify() function if enhanced error protection is required in the final release. </p><div class="fragment"><div class="line"><span class="comment">// OS Error Callback function</span></div>
746 <div class="line">__WEAK uint32_t osRtxErrorNotify (uint32_t code, <span class="keywordtype">void</span> *object_id) {</div>
747 <div class="line">  (void)object_id;</div>
748 <div class="line"> </div>
749 <div class="line">  <span class="keywordflow">switch</span> (code) {</div>
750 <div class="line">    <span class="keywordflow">case</span> osRtxErrorStackUnderflow:</div>
751 <div class="line">      <span class="comment">// Stack overflow detected for thread (thread_id=object_id)</span></div>
752 <div class="line">      <span class="keywordflow">break</span>;</div>
753 <div class="line">    <span class="keywordflow">case</span> osRtxErrorISRQueueOverflow:</div>
754 <div class="line">      <span class="comment">// ISR Queue overflow detected when inserting object (object_id)</span></div>
755 <div class="line">      <span class="keywordflow">break</span>;</div>
756 <div class="line">    <span class="keywordflow">case</span> osRtxErrorTimerQueueOverflow:</div>
757 <div class="line">      <span class="comment">// User Timer Callback Queue overflow detected for timer (timer_id=object_id)</span></div>
758 <div class="line">      <span class="keywordflow">break</span>;</div>
759 <div class="line">    <span class="keywordflow">case</span> osRtxErrorClibSpace:</div>
760 <div class="line">      <span class="comment">// Standard C/C++ library libspace not available: increase OS_THREAD_LIBSPACE_NUM</span></div>
761 <div class="line">      <span class="keywordflow">break</span>;</div>
762 <div class="line">    <span class="keywordflow">case</span> osRtxErrorClibMutex:</div>
763 <div class="line">      <span class="comment">// Standard C/C++ library mutex initialization failed</span></div>
764 <div class="line">      <span class="keywordflow">break</span>;</div>
765 <div class="line">    <span class="keywordflow">default</span>:</div>
766 <div class="line">      <span class="comment">// Reserved</span></div>
767 <div class="line">      <span class="keywordflow">break</span>;</div>
768 <div class="line">  }</div>
769 <div class="line">  <span class="keywordflow">for</span> (;;) {}</div>
770 <div class="line"><span class="comment">//return 0U;</span></div>
771 <div class="line">}</div>
772 </div><!-- fragment --><p> It is also possible to monitor the maximum stack memory usage during run time. If you check the "Stack Usage Watermark" option, a pattern (0xCC) is written into each stack space. During runtime, this watermark is used to calculate the maximum memory usage. In Arm Keil MDK, this figure is reported in the threads section of the View - Watch Window - RTX RTOS window.</p>
773 <p>This section also allows us to select whether the threads are running in privileged or unprivileged mode. The last option allows us to define the processor operating mode for the user threads. If you want an easy life, leave this set to "privileged mode" and you will have full access to all the processor features. However, if you are writing a safety critical or secure application then "unprivileged mode" can be used to prevent thread access to critical processor registers limiting run time errors or attempts at intrusion.</p>
774 <h2><a class="anchor" id="rtos2_tutorial_config_sys_timer"></a>
775 System Timer Configuration</h2>
776 <p>The default timer for use with CMSIS-RTOS is the Cortex-M SysTick timer which is present on nearly all Cortex-M processors. The input to the SysTick timer will generally be the CPU clock. It is possible to use a different timer by overloading the kernel timer functions as outlined explained in the <a class="el" href="group__CMSIS__RTOS__TickAPI.html">OS Tick API</a> documentation.</p>
777 <h1><a class="anchor" id="rtos2_tutorial_conclusion"></a>
778 Conclusion</h1>
779 <p>In this tutorial, we have worked our way through the CMSIS-RTOS2 API and introduced some of the key concepts associated with using an RTOS. The only real way to learn how to develop with an RTOS is to actually use one in a real project. </p>
780 </div></div><!-- contents -->
781 </div><!-- PageDoc -->
782 </div><!-- doc-content -->
783 <!-- start footer part -->
784 <div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
785   <ul>
786     <li class="footer">
787       <script type="text/javascript">
788         <!--
789         writeFooter.call(this);
790         //-->
791       </script> 
792     </li>
793   </ul>
794 </div>
795 </body>
796 </html>