1/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
2//  ==== Kernel Control ====
3/**
4\addtogroup CMSIS_RTOS_KernelCtrl Kernel Information and Control
5\ingroup CMSIS_RTOS
6\brief Provides version/system information and starts/controls the RTOS Kernel.
7\details
8The kernel Information and Control function group allows to:
9  - obtain information about the system and the underlying kernel.
10  - obtain version information about the CMSIS-RTOS API.
11  - initialize of the RTOS kernel for creating objects.
12  - start the RTOS kernel and thread switching.
13  - check the execution status of the RTOS kernel.
14
15\note The kernel information and control functions cannot be called from
16\ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
17\note The kernel initialization is documented in \ref SystemStartup.
18
19<b>Code Example</b>
20\code
21/*----------------------------------------------------------------------------
22 * Application main thread
23 *---------------------------------------------------------------------------*/
24void app_main (void *argument) {
25
26  // ...
27  for (;;) {}
28}
29
30int main (void) {
31
32  // System Initialization
33  SystemCoreClockUpdate();
34  // ...
35
36  osKernelInitialize();                 // Initialize CMSIS-RTOS
37  osThreadNew(app_main, NULL, NULL);    // Create application main thread
38  osKernelStart();                      // Start thread execution
39  for (;;) {}
40}
41\endcode
42@{
43*/
44/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
45/**
46\struct osVersion_t
47\details
48Identifies the underlying RTOS kernel and API version number. The version is represented in a combined decimal number in the
49format: major.minor.rev: mmnnnrrrr
50
51Use \ref osKernelGetInfo to retrieve the version numbers.
52*/
53
54/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
55/**
56\typedef osKernelState_t
57\details
58State of the kernel as retrieved by \ref osKernelGetState. In case \b osKernelGetState fails or if it is called from an ISR,
59it will return \c osKernelError, otherwise it returns the kernel state.
60
61\var osKernelState_t::osKernelInactive
62\details
63The kernel is not ready yet. \ref osKernelInitialize needs to be executed successfully.
64
65\var osKernelState_t::osKernelReady
66\details
67The kernel is not yet running. \ref osKernelStart transfers the kernel to the running state.
68
69\var osKernelState_t::osKernelRunning
70\details
71The kernel is initialized and running.
72
73\var osKernelState_t::osKernelLocked
74\details
75The kernel was locked with \ref osKernelLock. The functions \ref osKernelUnlock or \ref osKernelRestoreLock unlocks it.
76
77\var osKernelState_t::osKernelSuspended
78\details
79The kernel was suspended using \ref osKernelSuspend. The function \ref osKernelResume returns to normal operation.
80
81\var osKernelState_t::osKernelError
82\details
83An error occurred.
84
85\var osKernelState_t::osKernelReserved
86\details
87Reserved.
88
89*/
90
91/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
92/**
93\fn osStatus_t osKernelInitialize (void)
94\details
95The function \b osKernelInitialize initializes the RTOS Kernel. Before it is successfully executed, only the functions
96\ref osKernelGetInfo and \ref osKernelGetState may be called.
97
98Possible \ref osStatus_t return values:
99- \em osOK in case of success.
100- \em osError if an unspecific error occurred.
101- \em osErrorISR if called from an \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routine".
102- \em osErrorNoMemory if no memory could be reserved for the operation.
103
104\note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
105
106<b> Code Example</b>
107\code
108#include "RTE_Components.h"
109#include  CMSIS_device_header
110#include "cmsis_os2.h"
111
112/*----------------------------------------------------------------------------
113 * Application main thread
114 *---------------------------------------------------------------------------*/
115void app_main (void *argument) {
116
117  // ...
118  for (;;) {}
119}
120
121int main (void) {
122
123  // System Initialization
124  SystemCoreClockUpdate();
125  // ...
126
127  osKernelInitialize();                 // Initialize CMSIS-RTOS
128  osThreadNew(app_main, NULL, NULL);    // Create application main thread
129  osKernelStart();                      // Start thread execution
130  for (;;) {}
131}
132\endcode
133*/
134
135/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
136/**
137\fn osStatus_t osKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size)
138\details
139The function \b  osKernelGetInfo retrieves the API and kernel version of the underlying RTOS kernel and a human readable
140identifier string for the kernel. It can be safely called before the RTOS is initialized or started (call to
141\ref osKernelInitialize or \ref osKernelStart).
142
143Possible \ref osStatus_t return values:
144- \em osOK in case of success.
145- \em osError if an unspecific error occurred.
146
147\note This function may be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
148
149<b>Code Example</b>
150\code
151void info (void) {
152  char infobuf[100];
153  osVersion_t osv;
154  osStatus_t status;
155
156  status = osKernelGetInfo(&osv, infobuf, sizeof(infobuf));
157  if(status == osOK) {
158    printf("Kernel Information: %s\r\n", infobuf);
159    printf("Kernel Version    : %d\r\n", osv.kernel);
160    printf("Kernel API Version: %d\r\n", osv.api);
161  }
162}
163\endcode
164*/
165
166/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
167/**
168\fn osKernelState_t osKernelGetState (void)
169\details
170The function \b osKernelGetState returns the current state of the kernel and can be safely called before the RTOS is
171initialized or started (call to \ref osKernelInitialize or \ref osKernelStart). In case it fails it will return \c osKernelError,
172otherwise it returns the kernel state (refer to \ref osKernelState_t for the list of kernel states).
173
174Possible \ref osKernelState_t return values:
175- \ref osKernelError if an unspecific error occurred.
176- the actual kernel state otherwise.
177
178\note This function may be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
179
180<b>Code Example</b>
181\code
182int main (void) {
183  // System Initialization
184  SystemCoreClockUpdate();
185  // ...
186  if(osKernelGetState() == osKernelInactive) {     // Is the kernel initialized?
187     osKernelInitialize();                         // Initialize CMSIS-RTOS kernel
188  }
189  ;
190}
191\endcode
192
193*/
194/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
195/**
196\fn osStatus_t osKernelStart (void)
197\details
198The function \b osKernelStart starts the RTOS kernel and begins thread switching. It will not return to its calling function
199in case of success. Before it is successfully executed, only the functions \ref osKernelGetInfo, \ref osKernelGetState, and
200object creation functions (\b osXxxNew) may be called.
201
202At least one initial thread should be created prior osKernelStart, see \ref osThreadNew.
203
204Possible \ref osStatus_t return values:
205- \em osError if an unspecific error occurred.
206- \em osErrorISR if called from an \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routine".
207
208\note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
209
210<b>Code Example</b>
211\code
212int main (void) {
213  // System Initialization
214  SystemCoreClockUpdate();
215  // ...
216  if(osKernelGetState() == osKernelInactive) {
217    osKernelInitialize();
218  }
219  ; // ... Start Threads
220  if (osKernelGetState() == osKernelReady) {        // If kernel is ready to run...
221    osKernelStart();                                // ... start thread execution
222    }
223
224  while(1);                                         // only reached in case of error
225}
226\endcode
227*/
228
229/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
230/**
231\fn int32_t osKernelLock (void)
232\details
233The function \b osKernelLock allows to lock all task switches. It returns the previous value of the lock state (\token{1} if
234it was locked, \token{0} if it was unlocked), or a negative number representing an error code otherwise (refer to
235\ref osStatus_t).
236
237Possible \ref osStatus_t return values:
238- \em osError if an unspecific error occurred.
239- \em osErrorISR if called from an \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routine".
240- \em osErrorSafetyClass if the calling thread safety class is lower than the kernel protect safety class.
241
242\note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
243
244<b>Code Example</b>
245\code
246  int32_t state = osKernelLock();
247  // ... critical code
248  osKernelRestore(state);
249\endcode
250*/
251
252/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
253/**
254\fn int32_t osKernelUnlock (void)
255\details
256The function \b osKernelUnlock resumes from \ref osKernelLock. It returns the previous value of the lock state (\token{1} if
257it was locked, \token{0} if it was unlocked), or a negative number representing an error code otherwise (refer to
258\ref osStatus_t).
259
260Possible \ref osStatus_t return values:
261- \em osError if an unspecific error occurred.
262- \em osErrorISR if called from an \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routine".
263
264\note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
265
266<b>Code Example</b>
267\code
268  int32_t sl = osKernelLock();
269  // ... critical code
270  {
271    int32_t su = osKernelUnlock();
272    // ... uncritical code
273    osKernelRestoreLock(su);
274  }
275  // ... critical code
276  osKernelRestoreLock(sl);
277\endcode
278*/
279
280/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
281/**
282\fn int32_t osKernelRestoreLock (int32_t lock)
283\details
284The function \b osKernelRestoreLock restores the previous lock state after \ref osKernelLock or \ref osKernelUnlock.
285
286The argument \a lock specifies the lock state as obtained by \ref osKernelLock or \ref osKernelUnlock.
287
288The function returns the new value of the lock state (\token{1} if it was locked, \token{0} if it was unlocked), or a
289negative number representing an error code otherwise (refer to \ref osStatus_t).
290
291Possible \ref osStatus_t return values:
292- \em osError if an unspecific error occurred.
293- \em osErrorISR if called from interrupt other than fault or \ref osWatchdogAlarm_Handler.
294- \em osErrorSafetyClass if the calling thread safety class is lower than the kernel protect safety class.
295
296<b>Code Example</b>
297\code
298  int32_t sl = osKernelLock();
299  // ... critical code
300  {
301    int32_t su = osKernelUnlock();
302    // ... uncritical code
303    osKernelRestoreLock(su);
304  }
305  // ... critical code
306  osKernelRestoreLock(sl);
307\endcode
308*/
309
310/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
311/**
312\fn uint32_t osKernelSuspend (void)
313\details
314CMSIS-RTOS2 provides extension for tick-less operation which is useful for applications that use extensively low-power modes where the SysTick timer is also disabled.
315
316To provide a time-tick in such power-saving modes a wake-up timer is used to derive timer intervals. The function \b osKernelSuspend suspends the RTOS kernel scheduler and thus enables sleep modes.
317
318The return value can be used to determine the amount of system ticks until the next tick-based kernel event will occur, i.e. a delayed thread becomes ready again. It is recommended to set up the low power timer to generate a wake-up interrupt based on this return value.
319
320\note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
321
322<b>Code Example</b>
323\code
324void osRtxIdleThread (void) {
325                                               /* The idle thread is running
326                                                  when no other thread is ready
327                                                  to run.                      */
328  unsigned int sleep;
329
330  for (;;) {
331                                               /* HERE: include optional user
332                                                  code to be executed when no
333                                                  task runs.                   */
334    sleep = osKernelSuspend();                 /* Suspend RTOS kernel scheduler */
335
336    if (sleep) {                               /* How long can we sleep?       */
337                                               /* "sleep" is in kernel Timer Ticks
338                                                  which is 1ms in this
339                                                  configuration                */
340
341                                               /* Setup wake-up e.g. watchdog  */
342
343      __WFE();                                 /* Enter Power-down mode        */
344
345                                               /* After Wake-up                */
346      sleep = tc;                              /* Adjust with cycles slept     */
347    }
348
349    osKernelResume(sleep);                     /* Resume thread scheduler      */
350  }
351}
352\endcode
353*/
354
355/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
356/**
357\fn void osKernelResume (uint32_t sleep_ticks)
358\details
359CMSIS-RTOS provides extension for tick-less operation which is useful for applications that use extensively low-power modes where the SysTick timer is also disabled.
360
361To provide a time-tick in such power-saving modes a wake-up timer is used to derive timer intervals. The function \b osKernelResume enables the RTOS kernel scheduler and thus wakes up the system from sleep
362mode.
363
364\note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
365
366<b>Code Example</b>
367\code
368void osRtxIdleThread (void) {
369                                               /* The idle thread is running
370                                                  when no other thread is ready
371                                                  to run.                      */
372  unsigned int sleep;
373
374  for (;;) {
375                                               /* HERE: include optional user
376                                                  code to be executed when no
377                                                  task runs.                   */
378    sleep = osKernelSuspend();                 /* Suspend RTOS kernel scheduler */
379
380    if (sleep) {                               /* How long can we sleep?       */
381                                               /* "sleep" is in Kernel Timer Ticks
382                                                  which is 1ms in this
383                                                  configuration                */
384
385                                               /* Setup wake-up e.g. watchdog  */
386
387      __WFE();                                 /* Enter Power-down mode        */
388
389                                               /* After Wake-up                */
390      sleep = tc;                              /* Adjust with cycles slept     */
391    }
392
393    osKernelResume(sleep);                     /* Resume thread scheduler      */
394  }
395}
396\endcode
397
398*/
399/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
400/**
401\fn uint32_t osKernelGetTickCount (void)
402\details
403The function \b osKernelGetTickCount returns the current RTOS kernel tick count.
404
405\note This function may be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
406
407\b Code \b Example
408\code
409#include "cmsis_os2.h"
410
411void Thread_1 (void *arg)  {                // Thread function
412  uint32_t tick;
413
414  tick = osKernelGetTickCount();            // retrieve the number of system ticks
415  for (;;) {
416    tick += 1000;                           // delay 1000 ticks periodically
417    osDelayUntil(tick);
418    // ...
419  }
420}\endcode
421
422Due to the limited value range used for the tick count it may overflow during runtime,
423i.e. after 2<sup>32</sup> ticks which are roughly 49days @ 1ms. Typically one has not to
424take special care of this unless a monotonic counter is needed. For such a case an additional
42564bit tick counter can be implemented as follows. The given example needs GetTick() called at
426least twice per tick overflow to work properly.
427
428\b Code \b Example
429\code
430uint64_t GetTick(void) {
431  static uint32_t tick_h = 0U;
432  static uint32_t tick_l = 0U;
433         uint32_t tick;
434
435  tick = osKernelGetTickCount();
436  if (tick < tick_l) {
437    tick_h++;
438  }
439  tick_l = tick;
440
441  return (((uint64_t)tick_h << 32) | tick_l);
442}
443\endcode
444*/
445
446/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
447/**
448\fn uint32_t osKernelGetTickFreq (void)
449\details
450The function \b osKernelGetTickFreq returns the frequency of the current RTOS kernel tick.
451
452\note This function may be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
453*/
454
455/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
456/**
457\fn uint32_t osKernelGetSysTimerCount (void)
458\details
459The function \b osKernelGetSysTimerCount returns the current RTOS kernel system timer as a 32-bit value.
460The value is a rolling 32-bit counter that is composed of the kernel system interrupt timer value
461and the counter that counts these interrupts (RTOS kernel ticks).
462
463This function allows the implementation of very short timeout checks below the RTOS tick granularity.
464Such checks might be required when checking for a busy status in a device or peripheral initialization
465routine, see code example below.
466
467\note This function may be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
468
469<b>Code Example</b>
470\code{.c}
471#include "cmsis_os2.h"
472
473void SetupDevice (void)  {
474  uint32_t tick;
475
476  // Calculating 100us timeout in system timer ticks
477  const uint32_t timeout = 100U * osKernelGetSysTimerFreq() / 1000000u;
478
479  tick = osKernelGetSysTimerCount();             // get start value of the Kernel system tick
480  Device.Setup ();                               // initialize a device or peripheral
481  do {                                           // poll device busy status for 100 microseconds
482    if (!Device.Busy) break;                     // check if device is correctly initialized
483  } while ((osKernelGetSysTimerCount() - tick) < timeout));
484  if (Device.Busy)  {
485    ;                                            // in case device still busy, signal error
486  }
487                                                 // start interacting with device
488}
489
490\endcode
491*/
492
493/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
494/**
495\fn uint32_t osKernelGetSysTimerFreq (void)
496\details
497The function \b osKernelGetSysTimerFreq returns the frequency of the current RTOS kernel system timer.
498
499\note This function may be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
500*/
501
502/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
503/**
504\fn osStatus_t osKernelProtect (uint32_t safety_class);
505\details
506The function \b osKernelProtect configures kernel access protection. After its successful execution, only threads with
507safety class equal or higher than the \a safety_class specified in the argument can execute kernel control functions.
508- \ref osKernelLock
509- \ref osKernelUnlock
510- \ref osKernelRestoreLock
511- \ref osKernelSuspend
512- \ref osKernelResume
513- \ref osKernelProtect
514
515Possible \ref osStatus_t return values:
516- \em osOK in case of success.
517- \em osErrorParameter if \a safety_class is invalid.
518- \em osError if kernel is not in ready or running state.
519- \em osErrorISR if called from an \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routine".
520- \em osErrorSafetyClass if the calling thread safety class is lower than the kernel protect safety class.
521
522\note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
523
524<b>Code Example:</b>
525\code
526#include "cmsis_os2.h"
527
528void ProtectKernelControlFunctions (void) {
529  osStatus_t status;
530
531  status = osKernelProtect(4U); // Enable Kernel Control for threads with safety class 4 or higher
532  // verify status value here.
533}
534\endcode
535*/
536
537/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
538/**
539\fn osStatus_t osKernelDestroyClass (uint32_t safety_class, uint32_t mode);
540\details
541The function \b osKernelDestroyClass destroys RTOS objects based on safety class assignment. \a safety_class provides the reference safety class value, while \a mode is considered as a bitmap that additionally specifies the safety classes to be destroyed.
542
543If \ref osSafetyWithSameClass is set in \a mode than the RTOS objects with safety class value equal to \a safety_class will be destroyed.
544<br>
545If \ref osSafetyWithLowerClass is set in \a mode than the RTOS objects with safety class value lower than \a safety_class will be destroyed.
546
547Possible \ref osStatus_t return values:
548- \em osOK in case of success.
549- \em osErrorParameter if \a safety_class is invalid.
550- \em osErrorResource if no other \ref ThreadStates "READY" thread exists.
551- \em osErrorISR if called from interrupt other than \ref osWatchdogAlarm_Handler.
552- \em osErrorSafetyClass if the calling thread safety class is lower than the kernel protect safety class.
553
554<b>Code Example:</b>
555\code
556#include "cmsis_os2.h"
557
558void DestroyNonCriticalClasses (void) {
559  osStatus_t status;
560
561  status = osKernelDestroyClass(4U, osSafetyWithSameClass | osSafetyWithLowerClass); // Destroy objects with safety class 4 or lower
562  // verify status value here.
563}
564\endcode
565*/
566
567/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
568/**
569\fn void osFaultResume (void);
570\details
571Resume normal RTOS operation when exiting exception faults.
572
573<b>Code Example:</b>
574\code
575void HardFault_Handler (void) {
576  __ASM volatile (
577    "...                          \n\t" // Enter assembly and handle faults
578    "...                          \n\t"
579    "ldr  r0,=osFaultResume       \n\t" // Before exiting the handler load and
580    "bx   r0                      \n\t" // jump to osFaultResume
581  );
582}
583\endcode
584*/
585
586/// @}
587