#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)) // // \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). // 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)) // // \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). // 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)) // // \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 // 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