zoukankan      html  css  js  c++  java
  • CMSIS RTOS -- embOS segger

    #ifndef __CMSIS_OS_H__
    #define __CMSIS_OS_H__
    
    #include <stdint.h>
    #include <stddef.h>
    
    #include "RTOS.h"
    
    // API version (main [31:16] .sub [15:0])
    #define osCMSIS               0x10002
    // RTOS identification and version (main [31:16] .sub [15:0])
    #define osCMSIS_RTX           ((4<<16)|00)
    // RTOS identification string
    #define osKernelSystemId      "EMBOS V4.00"
    //
    // main thread      1=main can be thread, 0=not available
    #define osFeature_MainThread  1
    //
    // Memory Pools:    1=available, 0=not available
    #define osFeature_Pool        1
    //
    // Mail Queues:     1=available, 0=not available
    #define osFeature_MailQ       1
    //
    // Message Queues:  1=available, 0=not available
    #define osFeature_MessageQ    1
    //
    // maximum number of Signal Flags available per thread
    // bit31 = 0x80000000 : incorrect parameters
    #define osFeature_Signals     31
    //
    // maximum count for osSemaphoreCreate function
    #define osFeature_Semaphore   0xFFFFFFFF
    //
    // osWait function: 1=available, 0=not available
    #define osFeature_Wait        0
    //
    // osKernelSysTick functions: 1=available, 0=not available
    #define osFeature_SysTick     1
    //
    //
    //
    #ifdef  __cplusplus
    extern "C"
    {
    #endif
    
    // ==== Enumeration, structures, defines =======================================
    //
    // Priority used for thread control.
    // MUST REMAIN UNCHANGED: 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
    } osPriority;                     // or thread has illegal priority
    
    // Timeout value.
    // MUST REMAIN UNCHANGED: osWaitForever shall be consistent in every CMSIS-RTOS.
    //
    #define osWaitForever     0xFFFFFFFF     // wait forever timeout value
    // Status code values returned by CMSIS-RTOS functions.
    // MUST REMAIN UNCHANGED: osStatus shall be consistent in every CMSIS-RTOS.
    //
    typedef enum
    {
      // function completed; no error or event occurred.
      osOK = 0,
      //
      // function completed; signal event occurred.
      osEventSignal = 0x08,
      // function completed; message event occurred.
      osEventMessage = 0x10,
      // function completed; mail event occurred.
      osEventMail = 0x20,
      //
      // function completed; timeout occurred.
      osEventTimeout = 0x40,
      //
      // parameter error: a mandatory parameter was missing or specified an incorrect object.
      osErrorParameter = 0x80,
      //
      // resource not available: a specified resource was not available.
      osErrorResource = 0x81,
      // resource not available within given time: a specified resource was not available within the timeout period.
      osErrorTimeoutResource = 0xC1,
      // not allowed in ISR context: the function cannot be called from interrupt service routines.
      osErrorISR = 0x82,
      // function called multiple times from ISR with same object.
      osErrorISRRecursive = 0x83,
      // system cannot determine priority or thread has illegal priority.
      osErrorPriority = 0x84,
      // system is out of memory: it was impossible to allocate or reserve memory for the operation.
      osErrorNoMemory = 0x85,
      // value of a parameter is out of range.
      osErrorValue = 0x86,
      // unspecified RTOS error: run-time error but no other error message fits.
      osErrorOS = 0xFF,
      //
      os_status_reserved = 0x7FFFFFFF
    // prevent from enum down-size compiler optimization.
    // 32 bits for osStatus
    } osStatus;
    
    // Timer type value for the timer definition.
    // MUST REMAIN UNCHANGED: os_timer_type shall be consistent in every CMSIS-RTOS.
    //
    typedef enum
    {
      osTimerOnce = 0,            // one-shot timer
      osTimerPeriodic = 1         // repeating timer --- EMBOS can not support !
    } os_timer_type;
    
    typedef struct _CMSIS_OS_GLOBAL
    {
      uint32_t dummy;
    } CMSIS_OS_GLOBAL;
    
    extern CMSIS_OS_GLOBAL os_global;
    
    // Entry point of a thread.
    // MUST REMAIN UNCHANGED: os_pthread shall be consistent in every CMSIS-RTOS.
    //
    typedef void (*os_pthread)( void * argument );
    
    // Entry point of a timer call back function.
    // MUST REMAIN UNCHANGED: os_ptimer shall be consistent in every CMSIS-RTOS.
    //
    typedef void (*os_ptimer)( void * argument );
    
    // >>> the following data type definitions may shall adapted towards a specific RTOS
    
    // Thread ID identifies the thread (pointer to a thread control block).
    // CAN BE CHANGED: os_thread_cb is implementation specific in every CMSIS-RTOS.
    //
    typedef OS_TASK osThreadType;
    typedef osThreadType * osThreadId;
    
    // Timer ID identifies the timer (pointer to a timer control block).
    // CAN BE CHANGED: os_timer_cb is implementation specific in every CMSIS-RTOS.
    //
    typedef OS_TIMER_EX osTimerType;
    typedef osTimerType * osTimerId;
    
    // Mutex ID identifies the mutex (pointer to a mutex control block).
    // CAN BE CHANGED: os_mutex_cb is implementation specific in every CMSIS-RTOS.
    //
    typedef OS_RSEMA osMutexType;
    typedef osMutexType * osMutexId;
    
    // Semaphore ID identifies the semaphore (pointer to a semaphore control block).
    // CAN BE CHANGED: os_semaphore_cb is implementation specific in every CMSIS-RTOS.
    //
    typedef OS_CSEMA osSemaphoreType;
    typedef osSemaphoreType * osSemaphoreId;
    
    // Pool ID identifies the memory pool (pointer to a memory pool control block).
    // CAN BE CHANGED: os_pool_cb is implementation specific in every CMSIS-RTOS.
    //
    typedef OS_MEMF osPoolType;
    typedef osPoolType * osPoolId;
    
    // Message ID identifies the message queue (pointer to a message queue control block).
    // CAN BE CHANGED: os_messageQ_cb is implementation specific in every CMSIS-RTOS.
    //
    // OS_MAILBOX : Messages of fixed size
    // CMSIS_OS   : Messages of fixed size : 4 Bytes for Value or Pointer
    //
    typedef OS_MAILBOX osMessageQType;
    typedef osMessageQType * osMessageQId;
    
    // Mail ID identifies the mail queue (pointer to a mail queue control block).
    // CAN BE CHANGED: os_mailQ_cb is implementation specific in every CMSIS-RTOS.
    //
    // OS_MAILBOX : Messages of fixed size
    // CMSIS_OS   : Messages of fixed size : 1..32767 Bytes for Buffer
    //
    typedef struct _osMailQ_cb
    {
      osMessageQId messageId;
      osPoolId poolId;
    } osMailQType;
    
    typedef osMailQType * osMailQId;
    
    // Thread Definition structure contains startup information of a thread.
    // CAN BE CHANGED: os_thread_def is implementation specific in every CMSIS-RTOS.
    //
    typedef struct os_thread_def
    {
      osThreadId threadId;
      uint8_t * name;
      os_pthread pthread;     // start address of thread function
      osPriority tpriority;   // initial thread priority
      uint32_t stacksize;     // stack size requirements in bytes;
      uint32_t * stack;       //
    } osThreadDef_t;
    
    // Timer Definition structure contains timer parameters.
    // CAN BE CHANGED: os_timer_def is implementation specific in every CMSIS-RTOS.
    //
    typedef const struct os_timer_def
    {
      osTimerId timerId;
      os_ptimer ptimer;
    } osTimerDef_t;
    
    // Mutex Definition structure contains setup information for a mutex.
    // CAN BE CHANGED: os_mutex_def is implementation specific in every CMSIS-RTOS.
    //
    typedef struct os_mutex_def
    {
      osMutexId mutexId;
    } osMutexDef_t;
    
    // Semaphore Definition structure contains setup information for a semaphore.
    // CAN BE CHANGED: os_semaphore_def is implementation specific in every CMSIS-RTOS.
    //
    typedef struct os_semaphore_def
    {
      osSemaphoreId semaphoreId;
    } osSemaphoreDef_t;
    
    // Definition structure for memory block allocation.
    // CAN BE CHANGED: os_pool_def is implementation specific in every CMSIS-RTOS.
    //
    typedef struct os_pool_def
    {
      osPoolId poolId;
      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.
    // CAN BE CHANGED: os_messageQ_def is implementation specific in every CMSIS-RTOS.
    //
    typedef struct os_messageQ_def
    {
      osMessageQId messageQId;
      uint32_t queue_sz;    // number of elements in the queue
      void * pool;          // memory array for messages
    } osMessageQDef_t;
    
    // Definition structure for mail queue.
    // CAN BE CHANGED: os_mailQ_def is implementation specific in every CMSIS-RTOS.
    //
    typedef struct os_mailQ_def
    {
      osMailQId mailId;
      osMessageQDef_t * messageQDef;
      osPoolDef_t * poolDef;
      uint32_t queue_sz;      // number of elements in the queue
      uint32_t item_sz;       // size of an item
    } osMailQDef_t;
    
    // Event structure contains detailed information about an event.
    // MUST REMAIN UNCHANGED: 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 osMailCreate
        osMessageQId message_id;  // message id obtained by osMessageCreate
      } def;                      // event definition
    
    } osEvent;
    
    // ======= Kernel Control Functions ============================================
    
    // The RTOS kernel system timer frequency in Hz.
    // Reflects the system timer setting and is typically defined in a configuration file.
    #define osKernelSysTickFrequency                ( OS_FSYS )
    // The RTOS kernel frequency in Hz.
    // Reflects the system timer setting and is typically defined in a configuration file.
    #define osKernelTickFrequency                   ( OS_TICK_FREQ )
    //
    #define osKernelTickPeriod                      ( 1 / osKernelTickFrequency )
    #define osKernelTicksPerSecond                  ( osKernelTickFrequency )
    
    #if ( osKernelTickFrequency == 1000 )
    #define osKernelTicksPerMilliSec                ( 1 )
    #else
    #define osKernelTicksPerMilliSec                ( osKernelTickFrequency / 1000 )
    #endif
    
    //
    // Convert timeout in millisec to system ticks
    #if ( osKernelTickFrequency == 1000 )
    #define osKernelTicksByMilliSec( millisec )     ( millisec )
    #else
    #define osKernelTicksByMilliSec( millisec )     ( ( millisec ) * osKernelTicksPerMilliSec )
    #endif
    
    // Convert timeout in second to system ticks
    #define osKernelTicksBySecond( second )         ( ( second ) * osKernelTicksPerSecond )
    
    // Convert kernel ticks to millisec
    #if ( osKernelTickFrequency == 1000 )
    #define osKernelTicks2MilliSec( ticks )         ( ticks )
    #else
    #define osKernelTicks2MilliSec( ticks )         ( ( ticks ) / osKernelTicksPerMilliSec )
    #endif
    
    // Convert kernel ticks to second
    #define osKernelTicks2Second( ticks )           ( ( ticks ) / osKernelTicksPerSecond )
    //
    //
    #define osKernelSysTicksPerSecond               ( osKernelSysTickFrequency )
    #define osKernelSysTicksPerMilliSec             ( osKernelSysTickFrequency / 1000 )
    //
    // Convert timeout in millisec to system ticks
    #define osKernelSysTicksByMilliSec( millisec )  ( ( millisec ) * osKernelSysTicksPerMilliSec )
    // Convert timeout in second to system ticks
    #define osKernelSysTicksBySecond( second )      ( ( second ) * osKernelSysTicksPerSecond )
    // Convert system ticks to millisec
    #define osKernelSysTicks2MilliSec( ticks )      ( ( ticks ) / osKernelSysTicksPerMilliSec )
    // Convert system ticks to second
    #define osKernelSysTicks2Second( ticks )        ( ( ticks ) / osKernelSysTicksPerSecond )
    //
    
    #define osKernelSysTickMicroSec_i  
      ( osKernelSysTickFrequency / 1000000 )
    //
    #define osKernelSysTickMicroSec_f  
      ( ( ( (uint64_t)( osKernelSysTickFrequency - 1000000 * ( osKernelSysTickFrequency / 1000000 ) ) ) << 16 ) / 1000000 )
    //
    // Convert a microseconds value to a RTOS kernel system timer value.
    #define osKernelSysTickMicroSec(microsec)   
      ( ( microsec * osKernelSysTickMicroSec_i ) + ( ( microsec * osKernelSysTickMicroSec_f ) >> 16 ) )
    //
    #define osKernelSysTickMilliSec(millisec)   
      osKernelSysTicksByMilliSec(millisec)
    
    // return RTOS kernel time as 32-bit value in milli second
    //
    //#include "rt_Time.h"
    //#define osKernelTickTime                ( os_time / osKernelTicksPerMilliSec )
    //
    #define osKernelTickTime                  ( OS_Time / osKernelTicksPerMilliSec )
    #define osKernelTickCount()               OS_GetTime32()
    #define osKernelSysTick()                 OS_GetTime_Cycles()
    
    osStatus osKernelInitialize( void );
    osStatus osKernelStart( void );
    int32_t osKernelRunning( void );
    
    // ======= 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.
    // CAN BE CHANGED: The parameters to osThreadDef shall be consistent but the
    //       macro body is implementation specific in every CMSIS-RTOS.
    //
    #if defined (osObjectsExternal)
    #define osThreadDef(name, thread, priority, instances, stacksz)       
      extern osThreadDef_t os_thread_def_##name
    #else
    #define osThreadDef(name, thread, priority, instances, stacksz)       
      OS_TASK os_thread_id_##name;                                        
        uint32_t os_thread_stack_##name[ ( (stacksz ? stacksz : OS_STKSIZE ) + 3 ) / 4];      
      osThreadDef_t os_thread_def_##name =                                
          { &os_thread_id_##name, #name, (os_pthread)(thread), (priority),
            (( ( (stacksz ? stacksz : OS_STKSIZE ) + 3 ) / 4) << 2 ),     
              os_thread_stack_##name }
    #endif
    
    #define osThread(name)  
      &os_thread_def_##name
    
    osThreadId osThreadCreate( osThreadDef_t * thread_def, void * argument );
    osThreadId osThreadGetId( void );
    osStatus osThreadTerminate( osThreadId thread_id );
    osStatus osThreadYield( void );
    osStatus osThreadSetPriority( osThreadId thread_id, osPriority priority );
    osPriority osThreadGetPriority( osThreadId thread_id );
    
    // ======= Generic Wait Functions ==============================================
    //
    // Wait for Timeout (Time Delay).
    // param[in]     millisec      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))
    osEvent osWait( uint32_t millisec );
    #endif
    
    // ======= Timer Management Functions ==========================================
    //
    // Define a Timer object.
    // param         name          name of the timer object.
    // param         function      name of the timer call back function.
    // CAN BE CHANGED: The parameter to osTimerDef shall be consistent but the
    //       macro body is implementation specific in every CMSIS-RTOS.
    #if defined (osObjectsExternal)
    #define osTimerDef(name, function)          
      extern osTimerDef_t os_timer_def_##name
    #else
    #define osTimerDef(name, function)          
      OS_TIMER_EX os_timer_id_##name;           
      osTimerDef_t os_timer_def_##name =        
          {&os_timer_id_##name, (function) }
    #endif
    
    #define osTimer(name) 
      &os_timer_def_##name
    
    osTimerId osTimerCreate( osTimerDef_t * timer_def, os_timer_type type,
      void * argument );
    osStatus osTimerStart( osTimerId timer_id, uint32_t millisec );
    osStatus osTimerStop( osTimerId timer_id );
    osStatus osTimerDelete( osTimerId timer_id );
    
    // ======= Signal Management ===================================================
    //
    int32_t osSignalSet( osThreadId thread_id, int32_t signals );
    int32_t osSignalClear( osThreadId thread_id, int32_t signals );
    osEvent osSignalWait( int32_t signals, uint32_t millisec );
    
    // ======= Mutex Management ====================================================
    #if defined (osObjectsExternal)
    #define osMutexDef(name)  
      extern osMutexDef_t os_mutex_def_##name
    #else
    #define osMutexDef(name)  
      OS_RSEMA os_mutex_id_##name; 
      osMutexDef_t os_mutex_def_##name = { &os_mutex_id_##name }
    #endif
    
    #define osMutex(name)  
      &os_mutex_def_##name
    
    osMutexId osMutexCreate( osMutexDef_t * mutex_def );
    osStatus osMutexWait( osMutexId mutex_id, uint32_t millisec );
    osStatus osMutexRelease( osMutexId mutex_id );
    osStatus osMutexDelete( osMutexId mutex_id );
    
    // ======= Semaphore Management Functions ======================================
    
    #if (defined (osFeature_Semaphore)  &&  (osFeature_Semaphore != 0))
    //
    // Define a Semaphore object.
    // param         name          name of the semaphore object.
    // CAN BE CHANGED: The parameter to osSemaphoreDef shall be consistent but the
    //       macro body is implementation specific in every CMSIS-RTOS.
    //
    #if defined (osObjectsExternal)
    #define osSemaphoreDef(name)                              
      extern osSemaphoreDef_t os_semaphore_def_##name
    #else
    #define osSemaphoreDef(name)                              
      OS_CSEMA os_semaphore_id_##name;                        
      osSemaphoreDef_t os_semaphore_def_##name = { &os_semaphore_id_##name }
    #endif
    
    #define osSemaphore(name)  
      &os_semaphore_def_##name
    
    osSemaphoreId osSemaphoreCreate( osSemaphoreDef_t * semaphore_def,
      int32_t count );
    int32_t osSemaphoreWait( osSemaphoreId semaphore_id, uint32_t millisec );
    osStatus osSemaphoreRelease( osSemaphoreId semaphore_id );
    osStatus osSemaphoreDelete( osSemaphoreId semaphore_id );
    
    #endif
    
    // ============= Memory Pool Management Functions ==============================
    //
    #if (defined (osFeature_Pool)  &&  (osFeature_Pool != 0))
    //
    // rief 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).
    // CAN BE CHANGED: The parameter to osPoolDef shall be consistent but the
    //       macro body is implementation specific in every CMSIS-RTOS.
    #if defined (osObjectsExternal)
    #define osPoolDef(name, no, type)   
      extern osPoolDef_t os_pool_def_##name
    #else
    #define osPoolDef(name, no, type)   
      OS_MEMF os_pool_id_##name; 
      uint32_t 
      os_pool_m_##name[ ( ( OS_MEMF_SIZEOF_BLOCKCONTROL + sizeof(type) + 3 ) / 4) * (no) ]; 
      osPoolDef_t 
      os_pool_def_##name = 
                           { &os_pool_id_##name, (no), 
                             ( ( ( OS_MEMF_SIZEOF_BLOCKCONTROL + sizeof(type) + 3 ) / 4) << 2 ), 
                             (os_pool_m_##name) }
    #endif
    
    #define osPool(name) 
      &os_pool_def_##name
    
    osPoolId osPoolCreate( osPoolDef_t * pool_def );
    void * osPoolAlloc( osPoolId pool_id );
    void * osPoolCAlloc( osPoolId pool_id );
    osStatus osPoolFree( osPoolId pool_id, void * block );
    
    #endif
    
    // ======= Message Queue Management Functions ==================================
    
    #if (defined (osFeature_MessageQ)  &&  (osFeature_MessageQ != 0))
    //
    // rief 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).
    // CAN BE CHANGED: The parameter to osMessageQDef shall be consistent but the
    //       macro body is implementation specific in every CMSIS-RTOS.
    //
    #if defined (osObjectsExternal)
    #define osMessageQDef(name, queue_sz, type)   
      extern osMessageQDef_t os_messageQ_def_##name
    #else
    #define osMessageQDef(name, queue_sz, type)   
      OS_MAILBOX os_messageQ_id_##name;
      uint32_t os_messageQ_q_##name[ (queue_sz) ] = { 0 }; 
      osMessageQDef_t os_messageQ_def_##name = 
          { &os_messageQ_id_##name, (queue_sz << 2 ) , (os_messageQ_q_##name) }
    #endif
    
    #define osMessageQ(name) 
      &os_messageQ_def_##name
    
    osMessageQId osMessageCreate( osMessageQDef_t * queue_def,
      osThreadId thread_id );
    osStatus osMessagePut( osMessageQId queue_id, uint32_t info, uint32_t millisec );
    osEvent osMessageGet( osMessageQId queue_id, uint32_t millisec );
    osStatus osMessageDelete( osMessageQId queue_id );
    
    #endif
    // ======= Mail Queue Management Functions =====================================
    #if (defined (osFeature_MailQ)  &&  (osFeature_MailQ != 0))
    //
    // rief 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
    // CAN BE CHANGED: The parameter to osMailQDef shall be consistent but the
    //       macro body is implementation specific in every CMSIS-RTOS.
    //
    #if defined (osObjectsExternal)
    #define osMailQDef(name, queue_sz, type) 
      extern osMailQDef_t os_mailQ_def_##name
    #else
    #define osMailQDef(name, queue_sz, type) 
      osMailQ_cb os_MailQ_id_##name;
      osPoolDef(mail_##name, queue_sz, type); 
      osMessageQDef(mail_##name, queue_sz); 
      osMailQDef_t os_mailQ_def_##name =  
                                          { &os_MailQ_id_##name, osMessageQ(mail_##name), osPool(mail_##name), 
                                            queue_sz, ( ( (sizeof(type) + 3) >> 2 ) << 2 ) }
    #endif
    
    #define osMailQ(name)  
      &os_mailQ_def_##name
    osMailQId osMailCreate( osMailQDef_t * queue_def, osThreadId thread_id );
    void * osMailAlloc( osMailQId queue_id, uint32_t millisec );
    void * osMailCAlloc( osMailQId queue_id, uint32_t millisec );
    osStatus osMailPut( osMailQId queue_id, void * mail );
    osEvent osMailGet( osMailQId queue_id, uint32_t millisec );
    osStatus osMailFree( osMailQId queue_id, void * mail );
    
    #endif
    
    // ============= Memory Management Functions ===================================
    
    osStatus osMemoryLock( uint32_t timeout );
    
    void osMemoryUnlock( void );
    
    /*
     * ANSI C offers some basic dynamic memory management functions.
     * These are malloc, free, and realloc. Unfortunately, these routines are
     * not thread-safe, unless a special thread-safe implementation exists
     * in the compiler specific runtime libraries; they can only be used from
     * one task or by multiple tasks if they are called sequentially.
     *
     * Therefore, embOS offer task-safe variants of these routines.
     * These variants have the same names as their ANSI counterparts,
     * but are prefixed OS_; they are called OS_malloc(), OS_free(), OS_realloc().
     *
     * The thread-safe variants that embOS offers use the standard ANSI routines,
     * but they guarantee that the calls are serialized using a resource semaphore.
     *
     * If heap memory management is not supported by the standard C-libraries
     * for a specific CPU, embOS heap memory management is not implemented.
     *
     * Heap type memory management is part of the embOS libraries.
     * It does not use any resources if it is not referenced by the application
     * (that is, if the application does not use any memory management API function).
     *
     * Note that another aspect of these routines may still be a problem:
     * the memory used for the functions (known as heap) may fragment.
     *
     * This can lead to a situation where the total amount of memory is sufficient,
     * but there is not enough memory available in a single block
     * to satisfy an allocation request.
     *
     */
    
    /* Allocates a block of size bytes of memory, returning a pointer
     * to the beginning of the block. The content of the newly allocated block of
     * memory is not initialized, remaining with indeterminate values.
     *
     * On success, a pointer to the memory block allocated by the function.
     * The type of this pointer is always void*, which can be cast to the desired
     * type of data pointer in order to be dereferenceable.
     *
     * If the function failed to allocate the requested block of memory,
     * a null pointer is returned.
     *
     */
    void * osMalloc( size_t size, uint32_t timeout );
    
    /* Allocates a block of memory for an array of num elements,
     * each of them size bytes long, and initializes all its bits to zero.
     *
     * The effective result is the allocation of a zero-initialized memory block
     * of (num*size) bytes.
     *
     * On success, a pointer to the memory block allocated by the function.
     * The type of this pointer is always void*, which can be cast to the desired
     * type of data pointer in order to be dereferenceable.
     *
     * If the function failed to allocate the requested block of memory,
     * a null pointer is returned.
     *
     */
    void * osCalloc( size_t nelem, size_t elsize, uint32_t timeout );
    
    /* Changes the size of the memory block pointed to by ptr.
     * The function may move the memory block to a new location (whose address is
     * returned by the function).
     *
     * The content of the memory block is preserved up to the lesser of the new
     * and old sizes, even if the block is moved to a new location.
     *
     * If the new size is larger, the value of the newly allocated portion
     * is indeterminate.
     *
     * In case that ptr is a null pointer, the function behaves like malloc,
     * assigning a new block of size bytes and returning a pointer to its beginning.
     *
     * If the function fails to allocate the requested block of memory,
     * a null pointer is returned, and the memory block pointed to by argument ptr
     * is not deallocated (it is still valid, and with its contents unchanged).
     *
     * A pointer to the reallocated memory block, which may be either the same
     * as ptr or a new location. The type of this pointer is void*, which can be
     * cast to the desired type of data pointer in order to be dereferenceable.
     */
    void * osRealloc( void * ptr, size_t size, uint32_t timeout );
    
    /* A block of memory previously allocated by a call to malloc, calloc or realloc
     * is deallocated, making it available again for further allocations.
     *
     * If ptr does not point to a block of memory allocated with the above functions
     * it causes undefined behavior.
     * If ptr is a null pointer, the function does nothing.
     *
     * Notice that this function does not change the value of ptr itself,
     * hence it still points to the same (now invalid) location.
     *
     */
    void osFree( void * ptr );
    
    /*
     * Informs RTOS that interrupt code is executing.
     *
     * If osEnterInterrupt() is used, it should be the first function to be called
     * in the interrupt handler. It must be used with osLeaveInterrupt() as the last
     * function called. The use of this function has the following effects, it:
     *
     * disables task switches
     * keeps interrupts in internal routines disabled.
     */
    void osEnterInterrupt( void );
    
    /*
     * Informs RTOS that the end of the interrupt routine has been reached;
     * executes task switching within ISR.
     *
     * If osLeaveInterrupt()is used, it should be the last function to be called
     * in the interrupt handler. If the interrupt has caused a task switch, it will
     * be executed (unless the program which was interrupted was in a critical region).
     *
     */
    void osLeaveInterrupt( void );
    
    uint32_t osDisableInterrupt( void );
    
    void osRestoreInterrupt( uint32_t val );
    
    #ifdef  __cplusplus
    }
    #endif
    
    #endif  // __CMSIS_OS_H__
    #include "cmsis_os.h"
    #include <stdlib.h>
    
    #define CMSIS2EMBOS(x)    ((x)+3)
    #define EMBOS2CMSIS(x)    ( (osPriority)( (x) -3) )
    
    CMSIS_OS_GLOBAL os_global;
    
    //
    // System Timer available
    //
    // Get the RTOS kernel system timer counter.
    // MUST REMAIN UNCHANGED: osKernelSysTick shall be consistent in every CMSIS-RTOS.
    // return : RTOS kernel system timer as 32-bit value
    uint32_t osKernelSysTick0( void )
    {
      // returns the system time in timer clock cycles
      return OS_GetTime_Cycles( );
    }
    
    // ============= Kernel Control Functions ======================================
    //
    // Initialize the RTOS Kernel for creating objects.
    // return : status code that indicates the execution status of the function.
    // MUST REMAIN UNCHANGED: osKernelInitialize shall be consistent in every CMSIS-RTOS.
    //
    osStatus osKernelInitialize( void )
    {
      OS_IncDI();
      OS_InitKern( );
      OS_InitHW( );
      return osOK;
    }
    
    // Start the RTOS Kernel.
    // return : status code that indicates the execution status of the function.
    // MUST REMAIN UNCHANGED: osKernelStart shall be consistent in every CMSIS-RTOS.
    //
    osStatus osKernelStart( void )
    {
      /* This function starts the embOS scheduler and schould be the last function
       * called from main().
       *
       * It will activate and start the task with the highest priority.
       * automatically enables interrupts, and never return
       */
      OS_Running = 1u;
      OS_StartASM( );
      return osOK;
    }
    
    osStatus osKernelStartThread( osThreadDef_t * thread_def, void * argument )
    {
      osThreadCreate( thread_def, argument );
      return osKernelStart( );
    }
    
    // Check if the RTOS kernel is already started.
    // MUST REMAIN UNCHANGED: osKernelRunning shall be consistent in every CMSIS-RTOS.
    // return : 0 RTOS is not started, 1 RTOS is started.
    //
    int32_t osKernelRunning( void )
    {
      return OS_IsRunning(); // OS_Running;
    }
    
    // ============= Thread Management =============================================
    //
    // Create a thread and add it to Active Threads and set it to state READY.
    // param[in]   thread_def  thread definition referenced with 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.
    // MUST REMAIN UNCHANGED: osThreadCreate shall be consistent in every CMSIS-RTOS.
    //
    osThreadId osThreadCreate( osThreadDef_t * thread_def, void * argument )
    {
      OS_CreateTaskEx( thread_def->threadId, (char *) thread_def->name,
        CMSIS2EMBOS( thread_def->tpriority ),
        (void (*)( void * )) ( thread_def->pthread ), thread_def->stack,
        thread_def->stacksize, 2, argument );
      return thread_def->threadId;
    }
    
    // Return the thread ID of the current running thread.
    // return : thread ID for reference by other functions or NULL in case of error.
    // MUST REMAIN UNCHANGED: osThreadGetId shall be consistent in every CMSIS-RTOS.
    //
    osThreadId osThreadGetId( void )
    {
      return OS_GetTaskID();
    }
    
    // Terminate execution of a thread and remove it from Active Threads.
    // param[in]   thread_id   thread ID obtained by osThreadCreate or osThreadGetId.
    // return : status code that indicates the execution status of the function.
    // MUST REMAIN UNCHANGED: osThreadTerminate shall be consistent in every CMSIS-RTOS.
    //
    osStatus osThreadTerminate( osThreadId thread_id )
    {
      // If pTaskis the NULLpointer, the current task terminates.
      // The specified task will terminate immediately.
      // The memory used for stack and task control block can be reassigned.
      OS_TerminateTask( thread_id );
      return osOK;
    }
    
    // Pass control to next thread that is in state READY.
    // return : status code that indicates the execution status of the function.
    // MUST REMAIN UNCHANGED: osThreadYield shall be consistent in every CMSIS-RTOS.
    //
    osStatus osThreadYield( void )
    {
      // Calls the scheduler to force a task switch.
      OS_Yield( );
      return osOK;
    }
    
    // Change priority of an active thread.
    // param[in]   thread_id   thread ID obtained by osThreadCreate or osThreadGetId.
    // param[in]   priority    new priority value for the thread function.
    // return : status code that indicates the execution status of the function.
    // MUST REMAIN UNCHANGED: osThreadSetPriority shall be consistent in every CMSIS-RTOS.
    //
    osStatus osThreadSetPriority( osThreadId thread_id, osPriority priority )
    {
      OS_SetPriority( thread_id, CMSIS2EMBOS( priority ) );
      return osOK;
    }
    
    // Get current priority of an active thread.
    // param[in]   thread_id   thread ID obtained by osThreadCreate or osThreadGetId.
    // return : current priority value of the thread function.
    // MUST REMAIN UNCHANGED: osThreadGetPriority shall be consistent in every CMSIS-RTOS.
    //
    osPriority osThreadGetPriority( osThreadId thread_id )
    {
      return EMBOS2CMSIS( OS_GetPriority( thread_id ) );
    }
    
    // ============= Generic Wait Functions ========================================
    //
    // Wait for Timeout (Time Delay).
    // param[in]   millisec    time delay value
    // return : status code that indicates the execution status of the function.
    //
    osStatus osDelay( uint32_t millisec )
    {
      OS_Delay( osKernelTicksByMilliSec( millisec ) );
      return osOK;
    }
    
    // Generic Wait available
    //
    // Wait for Signal, Message, Mail, or Timeout.
    // param[in] millisec      timeout value or 0 in case of no time-out
    // return : event that contains signal, message, or mail information or error code.
    // MUST REMAIN UNCHANGED: osWait shall be consistent in every CMSIS-RTOS.
    //
    osEvent osWait( uint32_t millisec )
    {
      osEvent event;
      event.status = osOK;
      return event;
    }
    
    // ============= Timer Management Functions ====================================
    //
    // Create a timer.
    // param[in]   timer_def   timer object referenced with 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.
    // MUST REMAIN UNCHANGED: osTimerCreate shall be consistent in every CMSIS-RTOS.
    //
    osTimerId osTimerCreate( osTimerDef_t * timer_def, os_timer_type type,
      void * argument )
    {
      OS_CreateTimerEx( timer_def->timerId,
        (OS_TIMER_EX_ROUTINE *) ( timer_def->ptimer ), -1, argument );
      return timer_def->timerId;
    }
    
    // Start or restart a timer.
    // param[in]   timer_id    timer ID obtained by osTimerCreate.
    // param[in]   millisec    time delay value of the timer.
    // return : status code that indicates the execution status of the function.
    // MUST REMAIN UNCHANGED: osTimerStart shall be consistent in every CMSIS-RTOS.
    //
    osStatus osTimerStart( osTimerId timer_id, uint32_t millisec )
    {
      OS_SetTimerPeriodEx( timer_id, osKernelTicksByMilliSec( millisec ) );
      OS_RetriggerTimerEx( timer_id );
      return osOK;
    }
    
    // Stop the timer.
    // param[in]   timer_id    timer ID obtained by osTimerCreate.
    // return : status code that indicates the execution status of the function.
    // MUST REMAIN UNCHANGED: osTimerStop shall be consistent in every CMSIS-RTOS.
    //
    osStatus osTimerStop( osTimerId timer_id )
    {
      OS_StopTimerEx( timer_id );
      return osOK;
    }
    
    // Delete a timer that was created by osTimerCreate.
    // param[in]   timer_id    timer ID obtained by osTimerCreate.
    // return : status code that indicates the execution status of the function.
    // MUST REMAIN UNCHANGED: osTimerDelete shall be consistent in every CMSIS-RTOS.
    //
    osStatus osTimerDelete( osTimerId timer_id )
    {
      OS_DeleteTimerEx( timer_id );
      return osOK;
    }
    
    // ============= Signal Management =============================================
    //
    // Set the specified Signal Flags of an active thread.
    // param[in]   thread_id   thread ID obtained by osThreadCreate or 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.
    // MUST REMAIN UNCHANGED: osSignalSet shall be consistent in every CMSIS-RTOS.
    //
    int32_t osSignalSet( osThreadId thread_id, int32_t signals )
    {
      // Returns a list of events that have occurred for a specified task.
      // The event mask of the events that have actually occurred
      // the actual events remain signaled
      //
      int32_t result = OS_GetEventsOccurred( thread_id );
      OS_SignalEvent( signals, thread_id );
      return result;
    }
    
    int32_t OS_ClearEvent( osThreadId thread_id, int32_t signals )
    {
      if ( thread_id == 0 )
        thread_id = osThreadGetId( );
      int32_t result = thread_id.Events;
      // uint32_t val = osDisableInterrupt( );
      OS_DisableInt( );   // MOV.W   R1, #0x80   MSR.W   BASEPRI, R1
      thread_id.Events &= ~signals;
      if ( OS_Global.Counters.Cnt.DI == 0 )
        OS_EnableInt( );  // MOV.W   R1, #0x00   MSR.W   BASEPRI, R1
      // osRestoreInterrupt( val );
      return result;
    }
    
    // Clear the specified Signal Flags of an active thread.
    // param[in]   thread_id   thread ID obtained by osThreadCreate or 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.
    // MUST REMAIN UNCHANGED: osSignalClear shall be consistent in every CMSIS-RTOS.
    //
    int32_t osSignalClear( osThreadId thread_id, int32_t signals )
    {
      // Returns the actual state of events
      // and then clears the events of a specified task.
      // Returns the actual state of events and then
      // clears ** the ALL events ** of a specified task.
      //
      // return OS_ClearEvents( thread_id );
      //
      return OS_ClearEvent( thread_id );
    }
    
    // Wait for one or more Signal Flags to become signaled for the current RUNNING thread.
    // param[in]   signals     wait until all specified signal flags set or 0 for any single signal flag.
    // param[in]   millisec    timeout value or 0 in case of no time-out.
    // return : event flag information or error code.
    // MUST REMAIN UNCHANGED: osSignalWait shall be consistent in every CMSIS-RTOS.
    //
    osEvent osSignalWait( int32_t signals, uint32_t millisec )
    {
      osEvent event;
      event.status = osEventSignal;
    
      // Not allowed in ISR ?
      // event.status = osErrorISR
      //
      // The task is not suspended even if no events are signaled.
      if ( millisec == 0 )
      {
        // Returns a list of events that have occurred for a specified task.
        // The event mask of the events that have actually occurred.
        event.value.signals = OS_GetEventsOccurred( 0 );
      }
    
      else if ( millisec == osWaitForever )
      {
        if ( signals == 0 ) // Wait forever until any single signal flag
        {
          // Waits for one of the events specified in the bitmask and
          // clears the event memory after an event occurs
          event.value.signals = OS_WaitEvent( 0xFFFFFFFF );
        }
    
        else // Wait forever until all specified signal flags set
        {
          // Waits for one or more of the events specified by the Eventmask
          // and clears only those events that were specified in the eventmask.
          event.value.signals = OS_WaitSingleEvent( signals );
        }
      }
    
      else
      {
        if ( signals == 0 ) // Wait millisec until any single signal flag
        {
          // Waits for the specified events for a given time, and clears
          // ** the event memory ** after one of the requsted events occurs,
          // or after the timeout expired.
          event.value.signals = OS_WaitEventTimed( 0xFFFFFFFF,
            osKernelTicksByMilliSec( millisec ) );
        }
    
        else // Wait millisec until all specified signal flags set
        {
          // Waits for the specified events for a given time; after an event occurs,
          // only ** the requested events ** are cleared.
          event.value.signals = OS_WaitSingleEventTimed( signals,
            osKernelTicksByMilliSec( millisec ) );
        }
      }
    
      if ( event.value.signals == 0 )
      {
        event.status = ( millisec > 0 ) ? osEventTimeout : osOK;
      }
    
      return event;
    }
    
    // ============= Mutex Management ==============================================
    //
    /* Resource semaphores are used for managingresources by avoiding conflicts
     * caused by simultaneous use of a resource. The resource managed can be of
     * any kind: a part of the program that is not reentrant, a piece of hardware
     * like the display, a flash prom that can only be written to by a single task
     * at a time, a motor in a CNC control that can only be controlled by one task
     * at a time, and a lot more.
     *
     * The basic procedure is as follows:
     * Any task that uses a resource first claims it calling the OS_Use() or
     * OS_Request() routines of embOS. If the resource is available, the program
     * execution of the task continues, but the resource is blocked for other tasks.
     *
     * If a second task now tries to use the same resource while it is in use
     * by the first task, this second task is suspended until the first task releases
     * the resource. However, if the first task that uses the resource calls
     * OS_Use() again for that resource, it is not suspended because the resource
     * is blocked only for other tasks.
     *
     * A resource semaphore contains a counter that keeps track of how many times
     * the resource has been claimed by calling OS_Request() or OS_Use()
     * by a particular task. It is released when that counter reaches 0,
     * which means the OS_Unuse() routine has to be called exactly the same number
     * of times as OS_Use() or OS_Request(). If it is not, the resource remains
     * blocked for other tasks.
     *
     * On the other hand, a task cannot release a resource that it does not own
     * by calling OS_Unuse().
     *
     * counter = 0 after OS_CreateRSema()
     * counter++ : OS_Use() or OS_Request()
     * counter-- : OS_Unuse()
     *
     * A programmer can prefer mutex rather than creating a semaphore with count 1.
     */
    // Create and Initialize a Mutex object.
    // param[in]   mutex_def   mutex definition referenced with osMutex.
    // return : mutex ID for reference by other functions or NULL in case of error.
    // MUST REMAIN UNCHANGED: osMutexCreate shall be consistent in every CMSIS-RTOS.
    //
    osMutexId osMutexCreate( osMutexDef_t * mutex_def )
    {
      OS_CreateRSema( mutex_def->mutexId );
      return mutex_def->mutexId;
    }
    
    // Wait until a Mutex becomes available.
    // param[in]   mutex_id    mutex ID obtained by osMutexCreate.
    // param[in]   millisec    timeout value or 0 in case of no time-out.
    // return : status code that indicates the execution status of the function.
    // MUST REMAIN UNCHANGED: osMutexWait shall be consistent in every CMSIS-RTOS.
    //
    osStatus osMutexWait( osMutexId mutex_id, uint32_t millisec )
    {
      osStatus status = osOK;
    
      if ( millisec == 0 )
      {
        if ( OS_Request( mutex_id ) == 0 )
        {
          status = osErrorResource;
        }
      }
    
      else if ( millisec == osWaitForever )
      {
        OS_Use( mutex_id );
      }
    
      else if ( 0 == OS_UseTimed( mutex_id, osKernelTicksByMilliSec( millisec ) ) )
      {
        status = osErrorTimeoutResource;
      }
    
      return status;
    }
    
    // Release a Mutex that was obtained by osMutexWait.
    // param[in]   mutex_id    mutex ID obtained by osMutexCreate.
    // return : status code that indicates the execution status of the function.
    // MUST REMAIN UNCHANGED: osMutexRelease shall be consistent in every CMSIS-RTOS.
    //
    osStatus osMutexRelease( osMutexId mutex_id )
    {
      OS_Unuse( mutex_id );
      return osOK;
    }
    
    // Delete a Mutex that was created by osMutexCreate.
    // param[in]   mutex_id    mutex ID obtained by osMutexCreate.
    // return : status code that indicates the execution status of the function.
    // MUST REMAIN UNCHANGED: osMutexDelete shall be consistent in every CMSIS-RTOS.
    //
    osStatus osMutexDelete( osMutexId mutex_id )
    {
      OS_DeleteRSema( mutex_id );
      return osOK;
    }
    
    // ============= Semaphore Management Functions ================================
    /* Counting semaphores are counters that are managed by embOS.
     * They are not as widely used as resource semaphores, events or mailboxes,
     * but they can be very useful sometimes.
     *
     * They are used in situations where a task needs to wait for something
     * that can be signaled one or more times.
     *
     * The semaphores can be accessed from any point, any task,
     * or any interrupt in any way.
     *
     * OS_CreateCSema()
     * Creates a counting semaphore with a specified initial count value
     *
     * OS_SignalCSema()
     * Increments the counter of a semaphore.
     * If one or more tasks are waiting for an event to be signaled to this
     * semaphore, the task that has the highest priority will become the running task
     *
     * OS_WaitCSema()
     * Decrements the counter of a semaphore.
     * If the counter of the semaphore is not 0, the counter is decremented
     * and program execution continues.
     * If the counter is 0, WaitCSema()waits until the counter is incremented by
     * another task, a timer or an interrupt handler via a call to OS_SignalCSema().
     * The counter is then decremented and program execution continues.
     *
     * OS_WaitCSemaTimed()
     * Decrements a semaphore counter if the semaphore is available
     * within a specified time.
     * If the semaphore was not signaled within the specified time, the program
     * execution continues but returns a value of 0.
     *
     * OS_CSemaRequest()
     * Decrements the counter of a semaphore, if it is signaled.
     * If the counter is 0, OS_CSemaRequest() does not wait and does not modify
     * the semaphore counter. The function returns with error state.
     *
     */
    
    // Create and Initialize a Semaphore object used for managing resources.
    // param[in]   semaphore_def semaphore definition referenced with osSemaphore.
    // param[in]   count     number of available resources.
    // return : semaphore ID for reference by other functions or NULL in case of error.
    // MUST REMAIN UNCHANGED: osSemaphoreCreate shall be consistent in every CMSIS-RTOS.
    //
    osSemaphoreId osSemaphoreCreate( osSemaphoreDef_t * semaphore_def,
      int32_t count )
    {
      // Creates a counting semaphore with a specified initial count value.
      OS_CreateCSema( semaphore_def->semaphoreId, count );
      return semaphore_def->semaphoreId;
    }
    
    // Wait until a Semaphore token becomes available.
    // param[in]  semaphore_id  semaphore object referenced with osSemaphoreCreate.
    // param[in]  millisec      timeout value or 0 in case of no time-out.
    // return :   number of available tokens : (tokens after wait) + 1
    //            or -1 in case of incorrect parameters.
    // MUST REMAIN UNCHANGED: osSemaphoreWait shall be consistent in every CMSIS-RTOS.
    //
    int32_t osSemaphoreWait( osSemaphoreId semaphore_id, uint32_t millisec )
    {
      int32_t result = -1; // OS_WaitCSemaTimed() timeout
    
      if ( millisec == 0 )
      {
        // Decrements the counter of a semaphore, if it is signaled
        if ( OS_CSemaRequest( semaphore_id ) )
        {
          // Returns the counter value of a specified semaphore
          result = OS_GetCSemaValue( semaphore_id );
        }
      }
    
      else if ( millisec == osWaitForever )
      {
        // Decrements the counter of a semaphore
        // If the counter of the semaphore is not 0, the counter is decremented
        // and program execution continues.
        // If the counter is 0, WaitCSema() waits until the counter is incremented
        // by another task, a timer or an interrupt handler
        // via a call to OS_SignalCSema().
        OS_WaitCSema( semaphore_id );
    
        // Returns the counter value of a specified semaphore
        result = OS_GetCSemaValue( semaphore_id );
      }
      // Decrements a semaphore counter if the semaphore is available
      // within a specified time.
      else if ( OS_WaitCSemaTimed( semaphore_id,
        osKernelTicksByMilliSec( millisec ) ) )
      {
        result = OS_GetCSemaValue( semaphore_id );
      }
    
      return result + 1;
    }
    
    /**
     * @brief Release a Semaphore token
     * @param  semaphore_id  semaphore object referenced with osSemaphore.
     * @retval  status code that indicates the execution status of the function.
     * @note   MUST REMAIN UNCHANGED: osSemaphoreRelease shall be consistent in every CMSIS-RTOS.
     */
    osStatus osSemaphoreRelease( osSemaphoreId semaphore_id )
    {
      // Increments the counter of a semaphore
      // If one or more tasks are waiting for an event to be signaled to
      // this semaphore, the task that has the highest priority will
      // become the running task.
      OS_SignalCSema( semaphore_id );
      return osOK;
    }
    
    // Release a Semaphore token.
    // param[in]     semaphore_id  semaphore object referenced with osSemaphoreCreate.
    // return :  status code that indicates the execution status of the function.
    // MUST REMAIN UNCHANGED: osSemaphoreRelease shall be consistent in every CMSIS-RTOS.
    //
    osStatus osSemaphoreDelete( osSemaphoreId semaphore_id )
    {
      // Deletes a specified semaphore.
      // Before deleting a semaphore, make sure that no task is waiting for it
      // and that notask will signal that semaphore at a later point.
      OS_DeleteCSema( semaphore_id );
      return osOK;
    }
    
    // ============= Memory Pool Management Functions ==============================
    
    // Create and Initialize a memory pool.
    // param[in]   pool_def    memory pool definition referenced with osPool.
    // return : memory pool ID for reference by other functions or NULL in case of error.
    // MUST REMAIN UNCHANGED: osPoolCreate shall be consistent in every CMSIS-RTOS.
    //
    osPoolId osPoolCreate( osPoolDef_t * pool_def )
    {
      // void OS_MEMF_Create (OS_MEMF* pMEMF, void* pPool, OS_UINT NumBlocks, OS_UINT BlockSize);
      // BlockSize is aligment at 4 Bytes !!!
      //
      OS_MEMF_Create( pool_def->poolId, pool_def->pool, pool_def->pool_sz,
        pool_def->item_sz );
      return pool_def->poolId;
    }
    
    // Allocate a memory block from a memory pool.
    // param[in]   pool_id     memory pool ID obtain referenced with osPoolCreate.
    // return : address of the allocated memory block or NULL in case of no memory available.
    // MUST REMAIN UNCHANGED: osPoolAlloc shall be consistent in every CMSIS-RTOS.
    //
    // Requests allocation of a memory block.
    // Waits until a block of memory is available
    // If there is no free memory block in the pool, the calling task is suspended
    // until a memory block becomes available.
    //
    void * osPoolAlloc( osPoolId pool_id )
    {
      return OS_MEMF_Alloc( pool_id, 0 );
    }
    
    // Requests allocation of a memory block. Waits until a block of memory
    // is available or the timeout has expired.
    //
    void * osPoolAllocTimed( osPoolId pool_id, uint32_t millisec )
    {
      return OS_MEMF_AllocTimed( pool_id, osKernelTicksByMilliSec( millisec ), 0 );
    }
    
    // Requests allocation of a memory block. Continues execution in any case.
    // The calling task is never suspended by calling OS_MEMF_Request()
    //
    void * osPoolRequest( osPoolId pool_id )
    {
      return OS_MEMF_Request( pool_id, 0 );
    }
    
    // Allocate a memory block from a memory pool and set memory block to zero.
    // param[in]   pool_id     memory pool ID obtain referenced with osPoolCreate.
    // return : address of the allocated memory block or NULL in case of no memory available.
    // MUST REMAIN UNCHANGED: osPoolCAlloc shall be consistent in every CMSIS-RTOS.
    void * osPoolCAlloc( osPoolId pool_id )
    {
      void * p = osPoolAlloc( pool_id );
    
      if ( p )
      {
        memset( p, 0, pool_id->BlockSize );
      }
    
      return p;
    }
    
    // Return an allocated memory block back to a specific memory pool.
    // param[in]   pool_id     memory pool ID obtain referenced with 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.
    // MUST REMAIN UNCHANGED: osPoolFree shall be consistent in every CMSIS-RTOS.
    osStatus osPoolFree( osPoolId pool_id, void * block )
    {
      OS_MEMF_Release( pool_id, block );
      return osOK;
    }
    
    // ============= Message Queue Management Functions =============================
    
    // Create and Initialize a Message Queue.
    // param[in]   queue_def   queue definition referenced with osMessageQ.
    // param[in]   thread_id   thread ID (obtained by osThreadCreate or osThreadGetId) or NULL.
    // return : message queue ID for reference by other functions or NULL in case of error.
    // MUST REMAIN UNCHANGED: osMessageCreate shall be consistent in every CMSIS-RTOS.
    //
    osMessageQId osMessageCreate( osMessageQDef_t * queue_def,
      osThreadId thread_id )
    {
      OS_CreateMB( queue_def->messageQId, 4, queue_def->queue_sz, queue_def->pool );
      return queue_def->messageQId;
    }
    
    // Put a Message to a Queue.
    // param[in]   queue_id    message queue ID obtained with osMessageCreate.
    // param[in]   info      message information.
    // param[in]   millisec    timeout value or 0 in case of no time-out.
    // return : status code that indicates the execution status of the function.
    // MUST REMAIN UNCHANGED: osMessagePut shall be consistent in every CMSIS-RTOS.
    //
    osStatus osMessagePut( osMessageQId queue_id, uint32_t info, uint32_t millisec )
    {
      osStatus status = osOK;
    
      if ( millisec == 0 )
      {
        if ( OS_PutMailCond( queue_id, (const void *) &info ) > 0 )
        {
          status = osErrorResource;
        }
      }
      else if ( millisec == osWaitForever )
      {
        OS_PutMail( queue_id, (const void *) &info );
      }
      else
      {
        OS_TIME osKernelTickCountPrev = osKernelTickCount();
    
        while ( 1 )
        {
          if ( OS_PutMailCond( queue_id, (const void *) &info ) == 0 )
            return status;
    
          osDelay( 1 );
    
          if ( ( osKernelTickCount() - osKernelTickCountPrev )
            > osKernelTicksByMilliSec( millisec ) )
            return osErrorTimeoutResource;
        }
      }
    
      return status;
    }
    
    // Get a Message or Wait for a Message from a Queue.
    // param[in]   queue_id    message queue ID obtained with osMessageCreate.
    // param[in]   millisec    timeout value or 0 in case of no time-out.
    // return : event information that includes status code.
    // MUST REMAIN UNCHANGED: osMessageGet shall be consistent in every CMSIS-RTOS.
    //
    osEvent osMessageGet( osMessageQId queue_id, uint32_t millisec )
    {
      osEvent event;
      event.status = osEventMessage;
    
      // The task is not suspended even if no events are signaled.
      if ( millisec == 0 )
      {
        if ( OS_GetMailCond( queue_id, &event.value.v ) > 0 )
        {
          event.status = osOK;
        }
      }
    
      else if ( millisec == osWaitForever )
      {
        OS_GetMail( queue_id, &event.value.v );
      }
    
      else if ( OS_GetMailTimed( queue_id, &event.value.v,
        osKernelTicksByMilliSec( millisec ) ) > 0 )
      {
        event.status = osEventTimeout;
      }
    
      return event;
    }
    
    osStatus osMessageDelete( osMessageQId queue_id )
    {
      OS_DeleteMB( queue_id );
      return osOK;
    }
    
    // ============= Mail Queue Management Functions ===============================
    
    // Mail Queues available
    // Create and Initialize mail queue.
    // param[in]   queue_def   reference to the mail queue definition obtain with osMailQ
    // param[in]   thread_id   thread ID (obtained by osThreadCreate or osThreadGetId) or NULL.
    // return : mail queue ID for reference by other functions or NULL in case of error.
    // MUST REMAIN UNCHANGED: osMailCreate shall be consistent in every CMSIS-RTOS.
    //
    osMailQId osMailCreate( osMailQDef_t * queue_def, osThreadId thread_id )
    {
      queue_def->mailId->messageId = osMessageCreate( queue_def->messageQDef,
        thread_id );
      queue_def->mailId->poolId = osPoolCreate( queue_def->poolDef );
      return queue_def->mailId;
    }
    
    // Allocate a memory block from a mail.
    // param[in]   queue_id    mail queue ID obtained with osMailCreate.
    // param[in]   millisec    timeout value 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.
    // MUST REMAIN UNCHANGED: osMailAlloc shall be consistent in every CMSIS-RTOS.
    //
    void * osMailAlloc( osMailQId queue_id, uint32_t millisec )
    {
      void * p;
    
      if ( millisec == 0 )
      {
        p = osPoolRequest( queue_id->poolId );
      }
    
      else if ( millisec == osWaitForever )
      {
        p = osPoolAlloc( queue_id->poolId );
      }
    
      else
      {
        p = osPoolAllocTimed( queue_id->poolId, millisec );
      }
    
      return p;
    }
    
    // Allocate a memory block from a mail and set memory block to zero.
    // param[in]   queue_id    mail queue ID obtained with osMailCreate.
    // param[in]   millisec    timeout value 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.
    // MUST REMAIN UNCHANGED: osMailCAlloc shall be consistent in every CMSIS-RTOS.
    //
    void * osMailCAlloc( osMailQId queue_id, uint32_t millisec )
    {
      void * p = osMailAlloc( queue_id, millisec );
    
      if ( p )
      {
        memset( p, 0, queue_id->poolId->BlockSize );
      }
    
      return p;
    }
    
    // Put a mail to a queue.
    // param[in]   queue_id    mail queue ID obtained with osMailCreate.
    // param[in]   mail      memory block previously allocated with osMailAlloc or osMailCAlloc.
    // return : status code that indicates the execution status of the function.
    // MUST REMAIN UNCHANGED: osMailPut shall be consistent in every CMSIS-RTOS.
    //
    osStatus osMailPut( osMailQId queue_id, void * mail )
    {
      return osMessagePut( queue_id->messageId, (uint32_t) mail, osWaitForever );
    }
    
    // Get a mail from a queue.
    // param[in]   queue_id    mail queue ID obtained with osMailCreate.
    // param[in]   millisec    timeout value or 0 in case of no time-out
    // return : event that contains mail information or error code.
    // MUST REMAIN UNCHANGED: osMailGet shall be consistent in every CMSIS-RTOS.
    //
    osEvent osMailGet( osMailQId queue_id, uint32_t millisec )
    {
      osEvent event = osMessageGet( queue_id->messageId, millisec );
    
      if ( event.status == osEventMessage )
      {
        event.status = osEventMail;
      }
    
      return event;
    }
    
    // Free a memory block from a mail.
    // param[in]   queue_id    mail queue ID obtained with osMailCreate.
    // param[in]   mail      pointer to the memory block that was obtained with osMailGet.
    // return : status code that indicates the execution status of the function.
    // MUST REMAIN UNCHANGED: osMailFree shall be consistent in every CMSIS-RTOS.
    //
    osStatus osMailFree( osMailQId queue_id, void * mail )
    {
      return osPoolFree( queue_id->poolId, mail );
    }
    
    // ============= Memory Management Functions ===================================
    
    static osMutexDef( cmsis_memory )
    ;
    static osMutexId cmsis_memory;
    
    osStatus osMemoryLock( uint32_t timeout )
    {
      if ( cmsis_memory == 0 )
        cmsis_memory = osMutexCreate( osMutex( cmsis_memory ) );
    
      return osMutexWait( cmsis_memory, timeout );
    }
    
    void osMemoryUnlock( void )
    {
      osMutexRelease( cmsis_memory );
    }
    
    /* Allocates a block of size bytes of memory, returning a pointer
     * to the beginning of the block. The content of the newly allocated block of
     * memory is not initialized, remaining with indeterminate values.
     *
     * On success, a pointer to the memory block allocated by the function.
     * The type of this pointer is always void*, which can be cast to the desired
     * type of data pointer in order to be dereferenceable.
     *
     * If the function failed to allocate the requested block of memory,
     * a null pointer is returned.
     *
     */
    void * osMalloc( size_t size, uint32_t timeout )
    {
      void * p = 0;
      osStatus status = osMemoryLock( timeout );
      if ( status == osOK )
      {
        p = malloc( size );
        osMemoryUnlock( );
      }
      return p;
    }
    
    /* Allocates a block of memory for an array of num elements,
     * each of them size bytes long, and initializes all its bits to zero.
     *
     * The effective result is the allocation of a zero-initialized memory block
     * of (num*size) bytes.
     *
     * On success, a pointer to the memory block allocated by the function.
     * The type of this pointer is always void*, which can be cast to the desired
     * type of data pointer in order to be dereferenceable.
     *
     * If the function failed to allocate the requested block of memory,
     * a null pointer is returned.
     *
     */
    void * osCalloc( size_t nelem, size_t elsize, uint32_t timeout )
    {
      void * p = osMalloc( nelem * elsize, timeout );
    
      if ( p )
      {
        memset( p, 0, nelem * elsize );
      }
    
      return p;
    }
    
    /* Changes the size of the memory block pointed to by ptr.
     * The function may move the memory block to a new location (whose address is
     * returned by the function).
     *
     * The content of the memory block is preserved up to the lesser of the new
     * and old sizes, even if the block is moved to a new location.
     *
     * If the new size is larger, the value of the newly allocated portion
     * is indeterminate.
     *
     * In case that ptr is a null pointer, the function behaves like malloc,
     * assigning a new block of size bytes and returning a pointer to its beginning.
     *
     * If the function fails to allocate the requested block of memory,
     * a null pointer is returned, and the memory block pointed to by argument ptr
     * is not deallocated (it is still valid, and with its contents unchanged).
     *
     * A pointer to the reallocated memory block, which may be either the same
     * as ptr or a new location. The type of this pointer is void*, which can be
     * cast to the desired type of data pointer in order to be dereferenceable.
     */
    void * osRealloc( void * ptr, size_t size, uint32_t timeout )
    {
      void * p = 0;
      osStatus status = osMemoryLock( timeout );
      if ( status == osOK )
      {
        p = realloc( ptr, size );
        osMemoryUnlock( );
      }
      return p;
    }
    
    /* A block of memory previously allocated by a call to malloc, calloc or realloc
     * is deallocated, making it available again for further allocations.
     *
     * If ptr does not point to a block of memory allocated with the above functions
     * it causes undefined behavior.
     * If ptr is a null pointer, the function does nothing.
     *
     * Notice that this function does not change the value of ptr itself,
     * hence it still points to the same (now invalid) location.
     *
     */
    void osFree( void * ptr )
    {
      osMemoryLock( osWaitForever );
      free( ptr );
      osMemoryUnlock( );
    }
    
    /*
     * Informs RTOS that interrupt code is executing.
     *
     * If osEnterInterrupt() is used, it should be the first function to be called
     * in the interrupt handler. It must be used with osLeaveInterrupt() as the last
     * function called. The use of this function has the following effects, it:
     *
     * disables task switches
     * keeps interrupts in internal routines disabled.
     */
    void osEnterInterrupt( void )
    {
      OS_EnterInterrupt()
      ;
    }
    
    /*
     * Informs RTOS that the end of the interrupt routine has been reached;
     * executes task switching within ISR.
     *
     * If osLeaveInterrupt()is used, it should be the last function to be called
     * in the interrupt handler. If the interrupt has caused a task switch, it will
     * be executed (unless the program which was interrupted was in a critical region).
     *
     */
    void osLeaveInterrupt( void )
    {
      OS_LeaveInterrupt()
      ;
    }
    
    uint32_t osDisableInterrupt( void )
    {
      __istate_t s = __get_interrupt_state( );
      __disable_interrupt( );
      return (uint32_t) s;
    
    }
    
    void osRestoreInterrupt( uint32_t val )
    {
      __set_interrupt_state( (__istate_t ) val );
    }
    #include "cmsis_os.h"
    
    #if defined(osFeature_MainThread) && (osFeature_MainThread > 0 )
    
    /*----------------------------------------------------------------------------
     *      RTX Startup
     *---------------------------------------------------------------------------*/
    
    /* Main Thread definition */
    extern int main (void);
    
    osThreadDef( main, main, osPriorityNormal, 1, OS_MAINSTKSIZE );
    
    extern int  __low_level_init(void);
    extern void __iar_data_init3(void);
    extern void exit(int arg);
    
    __noreturn __stackless void __cmain(void) {
      int a;
    
      if (__low_level_init() != 0) {
        __iar_data_init3();
      }
      osKernelInitialize();
      osThreadCreate(&os_thread_def_main, NULL);
      a = osKernelStart();
      exit(a);
    }
    
    #endif
  • 相关阅读:
    Python中字符的练习
    Python中的数据结构 --- 集合(set)
    Python中的数据结构 --- 元组(tuple)、字典(tuple)
    Python中的数据结构 --- 列表(list)
    Python变量、字符练习1
    Python中字符串的操作
    Python中for、while、break、continue、if的使用
    Python中的变量
    Python中注释的添加
    Python的介绍及Pycharm软件的安装
  • 原文地址:https://www.cnblogs.com/shangdawei/p/3921473.html
Copyright © 2011-2022 走看看