tyustli 3 лет назад
Родитель
Сommit
a2cf05a60e
5 измененных файлов с 2725 добавлено и 0 удалено
  1. 6 0
      README.md
  2. 11 0
      SConscript
  3. 703 0
      cmsis_os.h
  4. 1558 0
      cmsis_rtthread.c
  5. 447 0
      testcases/cmsis_rtos_tc.c

+ 6 - 0
README.md

@@ -1 +1,7 @@
 # CMSIS-RTOS1 for RT-Thread
+
+RT-Thread adaptation for CMSIS-RTOS Version 1
+
+Version 1 source code
+
+- CMSIS_RTOS1/cmsis_rtthread.c

+ 11 - 0
SConscript

@@ -0,0 +1,11 @@
+from building import *
+
+src	= Glob('*.c')
+cwd = GetCurrentDir()
+
+if GetDepend('RT_USING_UTEST'):
+    src += ['testcases/cmsis_rtos_tc.c']
+
+path = [cwd]
+group = DefineGroup('CMSIS_RTOS1', src, depend = ['PKG_USING_CMSIS_RTOS1'], CPPPATH = path)
+Return('group')

+ 703 - 0
cmsis_os.h

@@ -0,0 +1,703 @@
+/* ----------------------------------------------------------------------
+ * $Date:        5. February 2013
+ * $Revision:    V1.02
+ *
+ * Project:      CMSIS-RTOS API
+ * Title:        cmsis_os.h template header file
+ *
+ * Version 0.02
+ *    Initial Proposal Phase
+ * Version 0.03
+ *    osKernelStart added, optional feature: main started as thread
+ *    osSemaphores have standard behavior
+ *    osTimerCreate does not start the timer, added osTimerStart
+ *    osThreadPass is renamed to osThreadYield
+ * Version 1.01
+ *    Support for C++ interface
+ *     - const attribute removed from the osXxxxDef_t typedef's
+ *     - const attribute added to the osXxxxDef macros
+ *    Added: osTimerDelete, osMutexDelete, osSemaphoreDelete
+ *    Added: osKernelInitialize
+ * Version 1.02
+ *    Control functions for short timeouts in microsecond resolution:
+ *    Added: osKernelSysTick, osKernelSysTickFrequency, osKernelSysTickMicroSec
+ *    Removed: osSignalGet 
+ *----------------------------------------------------------------------------
+ *
+ * Copyright (c) 2013-2017 ARM LIMITED
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *---------------------------------------------------------------------------*/
+ 
+ 
+#ifndef _CMSIS_OS_H
+#define _CMSIS_OS_H
+ 
+/// \note MUST REMAIN UNCHANGED: \b osCMSIS identifies the CMSIS-RTOS API version.
+#define osCMSIS           0x10002      ///< API version (main [31:16] .sub [15:0])
+ 
+/// \note CAN BE CHANGED: \b osCMSIS_KERNEL identifies the underlying RTOS kernel and version number.
+#define osCMSIS_KERNEL    0x10000	   ///< RTOS identification and version (main [31:16] .sub [15:0])
+ 
+/// \note MUST REMAIN UNCHANGED: \b osKernelSystemId shall be consistent in every CMSIS-RTOS.
+#define osKernelSystemId "KERNEL V1.00"   ///< RTOS identification string
+ 
+/// \note MUST REMAIN UNCHANGED: \b osFeature_xxx shall be consistent in every CMSIS-RTOS.
+#define osFeature_MainThread   1       ///< main thread      1=main can be thread, 0=not available
+#define osFeature_Pool         1       ///< Memory Pools:    1=available, 0=not available
+#define osFeature_MailQ        1       ///< Mail Queues:     1=available, 0=not available
+#define osFeature_MessageQ     1       ///< Message Queues:  1=available, 0=not available
+#define osFeature_Signals      8       ///< maximum number of Signal Flags available per thread
+#define osFeature_Semaphore    30      ///< maximum count for \ref osSemaphoreCreate function
+#define osFeature_Wait         1       ///< osWait function: 1=available, 0=not available
+#define osFeature_SysTick      1       ///< osKernelSysTick functions: 1=available, 0=not available
+ 
+#include <stdint.h>
+#include <stddef.h>
+#include "rtconfig.h"
+ 
+#ifdef  __cplusplus
+extern "C"
+{
+#endif
+ 
+ 
+// ==== Enumeration, structures, defines ====
+ 
+/// Priority used for thread control.
+/// \note MUST REMAIN UNCHANGED: \b osPriority shall be consistent in every CMSIS-RTOS.
+typedef enum  {
+  osPriorityIdle          = -3,          ///< priority: idle (lowest)
+  osPriorityLow           = -2,          ///< priority: low
+  osPriorityBelowNormal   = -1,          ///< priority: below normal
+  osPriorityNormal        =  0,          ///< priority: normal (default)
+  osPriorityAboveNormal   = +1,          ///< priority: above normal
+  osPriorityHigh          = +2,          ///< priority: high
+  osPriorityRealtime      = +3,          ///< priority: realtime (highest)
+  osPriorityError         =  0x84        ///< system cannot determine priority or thread has illegal priority
+} osPriority;
+ 
+/// Timeout value.
+/// \note MUST REMAIN UNCHANGED: \b osWaitForever shall be consistent in every CMSIS-RTOS.
+#define osWaitForever     0xFFFFFFFF     ///< wait forever timeout value
+ 
+/// Status code values returned by CMSIS-RTOS functions.
+/// \note MUST REMAIN UNCHANGED: \b osStatus shall be consistent in every CMSIS-RTOS.
+typedef enum  {
+  osOK                    =     0,       ///< function completed; no error or event occurred.
+  osEventSignal           =  0x08,       ///< function completed; signal event occurred.
+  osEventMessage          =  0x10,       ///< function completed; message event occurred.
+  osEventMail             =  0x20,       ///< function completed; mail event occurred.
+  osEventTimeout          =  0x40,       ///< function completed; timeout occurred.
+  osErrorParameter        =  0x80,       ///< parameter error: a mandatory parameter was missing or specified an incorrect object.
+  osErrorResource         =  0x81,       ///< resource not available: a specified resource was not available.
+  osErrorTimeoutResource  =  0xC1,       ///< resource not available within given time: a specified resource was not available within the timeout period.
+  osErrorISR              =  0x82,       ///< not allowed in ISR context: the function cannot be called from interrupt service routines.
+  osErrorISRRecursive     =  0x83,       ///< function called multiple times from ISR with same object.
+  osErrorPriority         =  0x84,       ///< system cannot determine priority or thread has illegal priority.
+  osErrorNoMemory         =  0x85,       ///< system is out of memory: it was impossible to allocate or reserve memory for the operation.
+  osErrorValue            =  0x86,       ///< value of a parameter is out of range.
+  osErrorOS               =  0xFF,       ///< unspecified RTOS error: run-time error but no other error message fits.
+  os_status_reserved      =  0x7FFFFFFF  ///< prevent from enum down-size compiler optimization.
+} osStatus;
+ 
+ 
+/// Timer type value for the timer definition.
+/// \note MUST REMAIN UNCHANGED: \b os_timer_type shall be consistent in every CMSIS-RTOS.
+typedef enum  {
+  osTimerOnce             =     0,       ///< one-shot timer
+  osTimerPeriodic         =     1        ///< repeating timer
+} os_timer_type;
+ 
+/// Entry point of a thread.
+/// \note MUST REMAIN UNCHANGED: \b os_pthread shall be consistent in every CMSIS-RTOS.
+typedef void (*os_pthread) (void const *argument);
+ 
+/// Entry point of a timer call back function.
+/// \note MUST REMAIN UNCHANGED: \b os_ptimer shall be consistent in every CMSIS-RTOS.
+typedef void (*os_ptimer) (void const *argument);
+ 
+// >>> the following data type definitions may shall adapted towards a specific RTOS
+ 
+/// Thread ID identifies the thread (pointer to a thread control block).
+/// \note CAN BE CHANGED: \b os_thread_cb is implementation specific in every CMSIS-RTOS.
+typedef struct os_thread_cb *osThreadId;
+ 
+/// Timer ID identifies the timer (pointer to a timer control block).
+/// \note CAN BE CHANGED: \b os_timer_cb is implementation specific in every CMSIS-RTOS.
+typedef struct os_timer_cb *osTimerId;
+ 
+/// Mutex ID identifies the mutex (pointer to a mutex control block).
+/// \note CAN BE CHANGED: \b os_mutex_cb is implementation specific in every CMSIS-RTOS.
+typedef struct os_mutex_cb *osMutexId;
+ 
+/// Semaphore ID identifies the semaphore (pointer to a semaphore control block).
+/// \note CAN BE CHANGED: \b os_semaphore_cb is implementation specific in every CMSIS-RTOS.
+typedef struct os_semaphore_cb *osSemaphoreId;
+ 
+/// Pool ID identifies the memory pool (pointer to a memory pool control block).
+/// \note CAN BE CHANGED: \b os_pool_cb is implementation specific in every CMSIS-RTOS.
+typedef struct os_pool_cb *osPoolId;
+ 
+/// Message ID identifies the message queue (pointer to a message queue control block).
+/// \note CAN BE CHANGED: \b os_messageQ_cb is implementation specific in every CMSIS-RTOS.
+typedef struct os_messageQ_cb *osMessageQId;
+ 
+/// Mail ID identifies the mail queue (pointer to a mail queue control block).
+/// \note CAN BE CHANGED: \b os_mailQ_cb is implementation specific in every CMSIS-RTOS.
+typedef struct os_mailQ_cb *osMailQId;
+ 
+ 
+/// Thread Definition structure contains startup information of a thread.
+/// \note CAN BE CHANGED: \b os_thread_def is implementation specific in every CMSIS-RTOS.
+typedef struct os_thread_def  {
+  os_pthread               pthread;    ///< start address of thread function
+  osPriority             tpriority;    ///< initial thread priority
+  uint32_t               instances;    ///< maximum number of instances of that thread function
+  uint32_t               stacksize;    ///< stack size requirements in bytes; 0 is default stack size
+} osThreadDef_t;
+ 
+/// Timer Definition structure contains timer parameters.
+/// \note CAN BE CHANGED: \b os_timer_def is implementation specific in every CMSIS-RTOS.
+typedef struct os_timer_def  {
+  os_ptimer                 ptimer;    ///< start address of a timer function
+} osTimerDef_t;
+ 
+/// Mutex Definition structure contains setup information for a mutex.
+/// \note CAN BE CHANGED: \b os_mutex_def is implementation specific in every CMSIS-RTOS.
+typedef struct os_mutex_def  {
+  uint32_t                   dummy;    ///< dummy value.
+} osMutexDef_t;
+ 
+/// Semaphore Definition structure contains setup information for a semaphore.
+/// \note CAN BE CHANGED: \b os_semaphore_def is implementation specific in every CMSIS-RTOS.
+typedef struct os_semaphore_def  {
+  uint32_t                   dummy;    ///< dummy value.
+} osSemaphoreDef_t;
+ 
+/// Definition structure for memory block allocation.
+/// \note CAN BE CHANGED: \b os_pool_def is implementation specific in every CMSIS-RTOS.
+typedef struct os_pool_def  {
+  uint32_t                 pool_sz;    ///< number of items (elements) in the pool
+  uint32_t                 item_sz;    ///< size of an item
+  void                       *pool;    ///< pointer to memory for pool
+} osPoolDef_t;
+ 
+/// Definition structure for message queue.
+/// \note CAN BE CHANGED: \b os_messageQ_def is implementation specific in every CMSIS-RTOS.
+typedef struct os_messageQ_def  {
+  uint32_t                queue_sz;    ///< number of elements in the queue
+  uint32_t                 item_sz;    ///< size of an item
+  void                       *pool;    ///< memory array for messages
+} osMessageQDef_t;
+ 
+/// Definition structure for mail queue.
+/// \note CAN BE CHANGED: \b os_mailQ_def is implementation specific in every CMSIS-RTOS.
+typedef struct os_mailQ_def  {
+  uint32_t                queue_sz;    ///< number of elements in the queue
+  uint32_t                 item_sz;    ///< size of an item
+  void                       *pool;    ///< memory array for mail
+} osMailQDef_t;
+ 
+/// Event structure contains detailed information about an event.
+/// \note MUST REMAIN UNCHANGED: \b os_event shall be consistent in every CMSIS-RTOS.
+///       However the struct may be extended at the end.
+typedef struct  {
+  osStatus                 status;     ///< status code: event or error information
+  union  {
+    uint32_t                    v;     ///< message as 32-bit value
+    void                       *p;     ///< message or mail as void pointer
+    int32_t               signals;     ///< signal flags
+  } value;                             ///< event value
+  union  {
+    osMailQId             mail_id;     ///< mail id obtained by \ref osMailCreate
+    osMessageQId       message_id;     ///< message id obtained by \ref osMessageCreate
+  } def;                               ///< event definition
+} osEvent;
+ 
+ 
+//  ==== Kernel Control Functions ====
+ 
+/// Initialize the RTOS Kernel for creating objects.
+/// \return status code that indicates the execution status of the function.
+/// \note MUST REMAIN UNCHANGED: \b osKernelInitialize shall be consistent in every CMSIS-RTOS.
+osStatus osKernelInitialize (void);
+ 
+/// Start the RTOS Kernel.
+/// \return status code that indicates the execution status of the function.
+/// \note MUST REMAIN UNCHANGED: \b osKernelStart shall be consistent in every CMSIS-RTOS.
+osStatus osKernelStart (void);
+ 
+/// Check if the RTOS kernel is already started.
+/// \note MUST REMAIN UNCHANGED: \b osKernelRunning shall be consistent in every CMSIS-RTOS.
+/// \return 0 RTOS is not started, 1 RTOS is started.
+int32_t osKernelRunning(void);
+ 
+#if (defined (osFeature_SysTick)  &&  (osFeature_SysTick != 0))     // System Timer available
+ 
+/// Get the RTOS kernel system timer counter 
+/// \note MUST REMAIN UNCHANGED: \b osKernelSysTick shall be consistent in every CMSIS-RTOS.
+/// \return RTOS kernel system timer as 32-bit value 
+uint32_t osKernelSysTick (void);
+ 
+/// The RTOS kernel system timer frequency in Hz
+/// \note Reflects the system timer setting and is typically defined in a configuration file.
+#ifdef RT_TICK_PER_SECOND
+#define osKernelSysTickFrequency RT_TICK_PER_SECOND
+#else
+#define osKernelSysTickFrequency 100000000
+#endif
+
+/// Convert a microseconds value to a RTOS kernel system timer value.
+/// \param         microsec     time value in microseconds.
+/// \return time value normalized to the \ref osKernelSysTickFrequency
+#define osKernelSysTickMicroSec(microsec) (((uint64_t)microsec * (osKernelSysTickFrequency)) / 1000000)
+ 
+#endif    // System Timer available
+ 
+//  ==== Thread Management ====
+ 
+/// Create a Thread Definition with function, priority, and stack requirements.
+/// \param         name         name of the thread function.
+/// \param         priority     initial priority of the thread function.
+/// \param         instances    number of possible thread instances.
+/// \param         stacksz      stack size (in bytes) requirements for the thread function.
+/// \note CAN BE CHANGED: The parameters to \b osThreadDef shall be consistent but the
+///       macro body is implementation specific in every CMSIS-RTOS.
+#if defined (osObjectsExternal)  // object is external
+#define osThreadDef(name, priority, instances, stacksz)  \
+extern const osThreadDef_t os_thread_def_##name
+#else                            // define the object
+#define osThreadDef(name, priority, instances, stacksz)  \
+const osThreadDef_t os_thread_def_##name = \
+{ (name), (priority), (instances), (stacksz)  }
+#endif
+ 
+/// Access a Thread definition.
+/// \param         name          name of the thread definition object.
+/// \note CAN BE CHANGED: The parameter to \b osThread shall be consistent but the
+///       macro body is implementation specific in every CMSIS-RTOS.
+#define osThread(name)  \
+&os_thread_def_##name
+ 
+/// Create a thread and add it to Active Threads and set it to state READY.
+/// \param[in]     thread_def    thread definition referenced with \ref osThread.
+/// \param[in]     argument      pointer that is passed to the thread function as start argument.
+/// \return thread ID for reference by other functions or NULL in case of error.
+/// \note MUST REMAIN UNCHANGED: \b osThreadCreate shall be consistent in every CMSIS-RTOS.
+osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument);
+ 
+/// Return the thread ID of the current running thread.
+/// \return thread ID for reference by other functions or NULL in case of error.
+/// \note MUST REMAIN UNCHANGED: \b osThreadGetId shall be consistent in every CMSIS-RTOS.
+osThreadId osThreadGetId (void);
+ 
+/// Terminate execution of a thread and remove it from Active Threads.
+/// \param[in]     thread_id   thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
+/// \return status code that indicates the execution status of the function.
+/// \note MUST REMAIN UNCHANGED: \b osThreadTerminate shall be consistent in every CMSIS-RTOS.
+osStatus osThreadTerminate (osThreadId thread_id);
+ 
+/// Pass control to next thread that is in state \b READY.
+/// \return status code that indicates the execution status of the function.
+/// \note MUST REMAIN UNCHANGED: \b osThreadYield shall be consistent in every CMSIS-RTOS.
+osStatus osThreadYield (void);
+ 
+/// Change priority of an active thread.
+/// \param[in]     thread_id     thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
+/// \param[in]     priority      new priority value for the thread function.
+/// \return status code that indicates the execution status of the function.
+/// \note MUST REMAIN UNCHANGED: \b osThreadSetPriority shall be consistent in every CMSIS-RTOS.
+osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority);
+ 
+/// Get current priority of an active thread.
+/// \param[in]     thread_id     thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
+/// \return current priority value of the thread function.
+/// \note MUST REMAIN UNCHANGED: \b osThreadGetPriority shall be consistent in every CMSIS-RTOS.
+osPriority osThreadGetPriority (osThreadId thread_id);
+ 
+ 
+//  ==== Generic Wait Functions ====
+ 
+/// Wait for Timeout (Time Delay).
+/// \param[in]     millisec      \ref CMSIS_RTOS_TimeOutValue "time delay" value
+/// \return status code that indicates the execution status of the function.
+osStatus osDelay (uint32_t millisec);
+ 
+#if (defined (osFeature_Wait)  &&  (osFeature_Wait != 0))     // Generic Wait available
+ 
+/// Wait for Signal, Message, Mail, or Timeout.
+/// \param[in] millisec          \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out
+/// \return event that contains signal, message, or mail information or error code.
+/// \note MUST REMAIN UNCHANGED: \b osWait shall be consistent in every CMSIS-RTOS.
+osEvent osWait (uint32_t millisec);
+ 
+#endif  // Generic Wait available
+ 
+ 
+//  ==== Timer Management Functions ====
+/// Define a Timer object.
+/// \param         name          name of the timer object.
+/// \param         function      name of the timer call back function.
+/// \note CAN BE CHANGED: The parameter to \b osTimerDef shall be consistent but the
+///       macro body is implementation specific in every CMSIS-RTOS.
+#if defined (osObjectsExternal)  // object is external
+#define osTimerDef(name, function)  \
+extern const osTimerDef_t os_timer_def_##name
+#else                            // define the object
+#define osTimerDef(name, function)  \
+const osTimerDef_t os_timer_def_##name = \
+{ (function) }
+#endif
+ 
+/// Access a Timer definition.
+/// \param         name          name of the timer object.
+/// \note CAN BE CHANGED: The parameter to \b osTimer shall be consistent but the
+///       macro body is implementation specific in every CMSIS-RTOS.
+#define osTimer(name) \
+&os_timer_def_##name
+ 
+/// Create a timer.
+/// \param[in]     timer_def     timer object referenced with \ref osTimer.
+/// \param[in]     type          osTimerOnce for one-shot or osTimerPeriodic for periodic behavior.
+/// \param[in]     argument      argument to the timer call back function.
+/// \return timer ID for reference by other functions or NULL in case of error.
+/// \note MUST REMAIN UNCHANGED: \b osTimerCreate shall be consistent in every CMSIS-RTOS.
+osTimerId osTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void *argument);
+ 
+/// Start or restart a timer.
+/// \param[in]     timer_id      timer ID obtained by \ref osTimerCreate.
+/// \param[in]     millisec      \ref CMSIS_RTOS_TimeOutValue "time delay" value of the timer.
+/// \return status code that indicates the execution status of the function.
+/// \note MUST REMAIN UNCHANGED: \b osTimerStart shall be consistent in every CMSIS-RTOS.
+osStatus osTimerStart (osTimerId timer_id, uint32_t millisec);
+ 
+/// Stop the timer.
+/// \param[in]     timer_id      timer ID obtained by \ref osTimerCreate.
+/// \return status code that indicates the execution status of the function.
+/// \note MUST REMAIN UNCHANGED: \b osTimerStop shall be consistent in every CMSIS-RTOS.
+osStatus osTimerStop (osTimerId timer_id);
+ 
+/// Delete a timer that was created by \ref osTimerCreate.
+/// \param[in]     timer_id      timer ID obtained by \ref osTimerCreate.
+/// \return status code that indicates the execution status of the function.
+/// \note MUST REMAIN UNCHANGED: \b osTimerDelete shall be consistent in every CMSIS-RTOS.
+osStatus osTimerDelete (osTimerId timer_id);
+ 
+ 
+//  ==== Signal Management ====
+ 
+/// Set the specified Signal Flags of an active thread.
+/// \param[in]     thread_id     thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
+/// \param[in]     signals       specifies the signal flags of the thread that should be set.
+/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
+/// \note MUST REMAIN UNCHANGED: \b osSignalSet shall be consistent in every CMSIS-RTOS.
+int32_t osSignalSet (osThreadId thread_id, int32_t signals);
+ 
+/// Clear the specified Signal Flags of an active thread.
+/// \param[in]     thread_id     thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
+/// \param[in]     signals       specifies the signal flags of the thread that shall be cleared.
+/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters or call from ISR.
+/// \note MUST REMAIN UNCHANGED: \b osSignalClear shall be consistent in every CMSIS-RTOS.
+int32_t osSignalClear (osThreadId thread_id, int32_t signals);
+ 
+/// Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread.
+/// \param[in]     signals       wait until all specified signal flags set or 0 for any single signal flag.
+/// \param[in]     millisec      \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
+/// \return event flag information or error code.
+/// \note MUST REMAIN UNCHANGED: \b osSignalWait shall be consistent in every CMSIS-RTOS.
+osEvent osSignalWait (int32_t signals, uint32_t millisec);
+ 
+ 
+//  ==== Mutex Management ====
+ 
+/// Define a Mutex.
+/// \param         name          name of the mutex object.
+/// \note CAN BE CHANGED: The parameter to \b osMutexDef shall be consistent but the
+///       macro body is implementation specific in every CMSIS-RTOS.
+#if defined (osObjectsExternal)  // object is external
+#define osMutexDef(name)  \
+extern const osMutexDef_t os_mutex_def_##name
+#else                            // define the object
+#define osMutexDef(name)  \
+const osMutexDef_t os_mutex_def_##name = { 0 }
+#endif
+ 
+/// Access a Mutex definition.
+/// \param         name          name of the mutex object.
+/// \note CAN BE CHANGED: The parameter to \b osMutex shall be consistent but the
+///       macro body is implementation specific in every CMSIS-RTOS.
+#define osMutex(name)  \
+&os_mutex_def_##name
+ 
+/// Create and Initialize a Mutex object.
+/// \param[in]     mutex_def     mutex definition referenced with \ref osMutex.
+/// \return mutex ID for reference by other functions or NULL in case of error.
+/// \note MUST REMAIN UNCHANGED: \b osMutexCreate shall be consistent in every CMSIS-RTOS.
+osMutexId osMutexCreate (const osMutexDef_t *mutex_def);
+ 
+/// Wait until a Mutex becomes available.
+/// \param[in]     mutex_id      mutex ID obtained by \ref osMutexCreate.
+/// \param[in]     millisec      \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
+/// \return status code that indicates the execution status of the function.
+/// \note MUST REMAIN UNCHANGED: \b osMutexWait shall be consistent in every CMSIS-RTOS.
+osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec);
+ 
+/// Release a Mutex that was obtained by \ref osMutexWait.
+/// \param[in]     mutex_id      mutex ID obtained by \ref osMutexCreate.
+/// \return status code that indicates the execution status of the function.
+/// \note MUST REMAIN UNCHANGED: \b osMutexRelease shall be consistent in every CMSIS-RTOS.
+osStatus osMutexRelease (osMutexId mutex_id);
+ 
+/// Delete a Mutex that was created by \ref osMutexCreate.
+/// \param[in]     mutex_id      mutex ID obtained by \ref osMutexCreate.
+/// \return status code that indicates the execution status of the function.
+/// \note MUST REMAIN UNCHANGED: \b osMutexDelete shall be consistent in every CMSIS-RTOS.
+osStatus osMutexDelete (osMutexId mutex_id);
+ 
+ 
+//  ==== Semaphore Management Functions ====
+ 
+#if (defined (osFeature_Semaphore)  &&  (osFeature_Semaphore != 0))     // Semaphore available
+ 
+/// Define a Semaphore object.
+/// \param         name          name of the semaphore object.
+/// \note CAN BE CHANGED: The parameter to \b osSemaphoreDef shall be consistent but the
+///       macro body is implementation specific in every CMSIS-RTOS.
+#if defined (osObjectsExternal)  // object is external
+#define osSemaphoreDef(name)  \
+extern const osSemaphoreDef_t os_semaphore_def_##name
+#else                            // define the object
+#define osSemaphoreDef(name)  \
+const osSemaphoreDef_t os_semaphore_def_##name = { 0 }
+#endif
+ 
+/// Access a Semaphore definition.
+/// \param         name          name of the semaphore object.
+/// \note CAN BE CHANGED: The parameter to \b osSemaphore shall be consistent but the
+///       macro body is implementation specific in every CMSIS-RTOS.
+#define osSemaphore(name)  \
+&os_semaphore_def_##name
+ 
+/// Create and Initialize a Semaphore object used for managing resources.
+/// \param[in]     semaphore_def semaphore definition referenced with \ref osSemaphore.
+/// \param[in]     count         number of available resources.
+/// \return semaphore ID for reference by other functions or NULL in case of error.
+/// \note MUST REMAIN UNCHANGED: \b osSemaphoreCreate shall be consistent in every CMSIS-RTOS.
+osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count);
+ 
+/// Wait until a Semaphore token becomes available.
+/// \param[in]     semaphore_id  semaphore object referenced with \ref osSemaphoreCreate.
+/// \param[in]     millisec      \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
+/// \return number of available tokens, or -1 in case of incorrect parameters.
+/// \note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS.
+int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec);
+ 
+/// Release a Semaphore token.
+/// \param[in]     semaphore_id  semaphore object referenced with \ref osSemaphoreCreate.
+/// \return status code that indicates the execution status of the function.
+/// \note MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS.
+osStatus osSemaphoreRelease (osSemaphoreId semaphore_id);
+ 
+/// Delete a Semaphore that was created by \ref osSemaphoreCreate.
+/// \param[in]     semaphore_id  semaphore object referenced with \ref osSemaphoreCreate.
+/// \return status code that indicates the execution status of the function.
+/// \note MUST REMAIN UNCHANGED: \b osSemaphoreDelete shall be consistent in every CMSIS-RTOS.
+osStatus osSemaphoreDelete (osSemaphoreId semaphore_id);
+ 
+#endif     // Semaphore available
+ 
+ 
+//  ==== Memory Pool Management Functions ====
+ 
+#if (defined (osFeature_Pool)  &&  (osFeature_Pool != 0))  // Memory Pool Management available
+ 
+/// \brief Define a Memory Pool.
+/// \param         name          name of the memory pool.
+/// \param         no            maximum number of blocks (objects) in the memory pool.
+/// \param         type          data type of a single block (object).
+/// \note CAN BE CHANGED: The parameter to \b osPoolDef shall be consistent but the
+///       macro body is implementation specific in every CMSIS-RTOS.
+#if defined (osObjectsExternal)  // object is external
+#define osPoolDef(name, no, type)   \
+extern const osPoolDef_t os_pool_def_##name
+#else                            // define the object
+#define osPoolDef(name, no, type)   \
+const osPoolDef_t os_pool_def_##name = \
+{ (no), sizeof(type), NULL }
+#endif
+ 
+/// \brief Access a Memory Pool definition.
+/// \param         name          name of the memory pool
+/// \note CAN BE CHANGED: The parameter to \b osPool shall be consistent but the
+///       macro body is implementation specific in every CMSIS-RTOS.
+#define osPool(name) \
+&os_pool_def_##name
+ 
+/// Create and Initialize a memory pool.
+/// \param[in]     pool_def      memory pool definition referenced with \ref osPool.
+/// \return memory pool ID for reference by other functions or NULL in case of error.
+/// \note MUST REMAIN UNCHANGED: \b osPoolCreate shall be consistent in every CMSIS-RTOS.
+osPoolId osPoolCreate (const osPoolDef_t *pool_def);
+ 
+/// Allocate a memory block from a memory pool.
+/// \param[in]     pool_id       memory pool ID obtain referenced with \ref osPoolCreate.
+/// \return address of the allocated memory block or NULL in case of no memory available.
+/// \note MUST REMAIN UNCHANGED: \b osPoolAlloc shall be consistent in every CMSIS-RTOS.
+void *osPoolAlloc (osPoolId pool_id);
+ 
+/// Allocate a memory block from a memory pool and set memory block to zero.
+/// \param[in]     pool_id       memory pool ID obtain referenced with \ref osPoolCreate.
+/// \return address of the allocated memory block or NULL in case of no memory available.
+/// \note MUST REMAIN UNCHANGED: \b osPoolCAlloc shall be consistent in every CMSIS-RTOS.
+void *osPoolCAlloc (osPoolId pool_id);
+ 
+/// Return an allocated memory block back to a specific memory pool.
+/// \param[in]     pool_id       memory pool ID obtain referenced with \ref osPoolCreate.
+/// \param[in]     block         address of the allocated memory block that is returned to the memory pool.
+/// \return status code that indicates the execution status of the function.
+/// \note MUST REMAIN UNCHANGED: \b osPoolFree shall be consistent in every CMSIS-RTOS.
+osStatus osPoolFree (osPoolId pool_id, void *block);
+ 
+#endif   // Memory Pool Management available
+ 
+ 
+//  ==== Message Queue Management Functions ====
+ 
+#if (defined (osFeature_MessageQ)  &&  (osFeature_MessageQ != 0))     // Message Queues available
+ 
+/// \brief Create a Message Queue Definition.
+/// \param         name          name of the queue.
+/// \param         queue_sz      maximum number of messages in the queue.
+/// \param         type          data type of a single message element (for debugger).
+/// \note CAN BE CHANGED: The parameter to \b osMessageQDef shall be consistent but the
+///       macro body is implementation specific in every CMSIS-RTOS.
+#if defined (osObjectsExternal)  // object is external
+#define osMessageQDef(name, queue_sz, type)   \
+extern const osMessageQDef_t os_messageQ_def_##name
+#else                            // define the object
+#define osMessageQDef(name, queue_sz, type)   \
+const osMessageQDef_t os_messageQ_def_##name = \
+{ (queue_sz), sizeof (type)  }
+#endif
+ 
+/// \brief Access a Message Queue Definition.
+/// \param         name          name of the queue
+/// \note CAN BE CHANGED: The parameter to \b osMessageQ shall be consistent but the
+///       macro body is implementation specific in every CMSIS-RTOS.
+#define osMessageQ(name) \
+&os_messageQ_def_##name
+ 
+/// Create and Initialize a Message Queue.
+/// \param[in]     queue_def     queue definition referenced with \ref osMessageQ.
+/// \param[in]     thread_id     thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL.
+/// \return message queue ID for reference by other functions or NULL in case of error.
+/// \note MUST REMAIN UNCHANGED: \b osMessageCreate shall be consistent in every CMSIS-RTOS.
+osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id);
+ 
+/// Put a Message to a Queue.
+/// \param[in]     queue_id      message queue ID obtained with \ref osMessageCreate.
+/// \param[in]     info          message information.
+/// \param[in]     millisec      \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
+/// \return status code that indicates the execution status of the function.
+/// \note MUST REMAIN UNCHANGED: \b osMessagePut shall be consistent in every CMSIS-RTOS.
+osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec);
+ 
+/// Get a Message or Wait for a Message from a Queue.
+/// \param[in]     queue_id      message queue ID obtained with \ref osMessageCreate.
+/// \param[in]     millisec      \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
+/// \return event information that includes status code.
+/// \note MUST REMAIN UNCHANGED: \b osMessageGet shall be consistent in every CMSIS-RTOS.
+osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec);
+ 
+#endif     // Message Queues available
+ 
+ 
+//  ==== Mail Queue Management Functions ====
+ 
+#if (defined (osFeature_MailQ)  &&  (osFeature_MailQ != 0))     // Mail Queues available
+ 
+/// \brief Create a Mail Queue Definition.
+/// \param         name          name of the queue
+/// \param         queue_sz      maximum number of messages in queue
+/// \param         type          data type of a single message element
+/// \note CAN BE CHANGED: The parameter to \b osMailQDef shall be consistent but the
+///       macro body is implementation specific in every CMSIS-RTOS.
+#if defined (osObjectsExternal)  // object is external
+#define osMailQDef(name, queue_sz, type) \
+extern const osMailQDef_t os_mailQ_def_##name
+#else                            // define the object
+#define osMailQDef(name, queue_sz, type) \
+const osMailQDef_t os_mailQ_def_##name =  \
+{ (queue_sz), sizeof (type) }
+#endif
+ 
+/// \brief Access a Mail Queue Definition.
+/// \param         name          name of the queue
+/// \note CAN BE CHANGED: The parameter to \b osMailQ shall be consistent but the
+///       macro body is implementation specific in every CMSIS-RTOS.
+#define osMailQ(name)  \
+&os_mailQ_def_##name
+ 
+/// Create and Initialize mail queue.
+/// \param[in]     queue_def     reference to the mail queue definition obtain with \ref osMailQ
+/// \param[in]     thread_id     thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL.
+/// \return mail queue ID for reference by other functions or NULL in case of error.
+/// \note MUST REMAIN UNCHANGED: \b osMailCreate shall be consistent in every CMSIS-RTOS.
+osMailQId osMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id);
+ 
+/// Allocate a memory block from a mail.
+/// \param[in]     queue_id      mail queue ID obtained with \ref osMailCreate.
+/// \param[in]     millisec      \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out
+/// \return pointer to memory block that can be filled with mail or NULL in case of error.
+/// \note MUST REMAIN UNCHANGED: \b osMailAlloc shall be consistent in every CMSIS-RTOS.
+void *osMailAlloc (osMailQId queue_id, uint32_t millisec);
+ 
+/// Allocate a memory block from a mail and set memory block to zero.
+/// \param[in]     queue_id      mail queue ID obtained with \ref osMailCreate.
+/// \param[in]     millisec      \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out
+/// \return pointer to memory block that can be filled with mail or NULL in case of error.
+/// \note MUST REMAIN UNCHANGED: \b osMailCAlloc shall be consistent in every CMSIS-RTOS.
+void *osMailCAlloc (osMailQId queue_id, uint32_t millisec);
+ 
+/// Put a mail to a queue.
+/// \param[in]     queue_id      mail queue ID obtained with \ref osMailCreate.
+/// \param[in]     mail          memory block previously allocated with \ref osMailAlloc or \ref osMailCAlloc.
+/// \return status code that indicates the execution status of the function.
+/// \note MUST REMAIN UNCHANGED: \b osMailPut shall be consistent in every CMSIS-RTOS.
+osStatus osMailPut (osMailQId queue_id, void *mail);
+ 
+/// Get a mail from a queue.
+/// \param[in]     queue_id      mail queue ID obtained with \ref osMailCreate.
+/// \param[in]     millisec      \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out
+/// \return event that contains mail information or error code.
+/// \note MUST REMAIN UNCHANGED: \b osMailGet shall be consistent in every CMSIS-RTOS.
+osEvent osMailGet (osMailQId queue_id, uint32_t millisec);
+ 
+/// Free a memory block from a mail.
+/// \param[in]     queue_id      mail queue ID obtained with \ref osMailCreate.
+/// \param[in]     mail          pointer to the memory block that was obtained with \ref osMailGet.
+/// \return status code that indicates the execution status of the function.
+/// \note MUST REMAIN UNCHANGED: \b osMailFree shall be consistent in every CMSIS-RTOS.
+osStatus osMailFree (osMailQId queue_id, void *mail);
+ 
+#endif  // Mail Queues available
+ 
+ 
+#ifdef  __cplusplus
+}
+#endif
+ 
+#endif  // _CMSIS_OS_H

+ 1558 - 0
cmsis_rtthread.c

@@ -0,0 +1,1558 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-04-27     tyustli      The first version
+ */
+
+#include <rtthread.h>
+#include "cmsis_os.h"
+
+#define DEFAULT_TICK (5)
+#define DEFAULT_THREAD_STACK_SIZE (512)
+
+#define CMSIS_MEM_ALLOC(_size) rt_malloc(_size)
+#define CMSIS_MEM_FREE(_ptr) rt_free(_ptr)
+
+/* cmsis to rt-thread priority map */
+static const rt_uint8_t priorityArrayMap[7] =
+    {
+        RT_THREAD_PRIORITY_MAX - 1,
+        RT_THREAD_PRIORITY_MAX - 1 - (RT_THREAD_PRIORITY_MAX / 6),
+        RT_THREAD_PRIORITY_MAX - 1 - (RT_THREAD_PRIORITY_MAX / 3),
+        RT_THREAD_PRIORITY_MAX / 2,
+        RT_THREAD_PRIORITY_MAX / 3,
+        RT_THREAD_PRIORITY_MAX / 6,
+        0,
+};
+
+/* Convert from CMSIS type osPriority to RT-Thread priority number */
+static rt_uint8_t makeRttPriority(osPriority priority)
+{
+    rt_uint8_t rttPriority = RT_THREAD_PRIORITY_MAX;
+
+    switch (priority)
+    {
+    case osPriorityIdle:
+        rttPriority = priorityArrayMap[0];
+        break;
+    case osPriorityLow:
+        rttPriority = priorityArrayMap[1];
+        break;
+    case osPriorityBelowNormal:
+        rttPriority = priorityArrayMap[2];
+        break;
+    case osPriorityNormal:
+        rttPriority = priorityArrayMap[3];
+        break;
+    case osPriorityAboveNormal:
+        rttPriority = priorityArrayMap[4];
+        break;
+    case osPriorityHigh:
+        rttPriority = priorityArrayMap[5];
+        break;
+    case osPriorityRealtime:
+        rttPriority = priorityArrayMap[6];
+        break;
+    default:
+        break;
+    }
+
+    return rttPriority;
+}
+
+/* Convert from RT-Thread priority number to CMSIS type osPriority */
+static osPriority makeCmsisPriority(rt_uint8_t rttPriority)
+{
+    osPriority priority = osPriorityError;
+
+    if (rttPriority == priorityArrayMap[0])
+        priority = osPriorityIdle;
+    else if (rttPriority == priorityArrayMap[1])
+        priority = osPriorityLow;
+    else if (rttPriority == priorityArrayMap[2])
+        priority = osPriorityBelowNormal;
+    else if (rttPriority == priorityArrayMap[3])
+        priority = osPriorityNormal;
+    else if (rttPriority == priorityArrayMap[4])
+        priority = osPriorityAboveNormal;
+    else if (rttPriority == priorityArrayMap[5])
+        priority = osPriorityHigh;
+    else if (rttPriority == priorityArrayMap[6])
+        rttPriority = osPriorityRealtime;
+
+    return priority;
+}
+
+/* Determine whether we are in thread mode or handler mode. */
+static int inHandlerMode(void)
+{
+    return rt_interrupt_get_nest() != 0;
+}
+
+/*********************** Kernel Control Functions *****************************/
+/**
+ * @brief  Initialize the RTOS Kernel for creating objects.
+ * @retval status code that indicates the execution status of the function.
+ * @note   MUST REMAIN UNCHANGED: \b osKernelInitialize shall be consistent in every CMSIS-RTOS.
+ */
+osStatus osKernelInitialize(void)
+{
+    return osOK;
+}
+
+/**
+ * @brief  Start the RTOS Kernel with executing the specified thread.
+ * @param  thread_def    thread definition referenced with \ref osThread.
+ * @param  argument      pointer that is passed to the thread function as start argument.
+ * @retval status code that indicates the execution status of the function
+ * @note   MUST REMAIN UNCHANGED: \b osKernelStart shall be consistent in every CMSIS-RTOS.
+ */
+osStatus osKernelStart(void)
+{
+    /* Cannot be called from Interrupt Service Routines */
+    if (inHandlerMode())
+        return osErrorISR;
+
+    return osOK;
+}
+
+/**
+ * @brief  Check if the RTOS kernel is already started
+ * @param  None
+ * @retval (0) RTOS is not started
+ *         (1) RTOS is started
+ * @note  MUST REMAIN UNCHANGED: \b osKernelRunning shall be consistent in every CMSIS-RTOS.
+ */
+int32_t osKernelRunning(void)
+{
+    if (rt_thread_self())
+        return 1;
+    else
+        return 0;
+}
+
+/**
+ * @brief  Get the value of the Kernel SysTick timer
+ * @param  None
+ * @retval None
+ * @note   MUST REMAIN UNCHANGED: \b osKernelSysTick shall be consistent in every CMSIS-RTOS.
+ */
+uint32_t osKernelSysTick(void)
+{
+    /* Cannot be called from Interrupt Service Routines */
+    if (inHandlerMode())
+        return 0;
+
+    return rt_tick_get();
+}
+
+/*********************** Thread Management *****************************/
+typedef struct os_thread_cb
+{
+    rt_thread_t thread_id;
+    rt_event_t event_id;
+} os_thread_cb_t;
+
+static void thread_cleanup(struct rt_thread *tid)
+{
+    if (tid->user_data)
+    {
+        /* delete event */
+        rt_event_delete(((struct os_thread_cb *)(tid->user_data))->event_id);
+        /* free mem */
+        CMSIS_MEM_FREE((void *)(tid->user_data));
+        tid->user_data = RT_NULL;
+    }
+}
+/**
+ * @brief  Create a thread and add it to Active Threads and set it to state READY.
+ * @param  thread_def    thread definition referenced with \ref osThread.
+ * @param  argument      pointer that is passed to the thread function as start argument.
+ * @retval thread ID for reference by other functions or NULL in case of error.
+ * @note   MUST REMAIN UNCHANGED: \b osThreadCreate shall be consistent in every CMSIS-RTOS.
+ */
+osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *argument)
+{
+    static rt_uint8_t thread_number = 0;
+    char name[RT_NAME_MAX];
+    rt_uint8_t rttPriority = 0;
+    rt_uint32_t stack_size = 0;
+    void (*entry)(void *parameter);
+    os_thread_cb_t *thread_cb = RT_NULL;
+
+    /* Cannot be called from Interrupt Service Routines */
+    if (inHandlerMode())
+        goto thread_create_failed;
+
+    if (RT_NULL == thread_def || RT_NULL == thread_def->pthread)
+        goto thread_create_failed;
+
+    rt_snprintf(name, sizeof(name), "thread%02d", thread_number++); /* thread name */
+    rttPriority = makeRttPriority(thread_def->tpriority);           /* thread priority */
+    entry = (void (*)(void *parameter))(thread_def->pthread);       /* thread entry */
+
+    stack_size = thread_def->stacksize; /* thread stack size */
+    if (0 == thread_def->stacksize)
+        stack_size = DEFAULT_THREAD_STACK_SIZE;
+
+    thread_cb = (void *)CMSIS_MEM_ALLOC(sizeof(struct os_thread_cb));
+    if (RT_NULL == thread_cb)
+        goto thread_create_failed;
+
+    thread_cb->thread_id = rt_thread_create(name,
+                                            entry,
+                                            argument,
+                                            stack_size,
+                                            rttPriority,
+                                            DEFAULT_TICK);
+    thread_cb->event_id = rt_event_create(name, RT_IPC_FLAG_PRIO);
+
+    if (RT_NULL == thread_cb->thread_id || RT_NULL == thread_cb->event_id)
+        goto thread_create_failed;
+
+    thread_cb->thread_id->user_data = (rt_ubase_t)thread_cb;
+    thread_cb->thread_id->cleanup = thread_cleanup; /* when thread done. event and mem must be free */
+
+    /* start thread */
+    rt_thread_startup(thread_cb->thread_id);
+
+    return thread_cb;
+thread_create_failed:
+    rt_kprintf("CMSIS RTOS1 %s failed\r\n", __func__);
+    if (thread_cb)
+    {
+        if (thread_cb->thread_id)
+            rt_thread_delete(thread_cb->thread_id);
+        if (thread_cb->event_id)
+            rt_event_delete(thread_cb->event_id);
+        CMSIS_MEM_FREE(thread_cb);
+    }
+    return RT_NULL;
+}
+
+osStatus osThreadTerminate(osThreadId thread_id)
+{
+    rt_err_t result;
+    osStatus status;
+    rt_thread_t thread;
+
+    /* thread_id is incorrect */
+    if (RT_NULL == thread_id)
+    {
+        status = osErrorParameter;
+        goto thread_terminate_error;
+    }
+
+    thread = thread_id->thread_id;
+    /* thread_id refers to a thread that is not an active thread. thread maybe done or has terminated*/
+    if (rt_object_get_type((rt_object_t)thread) != RT_Object_Class_Thread)
+    {
+        status = osErrorResource;
+        goto thread_terminate_error;
+    }
+
+    /* Cannot be called from Interrupt Service Routines */
+    if (inHandlerMode())
+    {
+        status = osErrorISR;
+        goto thread_terminate_error;
+    }
+
+    result = rt_thread_control(thread, RT_THREAD_CTRL_CLOSE, RT_NULL);
+    if (result != RT_EOK)
+    {
+        status = osErrorOS;
+        goto thread_terminate_error;
+    }
+
+    return osOK;
+thread_terminate_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
+    return status;
+}
+
+/**
+ * @brief  Pass control to next thread that is in state \b READY.
+ * @retval status code that indicates the execution status of the function.
+ * @note   MUST REMAIN UNCHANGED: \b osThreadYield shall be consistent in every CMSIS-RTOS.
+ */
+osStatus osThreadYield(void)
+{
+    /* Cannot be called from Interrupt Service Routines */
+    if (inHandlerMode())
+        return osErrorISR;
+
+    rt_thread_yield();
+
+    return osOK;
+}
+
+/**
+ * @brief  Return the thread ID of the current running thread.
+ * @retval thread ID for reference by other functions or NULL in case of error.
+ * @note   MUST REMAIN UNCHANGED: \b osThreadGetId shall be consistent in every CMSIS-RTOS.
+ */
+osThreadId osThreadGetId(void)
+{
+    rt_thread_t thread;
+
+    /* Cannot be called from Interrupt Service Routines */
+    if (inHandlerMode())
+        return RT_NULL;
+
+    thread = rt_thread_self();
+
+    return (osThreadId)(thread->user_data);
+}
+
+/**
+ * @brief   Change priority of an active thread.
+ * @param   thread_id     thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
+ * @param   priority      new priority value for the thread function.
+ * @retval  status code that indicates the execution status of the function.
+ * @note   MUST REMAIN UNCHANGED: \b osThreadSetPriority shall be consistent in every CMSIS-RTOS.
+ */
+osStatus osThreadSetPriority(osThreadId thread_id, osPriority priority)
+{
+    osStatus status;
+    rt_err_t result;
+    rt_uint8_t rttPriority = 0;
+    rt_thread_t thread;
+
+    /* thread_id is incorrect */
+    if (RT_NULL == thread_id)
+    {
+        status = osErrorParameter;
+        goto set_pri_error;
+    }
+
+    /* incorrect priority value */
+    if (osPriorityError == priority)
+    {
+        status = osErrorValue;
+        goto set_pri_error;
+    }
+
+    thread = thread_id->thread_id;
+    /* thread_id refers to a thread that is not an active thread. thread maybe done or has terminated*/
+    if (rt_object_get_type((rt_object_t)thread) != RT_Object_Class_Thread)
+    {
+        status = osErrorResource;
+        goto set_pri_error;
+    }
+
+    /* Cannot be called from Interrupt Service Routines */
+    if (inHandlerMode())
+    {
+        status = osErrorISR;
+        goto set_pri_error;
+    }
+
+    rttPriority = makeRttPriority(priority);
+    result = rt_thread_control(thread, RT_THREAD_CTRL_CHANGE_PRIORITY, &rttPriority);
+    if (result != RT_EOK)
+    {
+        status = osErrorOS;
+        goto set_pri_error;
+    }
+
+    return osOK;
+set_pri_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
+    return status;
+}
+
+/**
+ * @brief   Get current priority of an active thread.
+ * @param   thread_id     thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
+ * @retval  current priority value of the thread function.
+ * @note   MUST REMAIN UNCHANGED: \b osThreadGetPriority shall be consistent in every CMSIS-RTOS.
+ */
+osPriority osThreadGetPriority(osThreadId thread_id)
+{
+    rt_thread_t thread;
+
+    if (RT_NULL == thread_id)
+        goto get_pri_error;
+
+    thread = thread_id->thread_id;
+    /* thread_id refers to a thread that is not an active thread. thread maybe done or has terminated*/
+    if (rt_object_get_type((rt_object_t)thread) != RT_Object_Class_Thread)
+        goto get_pri_error;
+
+    /* Cannot be called from Interrupt Service Routines */
+    if (inHandlerMode())
+        goto get_pri_error;
+
+    return makeCmsisPriority(thread->current_priority);
+get_pri_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__);
+    return osPriorityError;
+}
+
+/*********************** Generic Wait Functions *******************************/
+/**
+ * @brief   Wait for Timeout (Time Delay)
+ * @param   millisec      time delay value
+ * @retval  status code that indicates the execution status of the function.
+ */
+osStatus osDelay(uint32_t millisec)
+{
+    /* Cannot be called from Interrupt Service Routines */
+    if (inHandlerMode())
+        return osErrorISR;
+
+    rt_thread_mdelay(millisec);
+
+    return osOK;
+}
+
+#if (defined(osFeature_Wait) && (osFeature_Wait != 0)) /* Generic Wait available */
+/**
+ * @brief  Wait for Signal, Message, Mail, or Timeout
+ * @param   millisec  timeout value or 0 in case of no time-out
+ * @retval  event that contains signal, message, or mail information or error code.
+ * @note   MUST REMAIN UNCHANGED: \b osWait shall be consistent in every CMSIS-RTOS.
+ */
+osEvent osWait(uint32_t millisec);
+
+#endif /* Generic Wait available */
+
+/***********************  Timer Management Functions ***************************/
+/**
+ * @brief  Create a timer.
+ * @param  timer_def     timer object referenced with \ref osTimer.
+ * @param  type          osTimerOnce for one-shot or osTimerPeriodic for periodic behavior.
+ * @param  argument      argument to the timer call back function.
+ * @retval  timer ID for reference by other functions or NULL in case of error.
+ * @note   MUST REMAIN UNCHANGED: \b osTimerCreate shall be consistent in every CMSIS-RTOS.
+ */
+osTimerId osTimerCreate(const osTimerDef_t *timer_def, os_timer_type type, void *argument)
+{
+    rt_timer_t timer;
+    static rt_uint16_t timer_number = 0U;
+    rt_uint8_t flag = RT_TIMER_FLAG_SOFT_TIMER;
+    char name[RT_NAME_MAX];
+    void (*timeout_callback)(void *parameter);
+
+    /* Cannot be called from Interrupt Service Routines */
+    if (inHandlerMode())
+        goto timer_create_error;
+
+    if (RT_NULL == timer_def || RT_NULL == timer_def->ptimer)
+        goto timer_create_error;
+
+    if (osTimerPeriodic == type)
+        flag |= RT_TIMER_FLAG_PERIODIC;
+    else if (osTimerOnce == type)
+        flag |= RT_TIMER_FLAG_ONE_SHOT;
+    else
+        goto timer_create_error;
+
+    rt_snprintf(name, sizeof(name), "timer%02d", timer_number++);      /* timer name */
+    timeout_callback = (void (*)(void *parameter))(timer_def->ptimer); /* timeout callback */
+
+    timer = rt_timer_create(name,
+                            timeout_callback,
+                            argument,
+                            0,
+                            flag);
+    if (RT_NULL == timer)
+        goto timer_create_error;
+
+    return (osTimerId)timer;
+
+timer_create_error:
+    rt_kprintf("CMSIS RTOS1 %s failed\r\n", __func__);
+    return RT_NULL;
+}
+
+/**
+ * @brief  Start or restart a timer.
+ * @param  timer_id      timer ID obtained by \ref osTimerCreate.
+ * @param  millisec      time delay value of the timer.
+ * @retval  status code that indicates the execution status of the function
+ * @note   MUST REMAIN UNCHANGED: \b osTimerStart shall be consistent in every CMSIS-RTOS.
+ */
+osStatus osTimerStart(osTimerId timer_id, uint32_t millisec)
+{
+    rt_err_t result;
+    rt_tick_t ticks;
+    osStatus status;
+
+    /* timer_id is incorrect */
+    if ((RT_NULL == timer_id))
+    {
+        status = osErrorParameter;
+        goto timer_start_error;
+    }
+
+    /* Cannot be called from Interrupt Service Routines */
+    if (inHandlerMode())
+    {
+        status = osErrorISR;
+        goto timer_start_error;
+    }
+
+    ticks = rt_tick_from_millisecond(millisec);
+    result = rt_timer_control((rt_timer_t)timer_id, RT_TIMER_CTRL_SET_TIME, &ticks);
+    if (result != RT_EOK)
+    {
+        status = osErrorOS;
+        goto timer_start_error;
+    }
+
+    result = rt_timer_start((rt_timer_t)timer_id);
+    if (result != RT_EOK)
+    {
+        status = osErrorOS;
+        goto timer_start_error;
+    }
+
+    return osOK;
+timer_start_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
+    return status;
+}
+
+/**
+ * @brief  Stop a timer.
+ * @param  timer_id      timer ID obtained by \ref osTimerCreate
+ * @retval  status code that indicates the execution status of the function.
+ * @note   MUST REMAIN UNCHANGED: \b osTimerStop shall be consistent in every CMSIS-RTOS.
+ */
+osStatus osTimerStop(osTimerId timer_id)
+{
+    rt_err_t result;
+    rt_uint32_t timer_status;
+    osStatus status;
+
+    /* Cannot be called from Interrupt Service Routines */
+    if (inHandlerMode())
+    {
+        status = osErrorISR;
+        goto timer_stop_error;
+    }
+
+    /* timer_id is incorrect */
+    if (RT_NULL == timer_id)
+    {
+        status = osErrorParameter;
+        goto timer_stop_error;
+    }
+
+    /* the timer is not started */
+    rt_timer_control((rt_timer_t)timer_id, RT_TIMER_CTRL_GET_STATE, &timer_status);
+    if (RT_TIMER_FLAG_ACTIVATED != timer_status)
+    {
+        status = osErrorResource;
+        goto timer_stop_error;
+    }
+
+    result = rt_timer_stop((rt_timer_t)timer_id);
+    if (result != RT_EOK)
+    {
+        status = osErrorOS;
+        goto timer_stop_error;
+    }
+
+    return osOK;
+timer_stop_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
+    return status;
+}
+
+/**
+ * @brief  Delete a timer.
+ * @param  timer_id      timer ID obtained by \ref osTimerCreate
+ * @retval  status code that indicates the execution status of the function.
+ * @note   MUST REMAIN UNCHANGED: \b osTimerDelete shall be consistent in every CMSIS-RTOS.
+ */
+osStatus osTimerDelete(osTimerId timer_id)
+{
+    rt_err_t result;
+    osStatus status;
+
+    /* timer_id is incorrect. */
+    if (RT_NULL == timer_id)
+    {
+        status = osErrorParameter;
+        goto timer_delete_error;
+    }
+
+    /* Cannot be called from Interrupt Service Routines. */
+    if (inHandlerMode())
+    {
+        status = osErrorISR;
+        goto timer_delete_error;
+    }
+
+    result = rt_timer_delete((rt_timer_t)timer_id);
+    if (RT_EOK != result)
+    {
+        status = osErrorOS;
+        goto timer_delete_error;
+    }
+
+    return osOK;
+timer_delete_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
+    return status;
+}
+
+/***************************  Signal Management ********************************/
+/**
+ * @brief  Set the specified Signal Flags of an active thread.
+ * @param  thread_id     thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
+ * @param  signals       specifies the signal flags of the thread that should be set.
+ * @retval previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
+ * @note   MUST REMAIN UNCHANGED: \b osSignalSet shall be consistent in every CMSIS-RTOS.
+ */
+int32_t osSignalSet(osThreadId thread_id, int32_t signal)
+{
+    rt_event_t event;
+    int32_t ret = 0x80000000;
+    rt_err_t result;
+
+    if (RT_NULL == thread_id)
+        goto signal_set_error;
+
+    event = thread_id->event_id;
+
+    /* previous signal flags of the specified thread */
+    rt_enter_critical();
+    ret = event->set;
+    rt_exit_critical();
+
+    result = rt_event_send(event, signal);
+    if (RT_EOK != result)
+    {
+        ret = 0x80000000;
+        goto signal_set_error;
+    }
+
+    return ret;
+signal_set_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, ret);
+    return 0x80000000;
+}
+/**
+ * @brief  Clear the specified Signal Flags of an active thread.
+ * @param  thread_id  thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
+ * @param  signals    specifies the signal flags of the thread that shall be cleared.
+ * @retval  previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
+ * @note   MUST REMAIN UNCHANGED: \b osSignalClear shall be consistent in every CMSIS-RTOS.
+ */
+int32_t osSignalClear(osThreadId thread_id, int32_t signal)
+{
+    rt_event_t event;
+    int32_t ret = 0x80000000;
+
+    if (RT_NULL == thread_id)
+        goto signal_clear_error;
+
+    /* Cannot be called from Interrupt Service Routines. */
+    if (inHandlerMode())
+        goto signal_clear_error;
+
+    event = thread_id->event_id;
+
+    /* previous signal flags of the specified thread */
+    rt_enter_critical();
+    ret = event->set;
+    rt_exit_critical();
+
+    rt_event_control(event, RT_IPC_CMD_RESET, RT_NULL);
+
+    return ret;
+signal_clear_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, ret);
+    return 0x80000000;
+}
+
+/**
+ * @brief  Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread.
+ * @param  signals   wait until all specified signal flags set or 0 for any single signal flag.
+ * @param  millisec  timeout value or 0 in case of no time-out.
+ * @retval  event flag information or error code.
+ * @note   MUST REMAIN UNCHANGED: \b osSignalWait shall be consistent in every CMSIS-RTOS.
+ */
+osEvent osSignalWait(int32_t signals, uint32_t millisec)
+{
+    osEvent event;
+    rt_event_t recv_event;
+    osThreadId thread_cb;
+    rt_uint32_t recved;
+    rt_uint32_t ticks = 0;
+    rt_err_t result;
+
+    /* Cannot be called from Interrupt Service Routines. */
+    if (inHandlerMode())
+    {
+        event.status = osErrorISR;
+        goto signal_wait_error;
+    }
+
+    /* get receive event */
+    thread_cb = osThreadGetId();
+    recv_event = thread_cb->event_id;
+
+    /* get timeout */
+    if (osWaitForever == millisec)
+        ticks = RT_WAITING_FOREVER;
+    else if (0U != millisec)
+        ticks = rt_tick_from_millisecond(millisec);
+
+    if (signals != 0)
+        result = rt_event_recv(recv_event, signals, RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, ticks, &recved);
+    else
+        result = rt_event_recv(recv_event, signals, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, ticks, &recved);
+
+    if (-RT_ETIMEOUT == result)
+    {
+        event.status = osEventTimeout;
+        goto signal_wait_error;
+    }
+    else if (RT_EOK != result)
+    {
+        event.status = osErrorOS;
+        goto signal_wait_error;
+    }
+
+    event.status = osEventSignal;
+    return event;
+signal_wait_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, event.status);
+    return event;
+}
+
+/****************************  Mutex Management ********************************/
+/**
+ * @brief  Create and Initialize a Mutex object
+ * @param  mutex_def     mutex definition referenced with \ref osMutex.
+ * @retval  mutex ID for reference by other functions or NULL in case of error.
+ * @note   MUST REMAIN UNCHANGED: \b osMutexCreate shall be consistent in every CMSIS-RTOS.
+ */
+osMutexId osMutexCreate(const osMutexDef_t *mutex_def)
+{
+#ifdef RT_USING_MUTEX
+    static rt_uint16_t mutex_cnt = 0U;
+    char name[RT_NAME_MAX];
+    rt_mutex_t mutex;
+
+    /* Cannot be called from Interrupt Service Routines. */
+    if (inHandlerMode())
+        goto mutex_create_failed;
+
+    rt_snprintf(name, sizeof(name), "mutex%02d", mutex_cnt++); /* mutex name */
+    mutex = rt_mutex_create(name, RT_IPC_FLAG_PRIO);
+    if (RT_NULL == mutex)
+        goto mutex_create_failed;
+
+    return (osMutexId)mutex;
+mutex_create_failed:
+    rt_kprintf("CMSIS RTOS1 %s failed\r\n", __func__);
+    return RT_NULL;
+#else  /* not define RT_USING_MUTEX */
+    return RT_NULL;
+#endif /* RT_USING_MUTEX */
+}
+
+/**
+ * @brief Wait until a Mutex becomes available
+ * @param mutex_id      mutex ID obtained by \ref osMutexCreate.
+ * @param millisec      timeout value or 0 in case of no time-out.
+ * @retval  status code that indicates the execution status of the function.
+ * @note   MUST REMAIN UNCHANGED: \b osMutexWait shall be consistent in every CMSIS-RTOS.
+ */
+osStatus osMutexWait(osMutexId mutex_id, uint32_t millisec)
+{
+    rt_err_t result;
+    osStatus status;
+    rt_uint32_t ticks = 0;
+
+    /* the parameter mutex_id is incorrect */
+    if (RT_NULL == mutex_id)
+    {
+        status = osErrorParameter;
+        goto mutex_wait_error;
+    }
+
+    /* the mutex could not be obtained when no timeout was specified */
+    if (0 == millisec)
+    {
+        status = osErrorResource;
+        goto mutex_wait_error;
+    }
+
+    /* Cannot be called from Interrupt Service Routines. */
+    if (inHandlerMode())
+    {
+        status = osErrorISR;
+        goto mutex_wait_error;
+    }
+
+    rt_enter_critical();
+    if (((rt_mutex_t)mutex_id)->owner == rt_thread_self())
+    {
+        rt_exit_critical();
+        status = osErrorOS;
+        goto mutex_wait_error;
+    }
+    rt_exit_critical();
+
+    if (osWaitForever == millisec)
+        ticks = RT_WAITING_FOREVER;
+    else if (0U != millisec)
+        ticks = rt_tick_from_millisecond(millisec);
+
+    result = rt_mutex_take((rt_mutex_t)mutex_id, ticks);
+    if (-RT_ETIMEOUT == result)
+    {
+        status = osErrorTimeoutResource;
+        goto mutex_wait_error;
+    }
+    else if (RT_EOK != result)
+    {
+        status = osErrorOS;
+        goto mutex_wait_error;
+    }
+
+    return osOK;
+mutex_wait_error:
+    rt_kprintf("CMSIS RTOS1 %s failed\r\n", __func__);
+    return status;
+}
+
+/**
+ * @brief Release a Mutex that was obtained by \ref osMutexWait
+ * @param mutex_id      mutex ID obtained by \ref osMutexCreate.
+ * @retval  status code that indicates the execution status of the function.
+ * @note   MUST REMAIN UNCHANGED: \b osMutexRelease shall be consistent in every CMSIS-RTOS.
+ */
+osStatus osMutexRelease(osMutexId mutex_id)
+{
+    rt_err_t result;
+    osStatus status;
+
+    /* the parameter mutex_id is incorrect */
+    if (RT_NULL == mutex_id)
+    {
+        status = osErrorParameter;
+        goto mutex_release_error;
+    }
+
+    /* Cannot be called from Interrupt Service Routines. */
+    if (inHandlerMode())
+    {
+        status = osErrorISR;
+        goto mutex_release_error;
+    }
+
+    /*  the mutex was not obtained before */
+    if (rt_object_get_type(&((rt_mutex_t)mutex_id)->parent.parent) != RT_Object_Class_Mutex)
+    {
+        status = osErrorResource;
+        goto mutex_release_error;
+    }
+
+    result = rt_mutex_release((rt_mutex_t)mutex_id);
+    if (RT_EOK != result)
+    {
+        status = osErrorOS;
+        goto mutex_release_error;
+    }
+
+    return osOK;
+mutex_release_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
+    return status;
+}
+
+/**
+ * @brief Delete a Mutex
+ * @param mutex_id  mutex ID obtained by \ref osMutexCreate.
+ * @retval  status code that indicates the execution status of the function.
+ * @note   MUST REMAIN UNCHANGED: \b osMutexDelete shall be consistent in every CMSIS-RTOS.
+ */
+osStatus osMutexDelete(osMutexId mutex_id)
+{
+    osStatus status;
+    rt_err_t result;
+
+    /* Check parameters */
+    if (RT_NULL == mutex_id)
+    {
+        status = osErrorParameter;
+        goto mutex_delete_error;
+    }
+
+    /* Cannot be called from Interrupt Service Routines */
+    if (inHandlerMode())
+    {
+        status = osErrorISR;
+        goto mutex_delete_error;
+    }
+
+    /*  all tokens have already been released */
+    if (rt_object_get_type(&((rt_mutex_t)mutex_id)->parent.parent) != RT_Object_Class_Mutex)
+    {
+        status = osErrorResource;
+        goto mutex_delete_error;
+    }
+
+    result = rt_mutex_delete((rt_mutex_t)mutex_id);
+    if (RT_EOK != result)
+    {
+        status = osErrorOS;
+        goto mutex_delete_error;
+    }
+
+    return osOK;
+mutex_delete_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is :%d\r\n", __func__, status);
+    return status;
+}
+
+/********************  Semaphore Management Functions **************************/
+
+#if (defined(osFeature_Semaphore) && (osFeature_Semaphore != 0))
+/**
+ * @brief Create and Initialize a Semaphore object used for managing resources
+ * @param semaphore_def semaphore definition referenced with \ref osSemaphore.
+ * @param count         number of available resources.
+ * @retval  semaphore ID for reference by other functions or NULL in case of error.
+ * @note   MUST REMAIN UNCHANGED: \b osSemaphoreCreate shall be consistent in every CMSIS-RTOS.
+ */
+osSemaphoreId osSemaphoreCreate(const osSemaphoreDef_t *semaphore_def, int32_t count)
+{
+#ifdef RT_USING_SEMAPHORE
+    static rt_uint16_t sem_cnt = 0U;
+    char name[RT_NAME_MAX];
+    rt_sem_t sem;
+
+    /* Cannot be called from Interrupt Service Routines */
+    if (inHandlerMode())
+        goto sem_create_error;
+
+    if (count < 0 || count > osFeature_Semaphore)
+        goto sem_create_error;
+
+    rt_snprintf(name, sizeof(name), "sem%02d", sem_cnt++);
+    sem = rt_sem_create(name, count, RT_IPC_FLAG_PRIO);
+    if (RT_NULL == sem)
+        goto sem_create_error;
+
+    return (osSemaphoreId)sem;
+sem_create_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error", __func__);
+    return RT_NULL;
+#else  /* not defined RT_USING_SEMAPHORE */
+    return RT_NULL;
+#endif /* RT_USING_SEMAPHORE */
+}
+
+/* get semaphore cnt */
+static int32_t _osSemaphoreGetCount(osSemaphoreId semaphore_id)
+{
+    rt_sem_t sem_cb = (rt_sem_t)semaphore_id;
+
+    /* Check parameters */
+    if ((RT_NULL == sem_cb) || (rt_object_get_type(&sem_cb->parent.parent) != RT_Object_Class_Semaphore))
+        return 0U;
+
+    return sem_cb->value;
+}
+/**
+ * @brief Wait until a Semaphore token becomes available
+ * @param  semaphore_id  semaphore object referenced with \ref osSemaphore.
+ * @param  millisec      timeout value or 0 in case of no time-out.
+ * @retval  number of available tokens, or -1 in case of incorrect parameters.
+ * @note   MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS.
+ */
+int32_t osSemaphoreWait(osSemaphoreId semaphore_id, uint32_t millisec)
+{
+    rt_err_t result;
+    rt_int32_t ticks = 0;
+
+    if (RT_NULL == semaphore_id)
+        goto sem_take_error;
+
+    /* when millisec is set to osWaitForever the function will wait for an infinite time until the Semaphore token becomes available. */
+    if (osWaitForever == millisec)
+        ticks = RT_WAITING_FOREVER;
+    else if (0U != millisec)
+        ticks = rt_tick_from_millisecond(millisec);
+
+    /* when millisec is 0, the function returns instantly */
+    if (0 == millisec)
+        result = rt_sem_trytake((rt_sem_t)semaphore_id);
+    else
+        result = rt_sem_take((rt_sem_t)semaphore_id, ticks);
+
+    if (RT_EOK != result)
+        goto sem_take_error;
+
+    return _osSemaphoreGetCount(semaphore_id);
+sem_take_error:
+    rt_kprintf("CMSIS RTOS1 %s failed \r\n", __func__);
+    return 0; /* If 0 is returned, then no semaphore was available. */
+}
+
+/**
+ * @brief Release a Semaphore token
+ * @param  semaphore_id  semaphore object referenced with \ref osSemaphore.
+ * @retval  status code that indicates the execution status of the function.
+ * @note   MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS.
+ */
+osStatus osSemaphoreRelease(osSemaphoreId semaphore_id)
+{
+    rt_err_t result;
+    osStatus status;
+
+    /* the parameter semaphore_id is incorrect. */
+    if (RT_NULL == semaphore_id)
+    {
+        status = osErrorParameter;
+        goto sem_release_error;
+    }
+
+    /* all tokens have already been released. */
+    if (0 == _osSemaphoreGetCount(semaphore_id))
+    {
+        status = osErrorResource;
+        goto sem_release_error;
+    }
+
+    result = rt_sem_release((rt_sem_t)semaphore_id);
+    if (RT_EOK != result)
+    {
+        status = osErrorOS;
+        goto sem_release_error;
+    }
+
+    return osOK;
+sem_release_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
+    return status;
+}
+
+/**
+ * @brief Delete a Semaphore
+ * @param  semaphore_id  semaphore object referenced with \ref osSemaphore.
+ * @retval  status code that indicates the execution status of the function.
+ * @note   MUST REMAIN UNCHANGED: \b osSemaphoreDelete shall be consistent in every CMSIS-RTOS.
+ */
+osStatus osSemaphoreDelete(osSemaphoreId semaphore_id)
+{
+    rt_err_t result;
+    osStatus status;
+
+    /*  the parameter semaphore_id is incorrect. */
+    if (RT_NULL == semaphore_id)
+    {
+        status = osErrorParameter;
+        goto sem_delete_error;
+    }
+
+    /* Cannot be called from Interrupt Service Routines */
+    if (inHandlerMode())
+    {
+        status = osErrorISR;
+        goto sem_delete_error;
+    }
+
+    /* the semaphore object could not be deleted. */
+    if (rt_object_get_type((rt_object_t) & (((rt_sem_t)semaphore_id)->parent)) != RT_Object_Class_Semaphore)
+    {
+        status = osErrorResource;
+        goto sem_delete_error;
+    }
+
+    result = rt_sem_delete((rt_sem_t)semaphore_id);
+    if (RT_EOK != result)
+    {
+        status = osErrorOS;
+        goto sem_delete_error;
+    }
+
+    return osOK;
+sem_delete_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
+    return status;
+}
+#endif /* Use Semaphores */
+
+/*******************   Memory Pool Management Functions  ***********************/
+
+#if (defined(osFeature_Pool) && (osFeature_Pool != 0))
+/**
+ * @brief Create and Initialize a memory pool
+ * @param  pool_def      memory pool definition referenced with \ref osPool.
+ * @retval  memory pool ID for reference by other functions or NULL in case of error.
+ * @note   MUST REMAIN UNCHANGED: \b osPoolCreate shall be consistent in every CMSIS-RTOS.
+ */
+osPoolId osPoolCreate(const osPoolDef_t *pool_def)
+{
+    static rt_uint16_t mp_cnt = 0U;
+    char name[RT_NAME_MAX];
+    rt_mp_t mempool;
+    rt_size_t block_size;
+
+    /* Cannot be called from Interrupt Service Routines. */
+    if (inHandlerMode())
+        goto mp_create_error;
+
+    if (RT_NULL == pool_def || 0 == pool_def->pool_sz || 0 == pool_def->item_sz)
+        goto mp_create_error;
+
+    rt_snprintf(name, sizeof(name), "mp%02d", mp_cnt++);     /* name */
+    block_size = RT_ALIGN(pool_def->item_sz, RT_ALIGN_SIZE); /* pool size */
+
+    mempool = rt_mp_create(name, pool_def->pool_sz, block_size);
+    if (RT_NULL == mempool)
+        goto mp_create_error;
+
+    return (osPoolId)mempool;
+mp_create_error:
+    rt_kprintf("CMSIS RTOS1 %s failed\r\n", __func__);
+    return RT_NULL;
+}
+
+/**
+ * @brief Allocate a memory block from a memory pool
+ * @param pool_id       memory pool ID obtain referenced with \ref osPoolCreate.
+ * @retval  address of the allocated memory block or NULL in case of no memory available.
+ * @note   MUST REMAIN UNCHANGED: \b osPoolAlloc shall be consistent in every CMSIS-RTOS.
+ */
+void *osPoolAlloc(osPoolId pool_id)
+{
+    /* Check parameters */
+    if (RT_NULL == pool_id)
+        return RT_NULL;
+
+    return rt_mp_alloc((rt_mp_t)pool_id, RT_WAITING_FOREVER);
+}
+
+/**
+ * @brief Allocate a memory block from a memory pool and set memory block to zero
+ * @param  pool_id       memory pool ID obtain referenced with \ref osPoolCreate.
+ * @retval  address of the allocated memory block or NULL in case of no memory available.
+ * @note   MUST REMAIN UNCHANGED: \b osPoolCAlloc shall be consistent in every CMSIS-RTOS.
+ */
+void *osPoolCAlloc(osPoolId pool_id)
+{
+    void *p = osPoolAlloc(pool_id);
+
+    if (p != NULL)
+        rt_memset(p, 0, ((rt_mp_t)pool_id)->block_size);
+
+    return p;
+}
+
+/**
+ * @brief Return an allocated memory block back to a specific memory pool
+ * @param  pool_id       memory pool ID obtain referenced with \ref osPoolCreate.
+ * @param  block         address of the allocated memory block that is returned to the memory pool.
+ * @retval  status code that indicates the execution status of the function.
+ * @note   MUST REMAIN UNCHANGED: \b osPoolFree shall be consistent in every CMSIS-RTOS.
+ */
+osStatus osPoolFree(osPoolId pool_id, void *block)
+{
+    osStatus status;
+    /* Check parameters */
+    if (NULL == pool_id)
+    {
+        status = osErrorParameter;
+        goto pool_free_error;
+    }
+
+    if (NULL == block)
+    {
+        status = osErrorParameter;
+        goto pool_free_error;
+    }
+
+    rt_mp_free(block);
+    block = RT_NULL;
+
+    return osOK;
+pool_free_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
+    return status;
+}
+#endif /* Use Memory Pool Management */
+
+/*******************   Message Queue Management Functions  *********************/
+
+#if (defined(osFeature_MessageQ) && (osFeature_MessageQ != 0)) /* Use Message Queues */
+/**
+ * @brief Create and Initialize a Message Queue
+ * @param queue_def     queue definition referenced with \ref osMessageQ.
+ * @param  thread_id     thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL.
+ * @retval  message queue ID for reference by other functions or NULL in case of error.
+ * @note   MUST REMAIN UNCHANGED: \b osMessageCreate shall be consistent in every CMSIS-RTOS.
+ */
+osMessageQId osMessageCreate(const osMessageQDef_t *queue_def, osThreadId thread_id)
+{
+#ifdef RT_USING_MAILBOX
+    (void)thread_id;
+    static rt_uint16_t mailbox_cnt = 0U;
+    char name[RT_NAME_MAX];
+    rt_mailbox_t mailbox;
+
+    /* Cannot be called from Interrupt Service Routines. */
+    if (inHandlerMode())
+        goto message_create_error;
+
+    /* param error */
+    if (RT_NULL == queue_def || 0 == queue_def->queue_sz || sizeof(void *) != queue_def->item_sz)
+        goto message_create_error;
+
+    rt_snprintf(name, sizeof(name), "mailbox%02d", mailbox_cnt++);
+    mailbox = rt_mb_create(name, queue_def->queue_sz, RT_IPC_FLAG_PRIO);
+    if (mailbox == RT_NULL)
+        goto message_create_error;
+
+    return (osMessageQId)mailbox;
+message_create_error:
+    rt_kprintf("CMSIS RTOS1 %s failed \r\n", __func__);
+    return RT_NULL;
+#else  /* RT_USING_MAILBOX */
+    return RT_NULL;
+#endif /* not define RT_USING_MAILBOX */
+}
+/**
+ * @brief Put a Message to a Queue.
+ * @param  queue_id  message queue ID obtained with \ref osMessageCreate.
+ * @param  info      message information.
+ * @param  millisec  timeout value or 0 in case of no time-out.
+ * @retval status code that indicates the execution status of the function.
+ * @note   MUST REMAIN UNCHANGED: \b osMessagePut shall be consistent in every CMSIS-RTOS.
+ */
+osStatus osMessagePut(osMessageQId queue_id, uint32_t info, uint32_t millisec)
+{
+    rt_err_t result;
+    osStatus status;
+    rt_mailbox_t mb_cb = (rt_mailbox_t)queue_id;
+    rt_tick_t ticks = 0;
+
+    if (RT_NULL == queue_id)
+    {
+        /* a parameter is invalid or outside of a permitted range */
+        status = osErrorParameter;
+        goto message_put_error;
+    }
+
+    if (osWaitForever == millisec)
+        ticks = RT_WAITING_FOREVER;
+    else if (0U != millisec)
+        ticks = rt_tick_from_millisecond(millisec);
+
+    /* when millisec is 0, the function returns instantly */
+    if (0 == millisec)
+        result = rt_mb_urgent(mb_cb, info);
+    else
+        result = rt_mb_send_wait(mb_cb, info, ticks);
+
+    if (-RT_EFULL == result)
+    {
+        /* no memory in the queue was available */
+        status = osErrorResource;
+        goto message_put_error;
+    }
+    else if (-RT_ETIMEOUT == result)
+    {
+        /* no memory in the queue was available during the given time limit. */
+        status = osErrorTimeoutResource;
+        goto message_put_error;
+    }
+    if (RT_EOK != result)
+    {
+        status = osErrorOS;
+        goto message_put_error;
+    }
+
+    return osOK;
+message_put_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
+    return status;
+}
+/**
+ * @brief Get a Message or Wait for a Message from a Queue.
+ * @param  queue_id  message queue ID obtained with \ref osMessageCreate.
+ * @param  millisec  timeout value or 0 in case of no time-out.
+ * @retval event information that includes status code.
+ * @note   MUST REMAIN UNCHANGED: \b osMessageGet shall be consistent in every CMSIS-RTOS.
+ */
+osEvent osMessageGet(osMessageQId queue_id, uint32_t millisec)
+{
+    osEvent event;
+    rt_err_t result;
+    rt_tick_t ticks = 0;
+
+    if (RT_NULL == queue_id)
+    {
+        /* a parameter is invalid or outside of a permitted range */
+        event.status = osErrorParameter;
+        goto message_get_error;
+    }
+
+    event.def.message_id = queue_id;
+    event.value.v = 0;
+
+    if (osWaitForever == millisec)
+        ticks = RT_WAITING_FOREVER;
+    else if (0U != millisec)
+        ticks = rt_tick_from_millisecond(millisec);
+
+    result = rt_mb_recv((rt_mailbox_t)queue_id, &(event.value.v), ticks);
+    if (-RT_ETIMEOUT == result)
+    {
+        /* no message has arrived during the given timeout period */
+        event.status = osEventTimeout;
+        goto message_get_error;
+    }
+    else if (RT_EOK != result)
+    {
+        event.status = osErrorOS;
+        goto message_get_error;
+    }
+
+    /* message received, value.p contains the pointer to message */
+    event.status = osEventMessage;
+    return event;
+message_get_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, event.status);
+    return event;
+}
+#endif /* Use Message Queues */
+
+/********************   Mail Queue Management Functions  ***********************/
+#if (defined(osFeature_MailQ) && (osFeature_MailQ != 0)) /* Use Mail Queues */
+typedef struct os_mailQ_cb
+{
+    rt_mp_t mp_id;
+    rt_mailbox_t mb_id;
+} os_mailQ_cb_t;
+/**
+ * @brief Create and Initialize mail queue
+ * @param  queue_def     reference to the mail queue definition obtain with \ref osMailQ
+ * @param   thread_id     thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL.
+ * @retval mail queue ID for reference by other functions or NULL in case of error.
+ * @note   MUST REMAIN UNCHANGED: \b osMailCreate shall be consistent in every CMSIS-RTOS.
+ */
+osMailQId osMailCreate(const osMailQDef_t *queue_def, osThreadId thread_id)
+{
+#if defined(RT_USING_MEMPOOL) && defined(RT_USING_MAILBOX)
+    (void)thread_id;
+    os_mailQ_cb_t *ptr = RT_NULL;
+
+    char name[RT_NAME_MAX];
+    static rt_uint16_t mail_cnt = 0U;
+    rt_size_t block_size;
+
+    /* Cannot be called from Interrupt Service Routines. */
+    if (inHandlerMode())
+        goto mail_create_failed;
+
+    if (RT_NULL == queue_def || 0 == queue_def->queue_sz || 0 == queue_def->item_sz)
+        goto mail_create_failed;
+
+    rt_snprintf(name, sizeof(name), "mb%02d", mail_cnt++);
+    block_size = RT_ALIGN(queue_def->item_sz, RT_ALIGN_SIZE);
+
+    ptr = (void *)CMSIS_MEM_ALLOC(sizeof(struct os_mailQ_cb));
+    if (RT_NULL == ptr)
+        goto mail_create_failed;
+
+    ptr->mp_id = rt_mp_create(name, queue_def->queue_sz, block_size);
+    ptr->mb_id = rt_mb_create(name, queue_def->queue_sz, RT_IPC_FLAG_PRIO);
+    if ((RT_NULL == ptr->mp_id) || (RT_NULL == ptr->mb_id))
+        goto mail_create_failed;
+
+    return ptr;
+mail_create_failed:
+    if (ptr)
+        CMSIS_MEM_FREE(ptr);
+    if (RT_NULL != ptr->mp_id)
+        rt_mp_delete(ptr->mp_id);
+    if (RT_NULL != ptr->mb_id)
+        rt_mb_delete(ptr->mb_id);
+    rt_kprintf("CMSIS RTOS1 %s failed\r\n", __func__);
+    return RT_NULL;
+#else  /* RT_USING_MEMPOOL && RT_USING_MAILBOX */
+    return RT_NULL;
+#endif /* not define RT_USING_MEMPOOL && RT_USING_MAILBOX */
+}
+
+/**
+ * @brief Allocate a memory block from a mail
+ * @param  queue_id      mail queue ID obtained with \ref osMailCreate.
+ * @param  millisec      timeout value or 0 in case of no time-out.
+ * @retval pointer to memory block that can be filled with mail or NULL in case error.
+ * @note   MUST REMAIN UNCHANGED: \b osMailAlloc shall be consistent in every CMSIS-RTOS.
+ */
+void *osMailAlloc(osMailQId queue_id, uint32_t millisec)
+{
+    os_mailQ_cb_t *ptr = (os_mailQ_cb_t *)queue_id;
+    void *ret = NULL;
+    rt_tick_t ticks = 0;
+
+    if (RT_NULL == ptr)
+        goto mail_alloc_error;
+
+    if (osWaitForever == millisec)
+        ticks = RT_WAITING_FOREVER;
+    else if (0U != millisec)
+        ticks = rt_tick_from_millisecond(millisec);
+
+    ret = rt_mp_alloc(ptr->mp_id, ticks);
+    if (RT_NULL == ret)
+        goto mail_alloc_error;
+
+    return ret;
+mail_alloc_error:
+    rt_kprintf("CMSIS RTOS1 %s failed\r\n", __func__);
+    return RT_NULL;
+}
+
+/**
+ * @brief Allocate a memory block from a mail and set memory block to zero
+ * @param  queue_id      mail queue ID obtained with \ref osMailCreate.
+ * @param  millisec      timeout value or 0 in case of no time-out.
+ * @retval pointer to memory block that can be filled with mail or NULL in case error.
+ * @note   MUST REMAIN UNCHANGED: \b osMailCAlloc shall be consistent in every CMSIS-RTOS.
+ */
+void *osMailCAlloc(osMailQId queue_id, uint32_t millisec)
+{
+    void *p = osMailAlloc(queue_id, millisec);
+    if (p)
+        rt_memset(p, 0, ((os_mailQ_cb_t *)queue_id)->mp_id->block_size);
+
+    return p;
+}
+
+/**
+ * @brief Put a mail to a queue
+ * @param  queue_id      mail queue ID obtained with \ref osMailCreate.
+ * @param  mail          memory block previously allocated with \ref osMailAlloc or \ref osMailCAlloc.
+ * @retval status code that indicates the execution status of the function.
+ * @note   MUST REMAIN UNCHANGED: \b osMailPut shall be consistent in every CMSIS-RTOS.
+ */
+osStatus osMailPut(osMailQId queue_id, void *mail)
+{
+    osStatus status;
+    os_mailQ_cb_t *ptr = (os_mailQ_cb_t *)queue_id;
+    rt_err_t result;
+
+    if (RT_NULL == ptr)
+    {
+        status = osErrorParameter;
+        goto mail_put_error;
+    }
+
+    if (RT_NULL == mail)
+    {
+        status = osErrorValue;
+        goto mail_put_error;
+    }
+
+    result = rt_mb_send((ptr->mb_id), (rt_ubase_t)mail);
+    if (RT_EOK != result)
+    {
+        status = osErrorOS;
+        goto mail_put_error;
+    }
+
+    return osOK;
+mail_put_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
+    return status;
+}
+
+/**
+ * @brief Get a mail from a queue
+ * @param  queue_id   mail queue ID obtained with \ref osMailCreate.
+ * @param millisec    timeout value or 0 in case of no time-out
+ * @retval event that contains mail information or error code.
+ * @note   MUST REMAIN UNCHANGED: \b osMailGet shall be consistent in every CMSIS-RTOS.
+ */
+osEvent osMailGet(osMailQId queue_id, uint32_t millisec)
+{
+    osEvent event;
+    os_mailQ_cb_t *ptr = (os_mailQ_cb_t *)queue_id;
+    rt_err_t result;
+    rt_ubase_t value;
+    rt_tick_t ticks = 0;
+
+    if (RT_NULL == ptr)
+    {
+        event.status = osErrorParameter;
+        goto mail_get_error;
+    }
+
+    if (osWaitForever == millisec)
+        ticks = RT_WAITING_FOREVER;
+    else if (0U != millisec)
+        ticks = rt_tick_from_millisecond(millisec);
+
+    result = rt_mb_recv((ptr->mb_id), &value, ticks);
+    if (-RT_ETIMEOUT == result)
+    {
+        event.status = osEventTimeout;
+        goto mail_get_error;
+    }
+    else if (RT_EOK != result)
+    {
+        event.status = osErrorOS;
+        goto mail_get_error;
+    }
+
+    event.value.p = (void *)value;
+    event.status = osEventMail;
+    return event;
+mail_get_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, event.status);
+    return event;
+}
+
+/**
+ * @brief Free a memory block from a mail
+ * @param  queue_id mail queue ID obtained with \ref osMailCreate.
+ * @param  mail     pointer to the memory block that was obtained with \ref osMailGet.
+ * @retval status code that indicates the execution status of the function.
+ * @note   MUST REMAIN UNCHANGED: \b osMailFree shall be consistent in every CMSIS-RTOS.
+ */
+osStatus osMailFree(osMailQId queue_id, void *mail)
+{
+    osStatus status;
+    os_mailQ_cb_t *ptr = (os_mailQ_cb_t *)queue_id;
+
+    if (RT_NULL == ptr)
+    {
+        status = osErrorParameter;
+        goto mail_free_error;
+    }
+
+    if (RT_NULL == mail)
+    {
+        status = osErrorValue;
+        goto mail_free_error;
+    }
+
+    rt_mp_free(mail);
+    mail = RT_NULL;
+
+    return osOK;
+mail_free_error:
+    rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
+    return status;
+}
+#endif /* Use Mail Queues */
+
+/****************************** end of file ******************************/

+ 447 - 0
testcases/cmsis_rtos_tc.c

@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 2006-2019, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2022-04-27     tyustli      the first version
+ */
+
+#include <rtthread.h>
+#include "utest.h"
+#include "cmsis_os.h"
+
+static void osKernelInitialize_test(void)
+{
+    osStatus status = osErrorOS;
+
+    status = osKernelInitialize();
+    if (osOK != status)
+    {
+        uassert_true(RT_FALSE);
+        return;
+    }
+    uassert_true(RT_TRUE);
+}
+
+static void osKernelStart_test(void)
+{
+    osStatus status = osErrorOS;
+
+    status = osKernelStart();
+    if (osOK != status)
+    {
+        uassert_true(RT_FALSE);
+        return;
+    }
+    uassert_true(RT_TRUE);
+}
+
+static void osKernelRunning_test(void)
+{
+    char status = -1;
+
+    status = osKernelRunning();
+    if (1 != status)
+    {
+        uassert_true(RT_FALSE);
+        return;
+    }
+    uassert_true(RT_TRUE);
+}
+
+static void thread_callback(void const *arg);
+osThreadDef(thread_callback, osPriorityNormal, 1, 0);
+static osThreadId test_tid1 = RT_NULL;
+
+static void thread_callback(void const *arg)
+{
+    uassert_true(RT_TRUE);
+    osDelay(10);
+    if (test_tid1 != osThreadGetId())
+    {
+        uassert_true(RT_FALSE);
+    }
+    osDelay(1000);
+}
+
+static void osThread_test(void)
+{
+    osStatus status;
+
+    test_tid1 = osThreadCreate(osThread(thread_callback), NULL);
+
+    if (test_tid1 == NULL)
+    {
+        uassert_true(RT_FALSE);
+        return;
+    }
+
+    status = osThreadSetPriority(test_tid1, osPriorityAboveNormal);
+    if (osOK != status)
+    {
+        uassert_true(RT_FALSE);
+    }
+
+    if (osPriorityAboveNormal != osThreadGetPriority(test_tid1))
+    {
+        uassert_true(RT_FALSE);
+    }
+
+    osDelay(100);
+    status = osThreadTerminate(test_tid1);
+    if (osOK != status)
+    {
+        uassert_true(RT_FALSE);
+        return;
+    }
+
+    uassert_true(RT_TRUE);
+}
+
+static void Timer1_Callback(void const *arg);
+static void Timer2_Callback(void const *arg);
+osTimerDef(Timer1, Timer1_Callback);
+osTimerDef(Timer2, Timer2_Callback);
+static uint32_t exec1;
+static uint32_t exec2;
+static char timer1_cnt = 0;
+static char timer2_cnt = 0;
+void Timer1_Callback(void const *arg)
+{
+    timer1_cnt++;
+    uassert_true(RT_TRUE);
+}
+void Timer2_Callback(void const *arg)
+{
+    timer2_cnt++;
+}
+
+static void osTimer_test(void)
+{
+    osTimerId id1;
+    osTimerId id2;
+
+    // Create one-shoot timer
+    exec1 = 1;
+    id1 = osTimerCreate(osTimer(Timer1), osTimerOnce, &exec1);
+    if (id1 == NULL)
+    {
+        uassert_true(RT_FALSE);
+    }
+
+    // Create periodic timer
+    exec2 = 2;
+    id2 = osTimerCreate(osTimer(Timer2), osTimerPeriodic, &exec2);
+    if (id2 == NULL)
+    {
+        uassert_true(RT_FALSE);
+    }
+
+    osTimerStart(id1, 50);
+    osTimerStart(id2, 50);
+    osDelay(1050);
+    uassert_true(timer2_cnt >= 20);
+    osTimerDelete(id1);
+    osTimerDelete(id2);
+    uassert_true(RT_TRUE);
+}
+
+osMutexDef(MutexIsr);
+static void osMutexDelete_test(void)
+{
+    osStatus status;
+    osMutexId mutex_id;
+
+    mutex_id = osMutexCreate(osMutex(MutexIsr));
+    if (mutex_id == NULL)
+    {
+        uassert_true(RT_FALSE);
+    }
+    status = osMutexWait(mutex_id, 1000);
+    uassert_true(osOK == status);
+    status = osMutexRelease(mutex_id);
+    uassert_true(osOK == status);
+    status = osMutexDelete(mutex_id);
+    uassert_true(osOK == status);
+}
+
+osThreadId tid_thread1;
+osSemaphoreId semaphore;
+osSemaphoreDef(semaphore);
+void thread1(void const *argument)
+{
+    int32_t value;
+    osDelay(20);
+    value = osSemaphoreWait(semaphore, osWaitForever);
+    if (value > 0)
+    {
+        uassert_true(RT_TRUE);
+    }
+}
+osThreadDef(thread1, osPriorityHigh, 1, 0);
+static void release_timer(void const *arg);
+osTimerDef(rtimer, release_timer);
+static void release_timer(void const *arg)
+{
+    osStatus status;
+
+    status = osSemaphoreRelease(semaphore);
+    uassert_true(status == osOK);
+}
+static void osSemaphore_test(void)
+{
+    osTimerId id1;
+    semaphore = osSemaphoreCreate(osSemaphore(semaphore), 1);
+    uassert_true(RT_NULL != semaphore);
+    tid_thread1 = osThreadCreate(osThread(thread1), NULL);
+
+    id1 = osTimerCreate(osTimer(rtimer), osTimerOnce, RT_NULL);
+    osTimerStart(id1, 10);
+    osDelay(1000);
+    osSemaphoreDelete(semaphore);
+    osTimerDelete(id1);
+}
+typedef struct
+{
+    uint8_t Buf[32];
+    uint8_t Idx;
+} MEM_BLOCK0;
+osPoolDef(MemPool0, 8, MEM_BLOCK0);
+static void osPool_test(void)
+{
+    osPoolId MemPool_Id;
+    MEM_BLOCK0 *addr;
+    osStatus status;
+
+    MemPool_Id = osPoolCreate(osPool(MemPool0));
+    if (MemPool_Id != NULL)
+    {
+        uassert_true(RT_TRUE);
+        addr = (MEM_BLOCK0 *)osPoolCAlloc(MemPool_Id);
+        if (addr != NULL)
+        {
+            rt_memset(addr, 0x5a, sizeof(MEM_BLOCK0));
+            uassert_true(RT_TRUE);
+            status = osPoolFree(MemPool_Id, addr);
+            if (status == osOK)
+            {
+                uassert_true(RT_TRUE);
+                return;
+            }
+        }
+    }
+    uassert_true(RT_FALSE);
+}
+
+typedef struct
+{                // Message object structure
+    int voltage; // AD result of measured voltage
+    int current; // AD result of measured current
+    int counter; // A counter value
+} T_MEASSAGE;
+osPoolDef(msg_mpool, 16, T_MEASSAGE); // Define memory pool
+osPoolId msg_mpool;
+osMessageQDef(MsgBox, 16, uint32_t); // Define message queue
+osMessageQId MsgBox;
+void message_send_thread(void const *argument); // forward reference
+void message_recv_thread(void const *argument); // forward reference
+                                                // Thread definitions
+osThreadDef(message_send_thread, osPriorityNormal, 1, 0);
+osThreadDef(message_recv_thread, osPriorityNormal, 1, 2000);
+
+void message_send_thread(void const *argument)
+{
+    T_MEASSAGE *mptr;
+    osStatus status;
+
+    mptr = osPoolAlloc(msg_mpool); // Allocate memory for the message
+    mptr->voltage = 223;           // Set the message content
+    mptr->current = 26;
+    mptr->counter = 120786;
+    status = osMessagePut(MsgBox, (uint32_t)mptr, osWaitForever); // Send Message
+    uassert_true(osOK == status);
+    osDelay(5);
+    mptr = osPoolAlloc(msg_mpool); // Allocate memory for the message
+    mptr->voltage = 227;           // Prepare a 2nd message
+    mptr->current = 12;
+    mptr->counter = 170823;
+    status = osMessagePut(MsgBox, (uint32_t)mptr, osWaitForever); // Send Message
+    uassert_true(osOK == status);
+    osThreadYield(); // Cooperative multitasking
+                     // We are done here, exit this thread
+}
+
+void message_recv_thread(void const *argument)
+{
+    T_MEASSAGE *rptr;
+    osEvent evt;
+
+    for (;;)
+    {
+        evt = osMessageGet(MsgBox, osWaitForever); // wait for message
+        if (evt.status == osEventMessage)
+        {
+            rptr = evt.value.p;
+            if (120786 == rptr->counter)
+            {
+                uassert_true(223 == rptr->voltage);
+                uassert_true(26 == rptr->current);
+            }
+            if (170823 == rptr->counter)
+            {
+                uassert_true(227 == rptr->voltage);
+                uassert_true(12 == rptr->current);
+            }
+            osPoolFree(msg_mpool, rptr); // free memory allocated for message
+        }
+    }
+}
+
+void osMessage_test(void)
+{
+    osThreadId message_tid_thread1;                     // ID for thread 1
+    osThreadId message_tid_thread2;                     // for thread 2
+    msg_mpool = osPoolCreate(osPool(msg_mpool));        // create memory pool
+    MsgBox = osMessageCreate(osMessageQ(MsgBox), NULL); // create msg queue
+    uassert_true(RT_NULL != MsgBox);
+
+    message_tid_thread1 = osThreadCreate(osThread(message_send_thread), NULL);
+    message_tid_thread2 = osThreadCreate(osThread(message_recv_thread), NULL);
+    (void)message_tid_thread1;
+    osDelay(500);
+    osThreadTerminate(message_tid_thread2);
+}
+
+typedef struct
+{                // Mail object structure
+    int voltage; // AD result of measured voltage
+    int current; // AD result of measured current
+    int counter; // A counter value
+} T_MEAS_MAIL;
+
+osMailQDef(mail, 16, T_MEAS_MAIL); // Define mail queue
+osMailQId mail;
+
+void mail_send_thread(void const *argument); // forward reference
+void mail_recv_thread(void const *argument);
+
+osThreadDef(mail_send_thread, osPriorityNormal, 1, 0); // thread definitions
+osThreadDef(mail_recv_thread, osPriorityNormal, 1, 2000);
+
+void mail_send_thread(void const *argument)
+{
+    T_MEAS_MAIL *mptr;
+
+    mptr = osMailAlloc(mail, osWaitForever); // Allocate memory
+    mptr->voltage = 223;                     // Set the mail content
+    mptr->current = 17;
+    mptr->counter = 120786;
+    osMailPut(mail, mptr); // Send Mail
+    osDelay(10);
+
+    mptr = osMailAlloc(mail, osWaitForever); // Allocate memory
+    mptr->voltage = 227;                     // Prepare 2nd mail
+    mptr->current = 12;
+    mptr->counter = 170823;
+    osMailPut(mail, mptr); // Send Mail
+    osThreadYield();       // Cooperative multitasking
+                           // We are done here, exit this thread
+}
+
+void mail_recv_thread(void const *argument)
+{
+    T_MEAS_MAIL *rptr;
+    osEvent evt;
+    for (;;)
+    {
+        evt = osMailGet(mail, osWaitForever); // wait for mail
+        if (evt.status == osEventMail)
+        {
+            rptr = evt.value.p;
+            if (120786 == rptr->counter)
+            {
+                uassert_true(223 == rptr->voltage);
+                uassert_true(17 == rptr->current);
+            }
+            if (170823 == rptr->counter)
+            {
+                uassert_true(227 == rptr->voltage);
+                uassert_true(12 == rptr->current);
+            }
+            osMailFree(mail, rptr); // free memory allocated for mail
+            uassert_true(RT_TRUE);
+        }
+    }
+}
+
+void osMail_test(void)
+{
+    osThreadId mail_tid_thread1; // ID for thread 1
+    osThreadId mail_tid_thread2; // ID for thread 2
+
+    mail = osMailCreate(osMailQ(mail), NULL); // create mail queue
+
+    mail_tid_thread1 = osThreadCreate(osThread(mail_send_thread), NULL);
+    mail_tid_thread2 = osThreadCreate(osThread(mail_recv_thread), NULL);
+    (void)mail_tid_thread1;
+    osDelay(500);
+    osThreadTerminate(mail_tid_thread2);
+}
+
+static void thread_rec(void const *arg);
+osThreadDef(thread_rec, osPriorityHigh, 1, 0);
+static void osSignal_test(void)
+{
+    int32_t signals;
+    osThreadId thread_id;
+
+    thread_id = osThreadCreate(osThread(thread_rec), NULL);
+    if (thread_id == NULL)
+    {
+        uassert_true(RT_FALSE);
+    }
+    else
+    {
+        signals = osSignalSet(thread_id, 0x02); // Send signals to the created thread
+        if (signals == 0x80000000)
+            uassert_true(RT_FALSE);
+    }
+}
+static void thread_rec(void const *arg)
+{
+    osEvent evt;
+    // wait for a signal
+    evt = osSignalWait(0x02, 100);
+    if (evt.status == osEventSignal)
+        uassert_true(RT_TRUE);
+    else
+        uassert_true(RT_FALSE);
+}
+
+static rt_err_t utest_tc_init(void)
+{
+    return RT_EOK;
+}
+
+static rt_err_t utest_tc_cleanup(void)
+{
+    return RT_EOK;
+}
+
+static void testcase(void)
+{
+    UTEST_UNIT_RUN(osKernelInitialize_test);
+    UTEST_UNIT_RUN(osKernelStart_test);
+    UTEST_UNIT_RUN(osKernelRunning_test);
+    UTEST_UNIT_RUN(osThread_test);
+    UTEST_UNIT_RUN(osTimer_test);
+    UTEST_UNIT_RUN(osMutexDelete_test);
+    UTEST_UNIT_RUN(osSemaphore_test);
+    UTEST_UNIT_RUN(osPool_test);
+    UTEST_UNIT_RUN(osMessage_test);
+    UTEST_UNIT_RUN(osMail_test);
+    UTEST_UNIT_RUN(osSignal_test);
+}
+UTEST_TC_EXPORT(testcase, "testcases.packages.cmsis", utest_tc_init, utest_tc_cleanup, 1000);