/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ // ==== Kernel Control ==== /** \addtogroup CMSIS_RTOS_KernelCtrl Kernel Information and Control \ingroup CMSIS_RTOS \brief Provides version/system information and starts/controls the RTOS Kernel. \details The kernel Information and Control function group allows to: - obtain information about the system and the underlying kernel. - obtain version information about the CMSIS-RTOS API. - initialize of the RTOS kernel for creating objects. - start the RTOS kernel and thread switching. - check the execution status of the RTOS kernel. \note The kernel information and control functions cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". \note The kernel initialization is documented in \ref SystemStartup. Code Example \code /*---------------------------------------------------------------------------- * Application main thread *---------------------------------------------------------------------------*/ void app_main (void *argument) { // ... for (;;) {} } int main (void) { // System Initialization SystemCoreClockUpdate(); // ... osKernelInitialize(); // Initialize CMSIS-RTOS osThreadNew(app_main, NULL, NULL); // Create application main thread osKernelStart(); // Start thread execution for (;;) {} } \endcode @{ */ /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ /** \struct osVersion_t \details Identifies the underlying RTOS kernel and API version number. The version is represented in a combined decimal number in the format: major.minor.rev: mmnnnrrrr Use \ref osKernelGetInfo to retrieve the version numbers. */ /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ /** \typedef osKernelState_t \details State of the kernel as retrieved by \ref osKernelGetState. In case \b osKernelGetState fails or if it is called from an ISR, it will return \c osKernelError, otherwise it returns the kernel state. \var osKernelState_t::osKernelInactive \details The kernel is not ready yet. \ref osKernelInitialize needs to be executed successfully. \var osKernelState_t::osKernelReady \details The kernel is not yet running. \ref osKernelStart transfers the kernel to the running state. \var osKernelState_t::osKernelRunning \details The kernel is initialized and running. \var osKernelState_t::osKernelLocked \details The kernel was locked with \ref osKernelLock. The functions \ref osKernelUnlock or \ref osKernelRestoreLock unlocks it. \var osKernelState_t::osKernelSuspended \details The kernel was suspended using \ref osKernelSuspend. The function \ref osKernelResume returns to normal operation. \var osKernelState_t::osKernelError \details An error occurred. \var osKernelState_t::osKernelReserved \details Reserved. */ /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ /** \fn osStatus_t osKernelInitialize (void) \details The function \b osKernelInitialize initializes the RTOS Kernel. Before it is successfully executed, only the functions \ref osKernelGetInfo and \ref osKernelGetState may be called. Possible \ref osStatus_t return values: - \em osOK in case of success. - \em osError if an unspecific error occurred. - \em osErrorISR if called from an \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routine". - \em osErrorNoMemory if no memory could be reserved for the operation. \note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". Code Example \code #include "RTE_Components.h" #include CMSIS_device_header #include "cmsis_os2.h" /*---------------------------------------------------------------------------- * Application main thread *---------------------------------------------------------------------------*/ void app_main (void *argument) { // ... for (;;) {} } int main (void) { // System Initialization SystemCoreClockUpdate(); // ... osKernelInitialize(); // Initialize CMSIS-RTOS osThreadNew(app_main, NULL, NULL); // Create application main thread osKernelStart(); // Start thread execution for (;;) {} } \endcode */ /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ /** \fn osStatus_t osKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size) \details The function \b osKernelGetInfo retrieves the API and kernel version of the underlying RTOS kernel and a human readable identifier string for the kernel. It can be safely called before the RTOS is initialized or started (call to \ref osKernelInitialize or \ref osKernelStart). Possible \ref osStatus_t return values: - \em osOK in case of success. - \em osError if an unspecific error occurred. \note This function may be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". Code Example \code void info (void) { char infobuf[100]; osVersion_t osv; osStatus_t status; status = osKernelGetInfo(&osv, infobuf, sizeof(infobuf)); if(status == osOK) { printf("Kernel Information: %s\r\n", infobuf); printf("Kernel Version : %d\r\n", osv.kernel); printf("Kernel API Version: %d\r\n", osv.api); } } \endcode */ /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ /** \fn osKernelState_t osKernelGetState (void) \details The function \b osKernelGetState returns the current state of the kernel and can be safely called before the RTOS is initialized or started (call to \ref osKernelInitialize or \ref osKernelStart). In case it fails it will return \c osKernelError, otherwise it returns the kernel state (refer to \ref osKernelState_t for the list of kernel states). Possible \ref osKernelState_t return values: - \ref osKernelError if an unspecific error occurred. - the actual kernel state otherwise. \note This function may be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". Code Example \code int main (void) { // System Initialization SystemCoreClockUpdate(); // ... if(osKernelGetState() == osKernelInactive) { // Is the kernel initialized? osKernelInitialize(); // Initialize CMSIS-RTOS kernel } ; } \endcode */ /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ /** \fn osStatus_t osKernelStart (void) \details The function \b osKernelStart starts the RTOS kernel and begins thread switching. It will not return to its calling function in case of success. Before it is successfully executed, only the functions \ref osKernelGetInfo, \ref osKernelGetState, and object creation functions (\b osXxxNew) may be called. At least one initial thread should be created prior osKernelStart, see \ref osThreadNew. Possible \ref osStatus_t return values: - \em osError if an unspecific error occurred. - \em osErrorISR if called from an \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routine". \note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". Code Example \code int main (void) { // System Initialization SystemCoreClockUpdate(); // ... if(osKernelGetState() == osKernelInactive) { osKernelInitialize(); } ; // ... Start Threads if (osKernelGetState() == osKernelReady) { // If kernel is ready to run... osKernelStart(); // ... start thread execution } while(1); // only reached in case of error } \endcode */ /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ /** \fn int32_t osKernelLock (void) \details The function \b osKernelLock allows to lock all task switches. It returns the previous value of the lock state (\token{1} if it was locked, \token{0} if it was unlocked), or a negative number representing an error code otherwise (refer to \ref osStatus_t). Possible \ref osStatus_t return values: - \em osError if an unspecific error occurred. - \em osErrorISR if called from an \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routine". - \em osErrorSafetyClass if the calling thread safety class is lower than the kernel protect safety class. \note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". Code Example \code int32_t state = osKernelLock(); // ... critical code osKernelRestore(state); \endcode */ /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ /** \fn int32_t osKernelUnlock (void) \details The function \b osKernelUnlock resumes from \ref osKernelLock. It returns the previous value of the lock state (\token{1} if it was locked, \token{0} if it was unlocked), or a negative number representing an error code otherwise (refer to \ref osStatus_t). Possible \ref osStatus_t return values: - \em osError if an unspecific error occurred. - \em osErrorISR if called from an \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routine". \note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". Code Example \code int32_t sl = osKernelLock(); // ... critical code { int32_t su = osKernelUnlock(); // ... uncritical code osKernelRestoreLock(su); } // ... critical code osKernelRestoreLock(sl); \endcode */ /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ /** \fn int32_t osKernelRestoreLock (int32_t lock) \details The function \b osKernelRestoreLock restores the previous lock state after \ref osKernelLock or \ref osKernelUnlock. The argument \a lock specifies the lock state as obtained by \ref osKernelLock or \ref osKernelUnlock. The function returns the new value of the lock state (\token{1} if it was locked, \token{0} if it was unlocked), or a negative number representing an error code otherwise (refer to \ref osStatus_t). Possible \ref osStatus_t return values: - \em osError if an unspecific error occurred. - \em osErrorISR if called from interrupt other than fault or \ref osWatchdogAlarm_Handler. - \em osErrorSafetyClass if the calling thread safety class is lower than the kernel protect safety class. Code Example \code int32_t sl = osKernelLock(); // ... critical code { int32_t su = osKernelUnlock(); // ... uncritical code osKernelRestoreLock(su); } // ... critical code osKernelRestoreLock(sl); \endcode */ /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ /** \fn uint32_t osKernelSuspend (void) \details CMSIS-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. To 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. The 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. \note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". Code Example \code void osRtxIdleThread (void) { /* The idle thread is running when no other thread is ready to run. */ unsigned int sleep; for (;;) { /* HERE: include optional user code to be executed when no task runs. */ sleep = osKernelSuspend(); /* Suspend RTOS kernel scheduler */ if (sleep) { /* How long can we sleep? */ /* "sleep" is in kernel Timer Ticks which is 1ms in this configuration */ /* Setup wake-up e.g. watchdog */ __WFE(); /* Enter Power-down mode */ /* After Wake-up */ sleep = tc; /* Adjust with cycles slept */ } osKernelResume(sleep); /* Resume thread scheduler */ } } \endcode */ /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ /** \fn void osKernelResume (uint32_t sleep_ticks) \details CMSIS-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. To 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 mode. \note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". Code Example \code void osRtxIdleThread (void) { /* The idle thread is running when no other thread is ready to run. */ unsigned int sleep; for (;;) { /* HERE: include optional user code to be executed when no task runs. */ sleep = osKernelSuspend(); /* Suspend RTOS kernel scheduler */ if (sleep) { /* How long can we sleep? */ /* "sleep" is in Kernel Timer Ticks which is 1ms in this configuration */ /* Setup wake-up e.g. watchdog */ __WFE(); /* Enter Power-down mode */ /* After Wake-up */ sleep = tc; /* Adjust with cycles slept */ } osKernelResume(sleep); /* Resume thread scheduler */ } } \endcode */ /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ /** \fn uint32_t osKernelGetTickCount (void) \details The function \b osKernelGetTickCount returns the current RTOS kernel tick count. \note This function may be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". \b Code \b Example \code #include "cmsis_os2.h" void Thread_1 (void *arg) { // Thread function uint32_t tick; tick = osKernelGetTickCount(); // retrieve the number of system ticks for (;;) { tick += 1000; // delay 1000 ticks periodically osDelayUntil(tick); // ... } }\endcode Due to the limited value range used for the tick count it may overflow during runtime, i.e. after 232 ticks which are roughly 49days @ 1ms. Typically one has not to take special care of this unless a monotonic counter is needed. For such a case an additional 64bit tick counter can be implemented as follows. The given example needs GetTick() called at least twice per tick overflow to work properly. \b Code \b Example \code uint64_t GetTick(void) { static uint32_t tick_h = 0U; static uint32_t tick_l = 0U; uint32_t tick; tick = osKernelGetTickCount(); if (tick < tick_l) { tick_h++; } tick_l = tick; return (((uint64_t)tick_h << 32) | tick_l); } \endcode */ /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ /** \fn uint32_t osKernelGetTickFreq (void) \details The function \b osKernelGetTickFreq returns the frequency of the current RTOS kernel tick. \note This function may be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". */ /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ /** \fn uint32_t osKernelGetSysTimerCount (void) \details The function \b osKernelGetSysTimerCount returns the current RTOS kernel system timer as a 32-bit value. The value is a rolling 32-bit counter that is composed of the kernel system interrupt timer value and the counter that counts these interrupts (RTOS kernel ticks). This function allows the implementation of very short timeout checks below the RTOS tick granularity. Such checks might be required when checking for a busy status in a device or peripheral initialization routine, see code example below. \note This function may be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". Code Example \code{.c} #include "cmsis_os2.h" void SetupDevice (void) { uint32_t tick; // Calculating 100us timeout in system timer ticks const uint32_t timeout = 100U * osKernelGetSysTimerFreq() / 1000000u; tick = osKernelGetSysTimerCount(); // get start value of the Kernel system tick Device.Setup (); // initialize a device or peripheral do { // poll device busy status for 100 microseconds if (!Device.Busy) break; // check if device is correctly initialized } while ((osKernelGetSysTimerCount() - tick) < timeout)); if (Device.Busy) { ; // in case device still busy, signal error } // start interacting with device } \endcode */ /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ /** \fn uint32_t osKernelGetSysTimerFreq (void) \details The function \b osKernelGetSysTimerFreq returns the frequency of the current RTOS kernel system timer. \note This function may be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". */ /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ /** \fn osStatus_t osKernelProtect (uint32_t safety_class); \details The function \b osKernelProtect configures kernel access protection. After its successful execution, only threads with safety class equal or higher than the \a safety_class specified in the argument can execute kernel control functions. - \ref osKernelLock - \ref osKernelUnlock - \ref osKernelRestoreLock - \ref osKernelSuspend - \ref osKernelResume - \ref osKernelProtect Possible \ref osStatus_t return values: - \em osOK in case of success. - \em osErrorParameter if \a safety_class is invalid. - \em osError if kernel is not in ready or running state. - \em osErrorISR if called from an \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routine". - \em osErrorSafetyClass if the calling thread safety class is lower than the kernel protect safety class. \note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". Code Example: \code #include "cmsis_os2.h" void ProtectKernelControlFunctions (void) { osStatus_t status; status = osKernelProtect(4U); // Enable Kernel Control for threads with safety class 4 or higher // verify status value here. } \endcode */ /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ /** \fn osStatus_t osKernelDestroyClass (uint32_t safety_class, uint32_t mode); \details The 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. If \ref osSafetyWithSameClass is set in \a mode than the RTOS objects with safety class value equal to \a safety_class will be destroyed.
If \ref osSafetyWithLowerClass is set in \a mode than the RTOS objects with safety class value lower than \a safety_class will be destroyed. Possible \ref osStatus_t return values: - \em osOK in case of success. - \em osErrorParameter if \a safety_class is invalid. - \em osErrorResource if no other \ref ThreadStates "READY" thread exists. - \em osErrorISR if called from interrupt other than \ref osWatchdogAlarm_Handler. - \em osErrorSafetyClass if the calling thread safety class is lower than the kernel protect safety class. Code Example: \code #include "cmsis_os2.h" void DestroyNonCriticalClasses (void) { osStatus_t status; status = osKernelDestroyClass(4U, osSafetyWithSameClass | osSafetyWithLowerClass); // Destroy objects with safety class 4 or lower // verify status value here. } \endcode */ /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ /** \fn void osFaultResume (void); \details Resume normal RTOS operation when exiting exception faults. Code Example: \code void HardFault_Handler (void) { __ASM volatile ( "... \n\t" // Enter assembly and handle faults "... \n\t" "ldr r0,=osFaultResume \n\t" // Before exiting the handler load and "bx r0 \n\t" // jump to osFaultResume ); } \endcode */ /// @}