The CMSIS-RTOS v2 (CMSIS-RTOS2) provides generic RTOS interfaces for Arm® Cortex® processor-based devices. It provides a standardized API for software components that require RTOS functionality and gives therefore serious benefits to the users and the software industry:
- CMSIS-RTOS2 provides basic features that are required in many applications.
- The unified feature set of the CMSIS-RTOS2 reduces learning efforts and simplifies sharing of software components.
- Middleware components that use the CMSIS-RTOS2 are RTOS agnostic and are easier to adapt.
- Standard project templates of the CMSIS-RTOS2 may be shipped with freely available CMSIS-RTOS2 implementations.
This CMSIS-RTOS v2 represents a wrapper layer for CMSIS RTOS v2 APIs implementation based on threadX RTOS APIs. The list of features supported by the current implementation are as below:
Feature | Supported | Short Description |
---|---|---|
Kernel Information and Control | Y | It provide version/system information and starts/controls the RTOS Kernel. More... |
Thread Management | Y | It define, create, and control thread functions.. More... |
Thread Flags | N | It synchronize threads using flags. More... |
Event Flags | Y | It synchronize threads using event flags. More... |
Generic Wait Functions | Y | It wait for a certain period of time.. More... |
Timer Management | Y | It create and control timer and timer callback functions. More... |
Mutex Management | Y | It synchronize resource access using Mutual Exclusion (Mutex). More... |
Semaphores | Y | It access shared resources simultaneously from different threads. More... |
Memory Pool | Y | It manage thread-safe fixed-size blocks of dynamic memory. More... |
Message Queue | Y | It exchange messages between threads in a FIFO-like operation. More... |
For more information about CMSIS-RTOS v2 APIs, please refer to the ARM manual: CMSIS-RTOS API v2
In threadX RTOS only one interface is used to start the kernel (tx_kernel_enter). This function will:
- _tx_initialize_low_level: invoke the low-level initialization to handle all processor specific initialization issues
- _tx_initialize_high_level: invoke the high-level initialization to exercise all of the ThreadX components and the application's initialization function
- tx_application_define: call the application provided initialization function. Pass the first available memory address to it
- _tx_thread_schedule: enter the scheduling loop to start executing threads.
For ARM CMSIS solution, its mandatory to separate the kernel initialization from the kernel start to allow the user to create threads, timers, semaphores,... in between. For that we design the CMSIS-RTOS2 wrapper as below:
- osKernelInitialize: will initialize the low level and high level layers by calling the function "_tx_initialize_kernel_setup"
- osKernelGetState: will call the application provided initialization function start the kernel.
CMSIS-RTOS v2 APIs such as osThreadNew, give the possibilities to the user, when implementing his application, to:
- Pass the block memory and stack address (declared or allocated in the application level)
- Let the low layers (wrapper or RTOS) allocate the memory
However, the dynamic memory allocation is not a supported feature for threadX RTOS. In fact, its mandatory to implement it in CMSIS RTOS v2 wrapper level.
The global idea for dynamic memory allocation solution is to use two threadX BytePools:
- HeapBytePool: used for thread, timer, mutex, semaphore, event flags and message queue object block memory allocation
- StackBytePool: used for thread and message queue stack memory allocation.
In fact, three internal functions are added as following:
Function Name | Short Description |
---|---|
MemInit | creates the HeapBytePool and StackBytePool BytePools |
MemAlloc | allocate the needed memory for object block or stack |
MemFree | free the memory for object block or stack |
Notes:
- The sizes of HeapBytePool and StackBytePool are user defined using respectively the macro defines RTOS2_BYTE_POOL_HEAP_SIZE and RTOS2_BYTE_POOL_STACK_SIZE
- The minimum size of HeapBytePool and StackBytePool is defined by the threadX macro define TX_BYTE_POOL_MIN
- The HeapBytePool and StackBytePool are allocated from the first free memory area defined by the threadX variable _tx_initialize_unused_memory.
CMSIS-RTOS v2 gives the possibilities to the user, when implementing his application, to statically allocate the memory. In fact, static buffers will be created and allocated based on user defines RTOS2_BYTE_POOL_HEAP_SIZE and RTOS2_BYTE_POOL_STACK_SIZE. The minimum size of HeapBytePool and StackBytePool is defined by the threadX macro define TX_BYTE_POOL_MIN.
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.
API Name | Supported | Short Description | Limitation |
---|---|---|---|
osKernelInitialize | Y | Kernel Initialize... | No limitations |
osKernelGetInfo | Y | Kernel Get Info... | No limitations |
osKernelGetState | Y | Kernel Get State... | Only osKernelInactive, osKernelReady and osKernelRunning states are supported |
osKernelStart | Y | Kernel Start... | No limitations |
osKernelLock | N | Kernel Lock... | This API is not supported due to threadX limitation |
osKernelUnlock | N | Kernel Unlock... | This API is not supported due to threadX limitation |
osKernelRestoreLock | N | Kernel Restore Lock... | This API is not supported due to threadX limitation |
osKernelSuspend | N | Kernel Suspend... | This API is not supported due to threadX limitation |
osKernelResume | N | Kernel Resume... | This API is not supported due to threadX limitation |
osKernelGetTickCount | Y | Kernel Get Tick Count... | No limitations |
osKernelGetTickFreq | Y | Kernel Get Tick Freq... | No limitations |
osKernelGetSysTimerCount | Y | Kernel Get SysTimer Count... | No limitations |
osKernelGetSysTimerFreq | Y | Kernel Get SysTimer Freq... | No limitations |
Notes:
- Due to threadX RTOS limitation (no lock or suspend feature are supported), all kernel lock, suspend and resume APIs are not supported.
The Thread Management function group allows defining, creating, and controlling thread functions in the system.
API Name | Supported | Short Description | Limitation |
---|---|---|---|
osThreadNew | Y | Thread New... | If argument is given as input this will be considered as entry_input for threadX |
osThreadGetName | Y | Thread Get Name... | No limitations |
osThreadGetId | Y | Thread Get Id... | No limitations |
osThreadGetState | Y | Thread Get State... | Only osThreadRunning, osThreadReady, osThreadTerminated and osThreadBlocked thread states are supported |
osThreadSetPriority | Y | Thread Set Priority... | No limitations |
osThreadGetPriority | Y | Thread Get Priority... | No limitations |
osThreadYield | Y | Thread Yield... | No limitations |
osThreadSuspend | Y | Thread Suspend... | No limitations |
osThreadResume | Y | Thread Resume... | No limitations |
osThreadDetach | Y | Thread Detach... | TX_THREAD_USER_EXTENSION must be defined |
osThreadJoin | Y | Thread Join... | TX_THREAD_USER_EXTENSION must be defined |
osThreadExit | Y | Thread Exit... | No limitations |
osThreadTerminate | Y | Thread Terminate... | No limitations |
osThreadGetStackSize | Y | Thread Get Stack Size... | No limitations |
osThreadGetStackSpace | Y | Thread Get Stack Space... | No limitations |
osThreadGetCount | Y | Thread Get Count... | No limitations |
osThreadEnumerate | Y | Thread Enumerate... | No limitations |
Notes:
- Thread management functions cannot be called from Interrupt Service Routines.
- To support osThreadDetach and osThreadJoin APIs, the TX_THREAD_USER_EXTENSION must be defined as tx_thread_detached_joinable (ULONG) in tx_user.h file
Thread Flags are a more specialized version of the Event Flags. See Event Flags. While Event Flags can be used to globally signal a number of threads, thread flags are only send to a single specific thread. Every thread instance can receive thread flags without any additional allocation of a thread flags object.
API Name | Supported | Short Description | Limitation |
---|---|---|---|
osThreadFlagsSet | N | Thread Flags Set... | Not yet implemented |
osThreadFlagsClear | N | Thread Flags Clear... | Not yet implemented |
osThreadFlagsGet | N | Thread Flags Get... | Not yet implemented |
osThreadFlagsWait | N | Thread Flags Wait... | Not yet implemented |
Notes:
- Thread flag management functions cannot be called from Interrupt Service Routines, except for osThreadFlagsSet.
- The Thread flag management functions are not supported in the current CMSIS RTOS v2 implementation and will be implemented in the future version.
The event flags management functions in CMSIS-RTOS allow you to control or wait for event flags. Each signal has up to 31 event flags.
A thread :
- Can wait for event flags to be set (using osEventFlagsWait). Using this function, it enters the BLOCKED state.
- May set one or more flags in any other given thread (using osEventFlagsSet).
- May clear its own signals or the signals of other threads (using osEventFlagsClear).
- When a thread wakes up and resumes execution, its signal flags are automatically cleared (unless event flags option osFlagsNoClear is specified).
API Name | Supported | Short Description | Limitation |
---|---|---|---|
osEventFlagsNew | Y | Thread Flags Set... | No limitations |
osEventFlagsSet | Y | Thread Flags Clear... | No limitations |
osEventFlagsClear | Y | Thread Flags Get... | No limitations |
osEventFlagsGet | Y | Thread Flags Wait... | No limitations |
osEventFlagsWait | Y | Thread Flags Clear... | No limitations |
osEventFlagsDelete | Y | Thread Flags Get... | No limitations |
osEventFlagsGetName | Y | Thread Flags Wait... | No limitations |
Notes:
- The functions osEventFlagsSet, osEventFlagsClear, osEventFlagsGet, and osEventFlagsWait can be called from Interrupt Service Routines
- If a thread is blocked on waiting an event flag, the osEventFlagsSet will unblock it.
The generic wait functions provide means for a time delay.
API Name | Supported | Short Description | Limitation |
---|---|---|---|
osDelay | Y | Delay... | No limitations |
osDelayUntil | Y | Delay Until... | No limitations |
Notes:
- Generic wait functions cannot be called from Interrupt Service Routines.
In addition to the Generic Wait Functions CMSIS-RTOS also supports virtual timer objects. These timer objects can trigger the execution of a function (not threads). When a timer expires, a callback function is executed to run associated code with the timer. Each timer can be configured as a one-shot or a periodic timer. A periodic timer repeats its operation until it is deleted or stopped. All timers can be started, restarted, or stopped.
API Name | Supported | Short Description | Limitation |
---|---|---|---|
osTimerNew | Y | Timer New... | No limitations |
osTimerGetName | Y | Timer Get Name... | No limitations |
osTimerStart | Y | Timer Start... | No limitations |
osTimerStop | Y | Timer Stop... | No limitations |
osTimerIsRunning | Y | Timer Is Running... | No limitations |
osTimerDelete | Y | Timer Delete... | No limitations |
Notes:
- Timer management functions cannot be called from Interrupt Service Routines.
Mutual exclusion (widely known as Mutex) is used in various operating systems for resource management. Many resources in a microcontroller device can be used repeatedly, but only by one thread at a time (for example communication channels, memory, and files). Mutexes are used to protect access to a shared resource. A mutex is created and then passed between the threads (they can acquire and release the mutex).
API Name | Supported | Short Description | Limitation |
---|---|---|---|
osMutexNew | Y | Mutex New... | osMutexRobust and osMutexRecursive mutex types are not supported |
osMutexGetName | Y | Mutex Get Name... | No limitations |
osMutexAcquire | Y | Mutex Acquire... | No limitations |
osMutexRelease | Y | Mutex Release... | No limitations |
osMutexGetOwner | Y | Mutex Get Owner... | No limitations |
osMutexDelete | Y | Mutex Delete... | No limitations |
Notes:
- Mutex management functions cannot be called from Interrupt Service Routines (ISR), unlike a binary semaphore that can be released from an ISR.
- If a thread is blocked on acquiring or releasing the mutex, the osMutexAcquire and osMutexRelease will unblock it. Therefore, acquiring or releasing the mutex will not change the mutex status except from the number of thread blocked on it.
Semaphores are used to manage and protect access to shared resources. Semaphores are very similar to Mutexes. Whereas a Mutex permits just one thread to access a shared resource at a time, a semaphore can be used to permit a fixed number of threads/ISRs to access a pool of shared resources. Using semaphores, access to a group of identical peripherals can be managed (for example multiple DMA channels).
API Name | Supported | Short Description | Limitation |
---|---|---|---|
osSemaphoreNew | Y | Semaphore New... | The parameter max_count is not supported |
osSemaphoreGetName | Y | Semaphore Get Name... | No limitations |
osSemaphoreAcquire | Y | Semaphore Acquire... | No limitations |
osSemaphoreRelease | Y | Semaphore Release... | No limitations |
osSemaphoreGetCount | N | Semaphore Get Count... | This API is not supported due to max_count limitation |
osSemaphoreDelete | Y | Semaphore Delete... | No limitations |
Notes:
- The functions osSemaphoreAcquire, osSemaphoreGetCount, and osSemaphoreRelease can be called from Interrupt Service Routines.
- If a thread is blocked on acquiring or releasing the semaphore, the osSemaphoreAcquire and osSemaphoreRelease will unblock it. Therefore, acquiring or releasing the semaphore will not change the semaphore status except from the number of thread blocked on it
- Due to max_count limitation, the binary semaphore is not supported.
Memory Pools are fixed-size blocks of memory that are thread-safe. They operate much faster than the dynamically allocated heap and do not suffer from fragmentation. Being thread-safe, they can be accessed from threads and ISRs alike. A Memory Pool can be seen as a linked list of available (unused) memory blocks of fixed and equal size. Allocating memory from a pool (using osMemoryPoolAlloc) simply unchains a block from the list and hands over control to the user. Freeing memory to the pool (using osMemoryPoolFree) simply rechains the block into the list.
API Name | Supported | Short Description | Limitation |
---|---|---|---|
osMemoryPoolNew | Y | MemoryPool New... | No limitations |
osMemoryPoolGetName | Y | MemoryPool Get Name... | No limitations |
osMemoryPoolAlloc | Y | MemoryPool Alloc... | No limitations |
osMemoryPoolFree | Y | MemoryPool Free... | No limitations |
osMemoryPoolGetCapacity | Y | MemoryPool Get Capacity... | No limitations |
osMemoryPoolGetBlockSize | Y | MemoryPool Get Block Size... | No limitations |
osMemoryPoolGetCount | Y | MemoryPool Get Count... | No limitations |
osMemoryPoolGetSpace | Y | MemoryPool Get Count... | No limitations |
osMemoryPoolDelete | Y | MemoryPool Delete... | No limitations |
Notes:
- The functions osMemoryPoolAlloc, osMemoryPoolFree, osMemoryPoolGetCapacity, osMemoryPoolGetBlockSize, osMemoryPoolGetCount, osMemoryPoolGetSpace can be called from Interrupt Service Routines.
Message passing is another basic communication model between threads. In the message passing model, one thread sends data explicitly, while another thread receives it. The operation is more like some kind of I/O rather than a direct access to information to be shared. In CMSIS-RTOS, this mechanism is called s message queue. The data is passed from one thread to another in a FIFO-like operation. Using message queue functions, you can control, send, receive, or wait for messages. The data to be passed can be of integer or pointer type.
API Name | Supported | Short Description | Limitation |
---|---|---|---|
osMessageQueueNew | Y | MessageQueue New... | No limitations |
osMessageQueueGetName | Y | MessageQueue Get Name... | No limitations |
osMessageQueuePut | Y | MessageQueue Put... | Message priority is not supported |
osMessageQueueGet | Y | MessageQueue Get... | Message priority is not supported |
osMessageQueueGetCapacity | Y | MessageQueue Get Capacity... | No limitations |
osMessageQueueGetMsgSize | Y | MessageQueue Get Msg Size... | No limitations |
osMessageQueueGetCount | Y | MessageQueue Get Count... | No limitations |
osMessageQueueGetSpace | Y | MessageQueue Get Space... | No limitations |
osMessageQueueReset | Y | MessageQueue Reset... | No limitations |
osMessageQueueDelete | Y | MessageQueue Delete... | No limitations |
Notes:
- The functions osMessageQueuePut, osMessageQueueGet, osMessageQueueGetCapacity, osMessageQueueGetMsgSize, osMessageQueueGetCount, osMessageQueueGetSpace can be called from Interrupt Service Routines.
- If a thread is blocked on getting or putting a message on the queue, the osMessageQueuePut and osMessageQueueGet will unblock it. Therefore, putting or getting a message will not change the queue status except from the number of thread blocked on it.