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