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">
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: Theory of Operation</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&dn=expat.txt MIT */
28 $(document).ready(function() { init_search(); });
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>
39 <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
41 <table cellspacing="0" cellpadding="0">
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  <span id="projectnumber"><script type="text/javascript">
49 writeHeader.call(this);
50 writeVersionDropdown.call(this, "CMSIS-RTOS2");
55 <div id="projectbrief">Real-Time Operating System: API and RTX Reference Implementation</div>
57 <td> <div id="MSearchBox" class="MSearchBoxInactive">
59 <span id="MSearchSelect" onmouseover="return searchBox.OnSearchSelectShow()" onmouseout="return searchBox.OnSearchSelectHide()"> </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>
69 <!--END !PROJECT_NAME-->
74 <!-- end header part -->
75 <div id="CMSISnav" class="tabs1">
77 <script type="text/javascript">
78 writeComponentTabs.call(this);
82 <!-- Generated by Doxygen 1.9.6 -->
83 <script type="text/javascript">
84 /* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT */
85 var searchBox = new SearchBox("searchBox", "search/",'.html');
89 <div id="side-nav" class="ui-resizable side-nav-resizable">
91 <div id="nav-tree-contents">
92 <div id="nav-sync" class="sync"></div>
95 <div id="splitbar" style="-moz-user-select:none;"
96 class="ui-resizable-handle">
99 <script type="text/javascript">
100 /* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT */
101 $(document).ready(function(){initNavTree('theory_of_operation.html',''); initResizable(); });
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)">
112 <!-- iframe showing the search results (closed by default) -->
113 <div id="MSearchResultsWindow">
114 <div id="MSearchResults">
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>
126 <div><div class="header">
127 <div class="headertitle"><div class="title">Theory of Operation </div></div>
129 <div class="contents">
130 <div class="toc"><h3>Table of Contents</h3>
131 <ul><li class="level1"><a href="#SystemStartup">System Startup</a></li>
132 <li class="level1"><a href="#Scheduler">Scheduler</a></li>
133 <li class="level1"><a href="#MemoryAllocation">Memory Allocation</a><ul><li class="level2"><a href="#GlobalMemoryPool">Global Memory Pool</a></li>
134 <li class="level2"><a href="#ObjectMemoryPool">Object-specific Memory Pools</a></li>
135 <li class="level2"><a href="#StaticObjectMemory">Static Object Memory</a></li>
138 <li class="level1"><a href="#ThreadStack">Thread Stack Management</a></li>
139 <li class="level1"><a href="#lowPower">Low-Power Operation</a></li>
140 <li class="level1"><a href="#kernelTimer">RTX Kernel Timer Tick</a><ul><li class="level2"><a href="#TickLess">Tick-less Low-Power Operation</a></li>
143 <li class="level1"><a href="#rtx_os_h">RTX5 Header File</a></li>
144 <li class="level1"><a href="#CMSIS_RTOS_TimeOutValue">Timeout Value</a></li>
145 <li class="level1"><a href="#CMSIS_RTOS_ISR_Calls">Calls from Interrupt Service Routines</a></li>
146 <li class="level1"><a href="#CMSIS_RTOS_svcFunctions">SVC Functions</a></li>
147 <li class="level1"><a href="#cre_rtx_proj_clib_arm">Arm C library multi-threading protection</a></li>
150 <div class="textblock"><p>Many aspects of the kernel are configurable and the configuration options are mentioned where applicable.</p>
151 <h1><a class="anchor" id="SystemStartup"></a>
153 <p>Since main is no longer a thread RTX5 does not interfere with the system startup until main is reached. Once the execution reaches <code>main()</code> there is a recommended order to initialize the hardware and start the kernel. This is also reflected in the user code template file "CMSIS-RTOS2 'main' function" supplied with the RTX5 component.</p>
154 <p>Your application's <code>main()</code> should implement at least the following in the given order:</p><ol type="1">
155 <li>Initialization and configuration of hardware including peripherals, memory, pins, clocks and the interrupt system.</li>
156 <li>Update the system core clock using the respective <a href="../../Core/html/group__system__init__gr.html">CMSIS-Core (Cortex-M)</a> or <a href="../../Core_A/html/group__system__init__gr.html">CMSIS-Core (Cortex-A)</a> function.</li>
157 <li>Initialize the CMSIS-RTOS kernel using <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#gae818f6611d25ba3140bede410a52d659">osKernelInitialize</a>.</li>
158 <li>Optionally, create one thread (for example <code>app_main</code>), which is used as a main thread using <a class="el" href="group__CMSIS__RTOS__ThreadMgmt.html#ga48d68b8666d99d28fa646ee1d2182b8f">osThreadNew</a>. This thread should take care of creating and starting objects, once it is run by the scheduler. Alternatively, threads can be created in <code>main()</code> directly.</li>
159 <li>Start the RTOS scheduler using <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#ga9ae2cc00f0d89d7b6a307bba942b5221">osKernelStart</a> which also configures the system tick timer and initializes RTOS specific interrupts. This function does not return in case of successful execution. Therefore, any application code after <b>osKernelStart</b> will not be executed.</li>
161 <dl class="section note"><dt>Note</dt><dd><ul>
162 <li>Modifying priorities and groupings in the NVIC by the application after the above sequence is not recommended.</li>
163 <li>Before executing <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#ga9ae2cc00f0d89d7b6a307bba942b5221">osKernelStart</a>, only the functions <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#ga6f7764e7250c5c5364c00c45a5d1d199">osKernelGetInfo</a>, <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#ga48b69b81012fce051f639be288b243ba">osKernelGetState</a>, and object creation functions (osXxxNew) may be called.</li>
166 <h1><a class="anchor" id="Scheduler"></a>
168 <p>RTX5 implements a low-latency preemptive scheduler. Major parts of RTX5 are executed in handler mode such as</p><ul>
169 <li>SysTick_Handler used for time-based scheduling.</li>
170 <li>SVC_Handler used for lock-based scheduling.</li>
171 <li>PendSV_Handler used for interrupt-based scheduling.</li>
173 <p>In order to be low-latency with respect to ISR execution those system exceptions are configured to use the lowest priority groups available. The priorities are configured such that no preemption happens between them. Thus no interrupt critical sections (i.e. interrupt locks) are needed to protect the scheduler.</p>
175 <img src="scheduling.png" alt=""/>
176 <div class="caption">
177 Thread scheduling and interrupt execution</div></div>
178 <p>The scheduler combines priority and round-robin based context switches. The example depicted in the image above contains four threads (1, 2, 3, and 4). Threads 1 and 2 share the same priority, thread 3 has a higher one and thread 4 the highest (<a class="el" href="group__CMSIS__RTOS__ThreadMgmt.html#a6a5183df4c54c3e28dc8dc704f2487d5">osThreadAttr_t::priority</a>). As long as threads 3 and 4 are blocked the scheduler switches between thread 1 and 2 on a time-slice basis (round-robin). The time-slice for round-robin scheduling can be configured, see Round-Robin Timeout in <a class="el" href="config_rtx5.html#systemConfig">System Configuration</a>.</p>
179 <p>Thread 2 unblocks thread 3 by an arbitrary RTOS-call (executed in <a class="el" href="theory_of_operation.html#CMSIS_RTOS_svcFunctions">SVC</a> handler mode) at time index 2. The scheduler switches to thread 3 immediately because thread 3 has the highest priority. Thread 4 is still blocked.</p>
180 <p>At time index 4 an interrupt (ISR) occurs and preempts the SysTick_Handler. RTX does not add any latency to the interrupt service execution. The ISR routine uses an RTOS-call that unblocks thread 4. Instead of switching to thread 4 immediately the PendSV flag is set to defer the context switching. The PendSV_Handler is executed right after the SysTick_Handler returns and the deferred context switch to thread 4 is carried out. As soon as highest priority thread 4 blocks again by using a blocking RTOS-call execution is switched back to thread 3 immediately during time index 5.</p>
181 <p>At time index 5 thread 3 uses a blocking RTOS-call as well. Thus the scheduler switches back to thread 2 for time index 6. At time index 7 the scheduler uses the round-robin mechanism to switch to thread 1 and so on.</p>
182 <h1><a class="anchor" id="MemoryAllocation"></a>
183 Memory Allocation</h1>
184 <p>RTX5 objects (thread, mutex, semaphore, timer, message queue, thread and event flags, as well as memory pool) require dedicated RAM memory. Objects can be created using os<em>Object</em>New() calls and deleted using os<em>Object</em>Delete() calls. The related object memory needs to be available during the lifetime of the object.</p>
185 <p>RTX5 offers three different memory allocation methods for objects:</p><ul>
186 <li><a class="el" href="theory_of_operation.html#GlobalMemoryPool">Global Memory Pool</a> uses a single global memory pool for all objects. It is easy to configure, but may have the disadvantage for memory fragmentation when objects with different sizes are created and destroyed.</li>
187 <li><a class="el" href="theory_of_operation.html#ObjectMemoryPool">Object-specific Memory Pools</a> uses a fixed-size memory pool for each object type. The method is time deterministic and avoids memory fragmentation.</li>
188 <li><a class="el" href="theory_of_operation.html#StaticObjectMemory">Static Object Memory</a> reserves memory during compile time and completely avoids that a system can be out of memory. This is typically a required for some safety critical systems.</li>
190 <p>It possible to intermix all the memory allocation methods in the same application.</p>
191 <h2><a class="anchor" id="GlobalMemoryPool"></a>
192 Global Memory Pool</h2>
193 <p>The global memory pool allocates all objects from a memory area. This method of memory allocation is the default configuration setting of RTX5.</p>
195 <img src="MemAllocGlob.png" alt=""/>
196 <div class="caption">
197 Global Memory Pool for all objects</div></div>
198 <p>When the memory pool does not provide sufficient memory, the creation of the object fails and the related os<em>Object</em>New() function returns <span class="XML-Token">NULL</span>.</p>
199 <p>Enabled in <a class="el" href="config_rtx5.html#systemConfig">System Configuration</a>.</p>
200 <h2><a class="anchor" id="ObjectMemoryPool"></a>
201 Object-specific Memory Pools</h2>
202 <p>Object-specific memory pools avoids memory fragmentation with a dedicated fixed-size memory management for each object type. This type of memory pools are fully time deterministic, which means that object creation and destruction takes always the same fixed amount of time. As a fixed-size memory pool is specific to an object type, the handling of out-of-memory situations is simplified.</p>
204 <img src="MemAllocSpec.png" alt=""/>
205 <div class="caption">
206 One memory pool per object type</div></div>
207 <p>Object-specific memory pools are selectively enabled for each object type, e.g: mutex or thread using the RTX configuration file:</p><ul>
208 <li>Enabled in <a class="el" href="config_rtx5.html#threadConfig">Thread Configuration</a> for thread objects.</li>
209 <li>Enabled in <a class="el" href="config_rtx5.html#timerConfig">Timer Configuration</a> for timer objects.</li>
210 <li>Enabled in <a class="el" href="config_rtx5.html#eventFlagsConfig">Event Flags Configuration</a> for event objects.</li>
211 <li>Enabled in <a class="el" href="config_rtx5.html#mutexConfig">Mutex Configuration</a> for mutex objects.</li>
212 <li>Enabled in <a class="el" href="config_rtx5.html#semaphoreConfig">Semaphore Configuration</a> for semaphore.</li>
213 <li>Enabled in <a class="el" href="config_rtx5.html#memPoolConfig">Memory Pool Configuration</a> for memory pools.</li>
214 <li>Enabled in <a class="el" href="config_rtx5.html#msgQueueConfig">Message Queue Configuration</a> for message objects.</li>
216 <p>When the memory pool does not provide sufficient memory, the creation of the object fails and the related os<em>Object</em>New() function returns <span class="XML-Token">NULL</span>.</p>
217 <h2><a class="anchor" id="StaticObjectMemory"></a>
218 Static Object Memory</h2>
219 <p>In contrast to the dynamic memory allocations, the static memory allocation requires compile-time allocation of object memory.</p>
221 <img src="MemAllocStat.png" alt=""/>
222 <div class="caption">
223 Statically allocated memory for all objects</div></div>
224 <p>Static memory allocation can be achieved by providing user-defined memory using attributes at object creation, see <a class="el" href="group__CMSIS__RTOS__MemoryMgmt.html#CMSIS_RTOS_MemoryMgmt_Manual">Manual User-defined Allocation</a>. Please take special note of the following restrictions:</p>
225 <table class="markdownTable">
226 <tr class="markdownTableHead">
227 <th class="markdownTableHeadNone">Memory type </th><th class="markdownTableHeadNone">Requirements </th></tr>
228 <tr class="markdownTableRowOdd">
229 <td class="markdownTableBodyNone">Control Block (osXxxAttr_t::cb_mem) </td><td class="markdownTableBodyNone">4-Byte alignment. Size defined by osRtxThreadCbSize, osRtxTimerCbSize, osRtxEventFlagsCbSize, osRtxMutexCbSize, osRtxSemaphoreCbSize, osRtxMemoryPoolCbSize, osRtxMessageQueueCbSize. </td></tr>
230 <tr class="markdownTableRowEven">
231 <td class="markdownTableBodyNone">Thread Stack (<a class="el" href="group__CMSIS__RTOS__ThreadMgmt.html#ad7c9b42355a4c8b9467130ab3fb19e43" title="memory for stack">osThreadAttr_t::stack_mem</a>) </td><td class="markdownTableBodyNone">8-Byte alignment. Size is application specific, i.e. amount of stack variables and frames. </td></tr>
232 <tr class="markdownTableRowOdd">
233 <td class="markdownTableBodyNone">Memory Pool (<a class="el" href="group__CMSIS__RTOS__PoolMgmt.html#a5799465cca9c71c5587ceb0986f5b06a" title="memory for data storage">osMemoryPoolAttr_t::mp_mem</a>) </td><td class="markdownTableBodyNone">4-Byte alignment. Size calculated with osRtxMemoryPoolMemSize. </td></tr>
234 <tr class="markdownTableRowEven">
235 <td class="markdownTableBodyNone">Message Queue (<a class="el" href="group__CMSIS__RTOS__Message.html#a4e208dc0fb049b42c4b90cbd2791c5ad" title="memory for data storage">osMessageQueueAttr_t::mq_mem</a>) </td><td class="markdownTableBodyNone">4-Byte alignment. Size calculated with osRtxMessageQueueMemSize. </td></tr>
237 <p>In order to allow RTX5 aware debugging, i.e. Component Viewer, to recognize control blocks these needs to be placed in individual memory sections, i.e. using <code>__attribute__((section(...)))</code>.</p>
238 <table class="markdownTable">
239 <tr class="markdownTableHead">
240 <th class="markdownTableHeadNone">RTX Object </th><th class="markdownTableHeadNone">Linker Section </th></tr>
241 <tr class="markdownTableRowOdd">
242 <td class="markdownTableBodyNone">Thread </td><td class="markdownTableBodyNone"><code>.bss.os.thread.cb</code> </td></tr>
243 <tr class="markdownTableRowEven">
244 <td class="markdownTableBodyNone">Timer </td><td class="markdownTableBodyNone"><code>.bss.os.timer.cb</code> </td></tr>
245 <tr class="markdownTableRowOdd">
246 <td class="markdownTableBodyNone">Event Flags </td><td class="markdownTableBodyNone"><code>.bss.os.evflags.cb</code> </td></tr>
247 <tr class="markdownTableRowEven">
248 <td class="markdownTableBodyNone">Mutex </td><td class="markdownTableBodyNone"><code>.bss.os.mutex.cb</code> </td></tr>
249 <tr class="markdownTableRowOdd">
250 <td class="markdownTableBodyNone">Semaphore </td><td class="markdownTableBodyNone"><code>.bss.os.semaphore.cb</code> </td></tr>
251 <tr class="markdownTableRowEven">
252 <td class="markdownTableBodyNone">Memory Pool </td><td class="markdownTableBodyNone"><code>.bss.os.mempool.cb</code> </td></tr>
253 <tr class="markdownTableRowOdd">
254 <td class="markdownTableBodyNone">Message Queue </td><td class="markdownTableBodyNone"><code>.bss.os.msgqueue.cb</code> </td></tr>
256 <p>It must be assured that these sections are placed into contiguous memory. This can fail, i.e. sections end up being split over multiple memory segments, when assigning compilation units to memory segments, manually.</p>
257 <p>The following code example shows how to create an OS object using static memory.</p>
258 <p><b> Code Example:</b> </p><div class="fragment"><div class="line"><span class="comment">/*----------------------------------------------------------------------------</span></div>
259 <div class="line"><span class="comment"> * CMSIS-RTOS 'main' function template</span></div>
260 <div class="line"><span class="comment"> *---------------------------------------------------------------------------*/</span></div>
261 <div class="line"> </div>
262 <div class="line"><span class="preprocessor">#include "RTE_Components.h"</span></div>
263 <div class="line"><span class="preprocessor">#include CMSIS_device_header</span></div>
264 <div class="line"><span class="preprocessor">#include "<a class="code" href="cmsis__os2_8h.html">cmsis_os2.h</a>"</span></div>
265 <div class="line"> </div>
266 <div class="line"><span class="comment">//include rtx_os.h for types of RTX objects</span></div>
267 <div class="line"><span class="preprocessor">#include "rtx_os.h"</span></div>
268 <div class="line"> </div>
269 <div class="line"><span class="comment">//The thread function instanced in this example</span></div>
270 <div class="line"><span class="keywordtype">void</span> worker(<span class="keywordtype">void</span> *arg)</div>
271 <div class="line">{</div>
272 <div class="line"> <span class="keywordflow">while</span>(1) </div>
273 <div class="line"> {</div>
274 <div class="line"> <span class="comment">//work</span></div>
275 <div class="line"> <a class="code hl_function" href="group__CMSIS__RTOS__Wait.html#gaf6055a51390ef65b6b6edc28bf47322e">osDelay</a>(10000);</div>
276 <div class="line"> } </div>
277 <div class="line">}</div>
278 <div class="line"> </div>
279 <div class="line"><span class="comment">// Define objects that are statically allocated for worker thread 1</span></div>
280 <div class="line">__attribute__((section(<span class="stringliteral">".bss.os.thread.cb"</span>)))</div>
281 <div class="line">osRtxThread_t worker_thread_tcb_1;</div>
282 <div class="line"> </div>
283 <div class="line"><span class="comment">// Reserve two areas for the stacks of worker thread 1</span></div>
284 <div class="line"><span class="comment">// uint64_t makes sure the memory alignment is 8</span></div>
285 <div class="line">uint64_t worker_thread_stk_1[64];</div>
286 <div class="line"> </div>
287 <div class="line"><span class="comment">// Define the attributes which are used for thread creation</span></div>
288 <div class="line"><span class="comment">// Optional const saves RAM memory and includes the values in periodic ROM tests </span></div>
289 <div class="line">const <a class="code hl_struct" href="group__CMSIS__RTOS__ThreadMgmt.html#structosThreadAttr__t">osThreadAttr_t</a> worker_attr_1 = {</div>
290 <div class="line"> <span class="stringliteral">"wrk1"</span>,</div>
291 <div class="line"> <a class="code hl_define" href="group__CMSIS__RTOS__ThreadMgmt.html#ga249499c519f3f8eef5673009ab6cfcbe">osThreadJoinable</a>,</div>
292 <div class="line"> &worker_thread_tcb_1,</div>
293 <div class="line"> <span class="keyword">sizeof</span>(worker_thread_tcb_1),</div>
294 <div class="line"> &worker_thread_stk_1[0],</div>
295 <div class="line"> <span class="keyword">sizeof</span>(worker_thread_stk_1),</div>
296 <div class="line"> <a class="code hl_enumvalue" href="cmsis__os2_8h.html#gad4e3e0971b41f2d17584a8c6837342eca17b36cd9cd38652c2bc6d4803990674b">osPriorityAboveNormal</a>,</div>
297 <div class="line"> 0</div>
298 <div class="line">};</div>
299 <div class="line"> </div>
300 <div class="line"><span class="comment">// Define ID object for thread</span></div>
301 <div class="line"><a class="code hl_typedef" href="group__CMSIS__RTOS__ThreadMgmt.html#gaa6c32fe2a3e0a2e01f212d55b02e51c7">osThreadId_t</a> th1;</div>
302 <div class="line"> </div>
303 <div class="line"><span class="comment">/*----------------------------------------------------------------------------</span></div>
304 <div class="line"><span class="comment"> * Application main thread</span></div>
305 <div class="line"><span class="comment"> *---------------------------------------------------------------------------*/</span></div>
306 <div class="line"><span class="keywordtype">void</span> app_main (<span class="keywordtype">void</span> *argument) {</div>
307 <div class="line"> uint32_t param = NULL;</div>
308 <div class="line"> </div>
309 <div class="line"> <span class="comment">// Create an instance of the worker thread with static resources (TCB and stack)</span></div>
310 <div class="line"> th1 = <a class="code hl_function" href="group__CMSIS__RTOS__ThreadMgmt.html#ga48d68b8666d99d28fa646ee1d2182b8f">osThreadNew</a>(worker, &param, &worker_attr_1);</div>
311 <div class="line"> </div>
312 <div class="line"> <span class="keywordflow">for</span> (;;) {}</div>
313 <div class="line">}</div>
314 <div class="line"> </div>
315 <div class="line"><span class="keywordtype">int</span> main (<span class="keywordtype">void</span>) {</div>
316 <div class="line"> <span class="comment">// System Initialization</span></div>
317 <div class="line"> SystemCoreClockUpdate();</div>
318 <div class="line"> <span class="comment">// ...</span></div>
319 <div class="line"> </div>
320 <div class="line"> <a class="code hl_function" href="group__CMSIS__RTOS__KernelCtrl.html#gae818f6611d25ba3140bede410a52d659">osKernelInitialize</a>(); <span class="comment">// Initialize CMSIS-RTOS</span></div>
321 <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 application main thread</span></div>
322 <div class="line"> <a class="code hl_function" href="group__CMSIS__RTOS__KernelCtrl.html#ga9ae2cc00f0d89d7b6a307bba942b5221">osKernelStart</a>(); <span class="comment">// Start thread execution</span></div>
323 <div class="line"> <span class="keywordflow">for</span> (;;) {}</div>
324 <div class="line">}</div>
325 <div class="ttc" id="acmsis__os2_8h_html"><div class="ttname"><a href="cmsis__os2_8h.html">cmsis_os2.h</a></div></div>
326 <div class="ttc" id="acmsis__os2_8h_html_gad4e3e0971b41f2d17584a8c6837342eca17b36cd9cd38652c2bc6d4803990674b"><div class="ttname"><a href="cmsis__os2_8h.html#gad4e3e0971b41f2d17584a8c6837342eca17b36cd9cd38652c2bc6d4803990674b">osPriorityAboveNormal</a></div><div class="ttdeci">@ osPriorityAboveNormal</div><div class="ttdoc">Priority: above normal.</div><div class="ttdef"><b>Definition:</b> cmsis_os2.h:147</div></div>
327 <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>
328 <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>
329 <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>
330 <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>
331 <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>
332 <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>
333 <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>
334 </div><!-- fragment --><h1><a class="anchor" id="ThreadStack"></a>
335 Thread Stack Management</h1>
336 <p>For Cortex-M processors without floating point unit the thread context requires 64 bytes on the local stack.</p>
337 <dl class="section note"><dt>Note</dt><dd>For Cortex-M4/M7 with FP the thread context requires 200 bytes on the local stack. For these devices the default stack space should be increased to a minimum of 300 bytes.</dd></dl>
338 <p>Each thread is provided with a separate stack that holds the thread context and stack space for automatic variables and return addresses for function call nesting. The stack sizes of RTX threads are flexibly configurable as explained in the section <a class="el" href="config_rtx5.html#threadConfig">Thread Configuration</a>. RTX offers a configurable checking for stack overflows and stack utilization.</p>
339 <h1><a class="anchor" id="lowPower"></a>
340 Low-Power Operation</h1>
341 <p>The system thread <b>osRtxIdleThread</b> can be use to switch the system into a low-power mode. The easiest form to enter a low-power mode is the execution of the <code>__WFE</code> function that puts the processor into a sleep mode where it waits for an event.</p>
342 <p><b>Code Example:</b> </p><div class="fragment"><div class="line"><span class="preprocessor">#include "RTE_Components.h"</span></div>
343 <div class="line"><span class="preprocessor">#include CMSIS_device_header </span><span class="comment">/* Device definitions */</span><span class="preprocessor"></span></div>
344 <div class="line"> </div>
345 <div class="line"><span class="keywordtype">void</span> osRtxIdleThread (<span class="keywordtype">void</span>) {</div>
346 <div class="line"> <span class="comment">/* The idle demon is a system thread, running when no other thread is */</span></div>
347 <div class="line"> <span class="comment">/* ready to run. */</span></div>
348 <div class="line"> </div>
349 <div class="line"> <span class="keywordflow">for</span> (;;) {</div>
350 <div class="line"> __WFE(); <span class="comment">/* Enter sleep mode */</span></div>
351 <div class="line"> }</div>
352 <div class="line">}</div>
353 </div><!-- fragment --><dl class="section note"><dt>Note</dt><dd><code>__WFE()</code> is not available in every Cortex-M implementation. Check device manuals for availability.</dd></dl>
354 <h1><a class="anchor" id="kernelTimer"></a>
355 RTX Kernel Timer Tick</h1>
356 <p>RTX uses the generic <a class="el" href="group__CMSIS__RTOS__TickAPI.html">OS Tick API</a> to configure and control its periodic Kernel Tick.</p>
357 <p>To use an alternative timer as the Kernel Tick Timer one simply needs to implement a custom version of the <a class="el" href="group__CMSIS__RTOS__TickAPI.html">OS Tick API</a>.</p>
358 <dl class="section note"><dt>Note</dt><dd>The OS Tick implementation provided must assure that the used timer interrupt uses the same (low) priority group as the service interrupts, i.e. interrupts used by RTX must not preempt each other. Refer to the <a class="el" href="theory_of_operation.html#Scheduler">Scheduler</a> section for more details.</dd></dl>
359 <h2><a class="anchor" id="TickLess"></a>
360 Tick-less Low-Power Operation</h2>
361 <p>RTX5 provides extension for tick-less operation which is useful for applications that use extensively low-power modes where the SysTick timer is also disabled. To provide a time-tick in such power-saving modes, a wake-up timer is used to derive timer intervals. The CMSIS-RTOS2 functions <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#gae26683e1606ec633354a2876c68f0c1f">osKernelSuspend</a> and <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#ga8c4b4d7ed34cab73c001665d9176aced">osKernelResume</a> control the tick-less operation.</p>
362 <p>Using this functions allows the RTX5 thread scheduler to stop the periodic kernel tick interrupt. When all active threads are suspended, the system enters power-down and calculates how long it can stay in this power-down mode. In the power-down mode the processor and peripherals can be switched off. Only a wake-up timer must remain powered, because this timer is responsible to wake-up the system after the power-down period expires.</p>
363 <p>The tick-less operation is controlled from the <b>osRtxIdleThread</b> thread. The wake-up timeout value is set before the system enters the power-down mode. The function <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#gae26683e1606ec633354a2876c68f0c1f">osKernelSuspend</a> calculates the wake-up timeout measured in RTX Timer Ticks; this value is used to setup the wake-up timer that runs during the power-down mode of the system.</p>
364 <p>Once the system resumes operation (either by a wake-up time out or other interrupts) the RTX5 thread scheduler is started with the function <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#ga8c4b4d7ed34cab73c001665d9176aced">osKernelResume</a>. The parameter <em>sleep_time</em> specifies the time (in RTX Timer Ticks) that the system was in power-down mode.</p>
365 <p><b>Code Example:</b> </p><div class="fragment"><div class="line"><span class="preprocessor">#include "msp.h"</span> <span class="comment">// Device header</span></div>
366 <div class="line"> </div>
367 <div class="line"><span class="comment">/*----------------------------------------------------------------------------</span></div>
368 <div class="line"><span class="comment"> * MSP432 Low-Power Extension Functions</span></div>
369 <div class="line"><span class="comment"> *---------------------------------------------------------------------------*/</span></div>
370 <div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> MSP432_LP_Entry(<span class="keywordtype">void</span>) {</div>
371 <div class="line"> <span class="comment">/* Enable PCM rude mode, which allows to device to enter LPM3 without waiting for peripherals */</span></div>
372 <div class="line"> PCM->CTL1 = PCM_CTL1_KEY_VAL | PCM_CTL1_FORCE_LPM_ENTRY; </div>
373 <div class="line"> <span class="comment">/* Enable all SRAM bank retentions prior to going to LPM3 */</span></div>
374 <div class="line"> SYSCTL->SRAM_BANKRET |= SYSCTL_SRAM_BANKRET_BNK7_RET;</div>
375 <div class="line"> __enable_interrupt();</div>
376 <div class="line"> NVIC_EnableIRQ(RTC_C_IRQn);</div>
377 <div class="line"> <span class="comment">/* Do not wake up on exit from ISR */</span></div>
378 <div class="line"> SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk;</div>
379 <div class="line"> <span class="comment">/* Setting the sleep deep bit */</span></div>
380 <div class="line"> SCB->SCR |= (SCB_SCR_SLEEPDEEP_Msk); </div>
381 <div class="line">}</div>
382 <div class="line"> </div>
383 <div class="line"><span class="keyword">static</span> <span class="keyword">volatile</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> tc;</div>
384 <div class="line"><span class="keyword">static</span> <span class="keyword">volatile</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> tc_wakeup;</div>
385 <div class="line"> </div>
386 <div class="line"><span class="keywordtype">void</span> RTC_C_IRQHandler(<span class="keywordtype">void</span>)</div>
387 <div class="line">{</div>
388 <div class="line"> <span class="keywordflow">if</span> (tc++ > tc_wakeup) </div>
389 <div class="line"> {</div>
390 <div class="line"> SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk; </div>
391 <div class="line"> NVIC_DisableIRQ(RTC_C_IRQn);</div>
392 <div class="line"> NVIC_ClearPendingIRQ(RTC_C_IRQn);</div>
393 <div class="line"> <span class="keywordflow">return</span>;</div>
394 <div class="line"> }</div>
395 <div class="line"> <span class="keywordflow">if</span> (RTC_C->PS0CTL & RTC_C_PS0CTL_RT0PSIFG)</div>
396 <div class="line"> {</div>
397 <div class="line"> RTC_C->CTL0 = RTC_C_KEY_VAL; <span class="comment">// Unlock RTC key protected registers</span></div>
398 <div class="line"> RTC_C->PS0CTL &= ~RTC_C_PS0CTL_RT0PSIFG;</div>
399 <div class="line"> RTC_C->CTL0 = 0;</div>
400 <div class="line"> SCB->SCR |= (SCB_SCR_SLEEPDEEP_Msk);</div>
401 <div class="line"> }</div>
402 <div class="line">}</div>
403 <div class="line"> </div>
404 <div class="line">uint32_t g_enable_sleep = 0;</div>
405 <div class="line"> </div>
406 <div class="line"><span class="keywordtype">void</span> osRtxIdleThread (<span class="keywordtype">void</span>) {</div>
407 <div class="line"> </div>
408 <div class="line"> <span class="keywordflow">for</span> (;;) {</div>
409 <div class="line"> tc_wakeup = <a class="code hl_function" href="group__CMSIS__RTOS__KernelCtrl.html#gae26683e1606ec633354a2876c68f0c1f">osKernelSuspend</a>();</div>
410 <div class="line"> <span class="comment">/* Is there some time to sleep? */</span></div>
411 <div class="line"> <span class="keywordflow">if</span> (tc_wakeup > 0) {</div>
412 <div class="line"> tc = 0;</div>
413 <div class="line"> <span class="comment">/* Enter the low power state */</span></div>
414 <div class="line"> MSP432_LP_Entry();</div>
415 <div class="line"> __WFE();</div>
416 <div class="line"> }</div>
417 <div class="line"> <span class="comment">/* Adjust the kernel ticks with the amount of ticks slept */</span></div>
418 <div class="line"> <a class="code hl_function" href="group__CMSIS__RTOS__KernelCtrl.html#ga8c4b4d7ed34cab73c001665d9176aced">osKernelResume</a> (tc);</div>
419 <div class="line"> }</div>
420 <div class="line">}</div>
421 <div class="ttc" id="agroup__CMSIS__RTOS__KernelCtrl_html_ga8c4b4d7ed34cab73c001665d9176aced"><div class="ttname"><a href="group__CMSIS__RTOS__KernelCtrl.html#ga8c4b4d7ed34cab73c001665d9176aced">osKernelResume</a></div><div class="ttdeci">void osKernelResume(uint32_t sleep_ticks)</div><div class="ttdoc">Resume the RTOS Kernel scheduler.</div></div>
422 <div class="ttc" id="agroup__CMSIS__RTOS__KernelCtrl_html_gae26683e1606ec633354a2876c68f0c1f"><div class="ttname"><a href="group__CMSIS__RTOS__KernelCtrl.html#gae26683e1606ec633354a2876c68f0c1f">osKernelSuspend</a></div><div class="ttdeci">uint32_t osKernelSuspend(void)</div><div class="ttdoc">Suspend the RTOS Kernel scheduler.</div></div>
423 </div><!-- fragment --><dl class="section note"><dt>Note</dt><dd><code>__WFE()</code> is not available in every Arm Cortex-M implementation. Check device manuals for availability. The alternative using <code>__WFI()</code> has other issues, please take note of <a href="https://www.keil.com/support/docs/3591.htm">https://www.keil.com/support/docs/3591.htm</a> as well.</dd></dl>
424 <h1><a class="anchor" id="rtx_os_h"></a>
425 RTX5 Header File</h1>
426 <p>Every implementation of the CMSIS-RTOS2 API can bring its own additional features. RTX5 adds a couple of functions for the idle more, for error notifications, and special system timer functions. It also is using macros for control block and memory sizes.</p>
427 <p>If you require some of the RTX specific functions in your application code, #include the header file <b>rtx_os.h</b>:</p>
428 <div class="fragment"></div><!-- fragment --><h1><a class="anchor" id="CMSIS_RTOS_TimeOutValue"></a>
430 <p>Timeout values are an argument to several <b>osXxx</b> functions to allow time for resolving a request. A timeout value of <b>0</b> means that the RTOS does not wait and the function returns instantly, even when no resource is available. A timeout value of <a class="el" href="group__CMSIS__RTOS__Definitions.html#ga9eb9a7a797a42e4b55eb171ecc609ddb">osWaitForever</a> means that the RTOS waits infinitely until a resource becomes available. Or one forces the thread to resume using <a class="el" href="group__CMSIS__RTOS__ThreadMgmt.html#ga3dbad90eff394b02de76a452c84c5d80">osThreadResume</a> which is discouraged.</p>
431 <p>The timeout value specifies the number of timer ticks until the time delay elapses. The value is an upper bound and depends on the actual time elapsed since the last timer tick.</p>
433 <li>timeout value <b>0</b> : the system does not wait, even when no resource is available the RTOS function returns instantly.</li>
434 <li>timeout value <b>1</b> : the system waits until the next timer tick occurs; depending on the previous timer tick, it may be a very short wait time.</li>
435 <li>timeout value <b>2</b> : actual wait time is between 1 and 2 timer ticks.</li>
436 <li>timeout value <a class="el" href="group__CMSIS__RTOS__Definitions.html#ga9eb9a7a797a42e4b55eb171ecc609ddb">osWaitForever</a> : system waits infinite until a resource becomes available.</li>
439 <img src="TimerValues.png" alt=""/>
440 <div class="caption">
441 Example of timeout using osDelay()</div></div>
442 <h1><a class="anchor" id="CMSIS_RTOS_ISR_Calls"></a>
443 Calls from Interrupt Service Routines</h1>
444 <p>The following CMSIS-RTOS2 functions can be called from threads and Interrupt Service Routines (ISR):</p><ul>
445 <li><a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#ga6f7764e7250c5c5364c00c45a5d1d199">osKernelGetInfo</a>, <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#ga48b69b81012fce051f639be288b243ba">osKernelGetState</a>, <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#ga84bcdbf2fb76b10c8df4e439f0c7e11b">osKernelGetTickCount</a>, <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#ga7a8d7bd927eaaa58999f91d7d6310cee">osKernelGetTickFreq</a>, <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#gae0fcaff6cecfb4013bb556c87afcd7d2">osKernelGetSysTimerCount</a>, <a class="el" href="group__CMSIS__RTOS__KernelCtrl.html#ga4d69215a93220f72be3684cad582f16a">osKernelGetSysTimerFreq</a></li>
446 <li><a class="el" href="group__CMSIS__RTOS__ThreadMgmt.html#gac3230f3a55a297514b013ebf38f27e0a">osThreadGetName</a>, <a class="el" href="group__CMSIS__RTOS__ThreadMgmt.html#ga8df03548e89fbc56402a5cd584a505da">osThreadGetId</a>, <a class="el" href="group__CMSIS__RTOS__ThreadFlagsMgmt.html#ga6f89ef9caded1d9963c7b12b0f6412c9">osThreadFlagsSet</a></li>
447 <li><a class="el" href="group__CMSIS__RTOS__TimerMgmt.html#ga4f82a98eee4d9ea79507e44340d3d319">osTimerGetName</a></li>
448 <li><a class="el" href="group__CMSIS__RTOS__EventFlags.html#ga59f4ddf0ee8c395b1672bb978d1cfc88">osEventFlagsGetName</a>, <a class="el" href="group__CMSIS__RTOS__EventFlags.html#ga33b71d14cecf90b4e72639dd19f23a5e">osEventFlagsSet</a>, <a class="el" href="group__CMSIS__RTOS__EventFlags.html#ga93bf258ca0007c6641fbe8e4f2b8a1e5">osEventFlagsClear</a>, <a class="el" href="group__CMSIS__RTOS__EventFlags.html#ga8bda3185f46bfd278cea8a6cf357677d">osEventFlagsGet</a>, <a class="el" href="group__CMSIS__RTOS__EventFlags.html#ga52acb34a8322e58020227344fe662b4e">osEventFlagsWait</a></li>
449 <li><a class="el" href="group__CMSIS__RTOS__MutexMgmt.html#ga00b5e58cd247a412d1afd18732d8b752">osMutexGetName</a></li>
450 <li><a class="el" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga9586952051f00285f1482dbe6695bbc4">osSemaphoreGetName</a>, <a class="el" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga7e94c8b242a0c81f2cc79ec22895c87b">osSemaphoreAcquire</a>, <a class="el" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga0abcee1b5449d7a6928fb9248c690bb6">osSemaphoreRelease</a>, <a class="el" href="group__CMSIS__RTOS__SemaphoreMgmt.html#ga7559d4dff3cda9992fc5ab5de3e74c70">osSemaphoreGetCount</a></li>
451 <li><a class="el" href="group__CMSIS__RTOS__PoolMgmt.html#gab414a1e138205a55820acfa277c8f386">osMemoryPoolGetName</a>, <a class="el" href="group__CMSIS__RTOS__PoolMgmt.html#ga8ead54e99ccb8f112356c88f99d38fbe">osMemoryPoolAlloc</a>, <a class="el" href="group__CMSIS__RTOS__PoolMgmt.html#gabb4f4560daa6d1f8c8789082ee186d16">osMemoryPoolFree</a>, <a class="el" href="group__CMSIS__RTOS__PoolMgmt.html#gad696e94bfbe28f0b6613f9303fdf6a37">osMemoryPoolGetCapacity</a>, <a class="el" href="group__CMSIS__RTOS__PoolMgmt.html#gab2bf059b7fa7679c3cccdaeec60b6c0e">osMemoryPoolGetBlockSize</a>, <a class="el" href="group__CMSIS__RTOS__PoolMgmt.html#ga958a9449bff8c95ce213de98eef5739d">osMemoryPoolGetCount</a>, <a class="el" href="group__CMSIS__RTOS__PoolMgmt.html#ga0394cffa9479a7994e3b03c79c1cb909">osMemoryPoolGetSpace</a></li>
452 <li><a class="el" href="group__CMSIS__RTOS__Message.html#gae7cf7bf2b97a5ae481fb60fcce99247a">osMessageQueueGetName</a>, <a class="el" href="group__CMSIS__RTOS__Message.html#gaa515fc8b956f721a8f72b2c505813bfc">osMessageQueuePut</a>, <a class="el" href="group__CMSIS__RTOS__Message.html#gad90d4959466a7a65105061da8256ab9e">osMessageQueueGet</a>, <a class="el" href="group__CMSIS__RTOS__Message.html#gac24f87d4f395e9e9c900c320e45ade8a">osMessageQueueGetCapacity</a>, <a class="el" href="group__CMSIS__RTOS__Message.html#ga96d3d84069b20359de48109e28a1a89e">osMessageQueueGetMsgSize</a>, <a class="el" href="group__CMSIS__RTOS__Message.html#ga6a32ac394fcff568b251c160cc3014b2">osMessageQueueGetCount</a>, <a class="el" href="group__CMSIS__RTOS__Message.html#gaddf0904427436dd3880d46263c2dc9fa">osMessageQueueGetSpace</a></li>
454 <p>Functions that cannot be called from an ISR are verifying the interrupt status and return the status code <b>osErrorISR</b>, in case they are called from an ISR context. In some implementations, this condition might be caught using the HARD_FAULT vector.</p>
455 <dl class="section note"><dt>Note</dt><dd><ul>
456 <li>RTX does not disable interrupts during critical sections for Armv7-M and Armv8-M architecture based devices, but rather uses atomic operations.</li>
457 <li>Therefore, there is no need to configure interrupt priorities of interrupt service routines that use RTOS functions.</li>
460 <h1><a class="anchor" id="CMSIS_RTOS_svcFunctions"></a>
462 <p>Supervisor Calls (SVC) are exceptions targeted at software and operating systems for generating system function calls. They are sometimes called software interrupts. For example, instead of allowing user programs to directly access hardware, an operating system may provide access to hardware through an SVC. So when a user program wants to use certain hardware, it generates the exception using SVC instructions. The software exception handler in the operating system executes and provides the requested service to the user application. In this way, access to hardware is under the control of the OS, which can provide a more robust system by preventing the user applications from directly accessing the hardware.</p>
463 <p>SVCs can also make software more portable because the user application does not need to know the programming details of the underlying hardware. The user program will only need to know the application programming interface (API) function ID and parameters; the actual hardware-level programming is handled by device drivers.</p>
464 <p>SVCs run in <b>privileged</b> <b>handler</b> mode of the Arm Cortex-M core. SVC functions accept arguments and can return values. The functions are used in the same way as other functions; however, they are executed indirectly through the SVC instruction. When executing SVC instructions, the controller changes to the privileged handler mode.</p>
465 <p>Interrupts are <b>not</b> <b>disabled</b> in this mode. To protect SVC functions from interrupts, you need to include the disable/enable intrinsic functions <code>__disable_irq()</code> and <code>__enable_irq()</code> in your code.</p>
466 <p>You can use SVC functions to access <b>protected</b> <b>peripherals</b>, for example, to configure NVIC and interrupts. This is required if you run threads in unprivileged (protected) mode and you need to change interrupts from the within the thread.</p>
467 <p>To implement SVC functions in your Keil RTX5 project, you need to:</p><ol type="1">
468 <li>Add the SVC User Table file <b>svc_user.c</b> to your project folder and include it into your project. This file is available as a user code template.</li>
469 <li>Write a function implementation. Example: <div class="fragment"><div class="line">uint32_t svc_atomic_inc32 (uint32_t *mem) {</div>
470 <div class="line"> <span class="comment">// A protected function to increment a counter. </span></div>
471 <div class="line"> uint32_t val;</div>
472 <div class="line"> </div>
473 <div class="line"> __disable_irq();</div>
474 <div class="line"> val = *mem;</div>
475 <div class="line"> (*mem) = val + 1U;</div>
476 <div class="line"> __enable_irq();</div>
477 <div class="line"> </div>
478 <div class="line"> <span class="keywordflow">return</span> (val);</div>
479 <div class="line">}</div>
480 </div><!-- fragment --></li>
481 <li>Add the function to the SVC function table in the <b>svc_user.c</b> module: <div class="fragment"><div class="line"><span class="keywordtype">void</span> * <span class="keyword">const</span> osRtxUserSVC[1+USER_SVC_COUNT] = {</div>
482 <div class="line"> (<span class="keywordtype">void</span> *)USER_SVC_COUNT,</div>
483 <div class="line"> (<span class="keywordtype">void</span> *)svc_atomic_inc32,</div>
484 <div class="line">};</div>
485 </div><!-- fragment --></li>
486 <li>Increment the number of user SVC functions: <div class="fragment"><div class="line"><span class="preprocessor">#define USER_SVC_COUNT 1 </span><span class="comment">// Number of user SVC functions</span></div>
487 </div><!-- fragment --></li>
488 <li><p class="startli">Declare a function wrapper to be called by the user to execute the SVC call.<br />
489 <b>Code</b> <b>Example</b> (Arm Compiler 6) </p><div class="fragment"><div class="line">__STATIC_FORCEINLINE uint32_t atomic_inc32 (uint32_t *mem) {</div>
490 <div class="line"> <span class="keyword">register</span> uint32_t val;</div>
491 <div class="line"> </div>
492 <div class="line"> __ASM <span class="keyword">volatile</span> (</div>
493 <div class="line"> <span class="stringliteral">"svc 1"</span> : <span class="stringliteral">"=l"</span> (val) : <span class="stringliteral">"l"</span> (mem) : <span class="stringliteral">"cc"</span>, <span class="stringliteral">"memory"</span></div>
494 <div class="line"> );</div>
495 <div class="line"> <span class="keywordflow">return</span> (val);</div>
496 <div class="line">}</div>
497 </div><!-- fragment --><p class="startli"><b>Code</b> <b>Example</b> (Arm Compiler 5 using <code>__svc(x)</code> attribute) </p><div class="fragment"><div class="line">uint32_t atomic_inc32 (uint32_t *mem) __svc(1);</div>
498 </div><!-- fragment --></li>
500 <dl class="section note"><dt>Note</dt><dd><ul>
501 <li>The SVC function <span class="XML-Token">0</span> is <b>reserved</b> for the Keil RTX5 kernel.</li>
502 <li>Do not leave gaps when numbering SVC functions. They must occupy a <b>continuous</b> range of numbers starting from 1.</li>
503 <li>SVC functions can still be interrupted.</li>
506 <h1><a class="anchor" id="cre_rtx_proj_clib_arm"></a>
507 Arm C library multi-threading protection</h1>
508 <p>RTX5 provides an interface to the <a href="https://developer.arm.com/docs/dui0475/m/the-arm-c-and-c-libraries/multithreaded-support-in-arm-c-libraries" target="_blank"><b>Arm C libraries</b></a> to ensure static data protection in a multi-threaded application.</p>
509 <p>The Arm C libraries use static data to store errno, floating-point status word for software floating-point operations, a pointer to the base of the heap, and other variables. The Arm C micro-library (i.e. microlib) does not support protection for multi-threaded applications. See the <a href="https://developer.arm.com/docs/dui0475/m/the-arm-c-micro-library/differences-between-microlib-and-the-default-c-library" target="_blank"><b>limitations and differences</b></a> between microlib and the default C library.</p>
510 <p>By default, RTX5 uses the Arm C libraries multi-thread protection for:</p><ul>
511 <li>all user threads if <a class="el" href="config_rtx5.html#threadConfig">Object specific Memory allocation</a> is enabled.</li>
512 <li>the number of threads defined by <b>OS_THREAD_LIBSPACE_NUM</b> if <a class="el" href="config_rtx5.html#threadConfig">Object specific Memory allocation</a> is disabled. The definition <b>OS_THREAD_LIBSPACE_NUM</b> defines the number of threads that can safely call Arm C library functions and can be found in "RTX_Config.h" file or can be defined on the global scope.</li>
514 <p>The default, Arm C libraries use mutex functions to <a href="https://developer.arm.com/docs/dui0475/m/the-arm-c-and-c-libraries/multithreaded-support-in-arm-c-libraries/management-of-locks-in-multithreaded-applications" target="_blank"><b>protect shared resources from concurrent access</b></a>. RTX5 implements these functions and uses resources from the <a class="el" href="config_rtx5.html#systemConfig">Global Dynamic Memory</a> to allocate mutex objects. </p>
515 </div></div><!-- contents -->
516 </div><!-- PageDoc -->
517 </div><!-- doc-content -->
518 <!-- start footer part -->
519 <div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
522 <script type="text/javascript">
524 writeFooter.call(this);