如何理解CMSIS-RTOS API和宏定义

网友投稿 345 2022-11-04

如何理解CMSIS-RTOS API和宏定义

这套API表现为两个文件:cmsis-os.h和cmsis-os.c,也就是说,不同的RTOS内核分别用自己的一套东西去适配.c文件中的接口,而用户只需要调用.h文件中给出的API编写应用。

本文会列举性的给出CMSIS-RTOS有哪些API和宏定义,并给出每类API的使用demo,学习者只需要了解这些东西,能看懂用CMSIS-RTOS API编写的应用程序即可~

基于TencentOS-tiny的CMSIS-RTOS API v1.02版本实现:

cmsis_os.h

cmsis_os.c

基于TencentOS-tiny的CMSIS-RTOS API v2.1.3版本实现:

cmsis_os2.h

cmsis_os2.c

CMSIS-RTOS API的整体架构如下图:

2. CMSIS-RTOS API列表

下面列出了 CMSIS-RTOS API v1.02 版本提供的所有API。

CMSIS-RTOS 所有API使用的错误码(cmsis-os.h):

typedefenum{

osOK=0,///< function completed; no error or event occurred.    osEventSignal           =  0x08,       ///< function completed; signal event occurred.    osEventMessage          =  0x10,       ///< function completed; message event occurred.    osEventMail             =  0x20,       ///< function completed; mail event occurred.    osEventTimeout          =  0x40,       ///< function completed; timeout occurred.    osErrorParameter        =  0x80,       ///< parameter error: a mandatory parameter was missing or specified an incorrect object.    osErrorResource         =  0x81,       ///< resource not available: a specified resource was not available.    osErrorTimeoutResource  =  0xC1,       ///< resource not available within given time: a specified resource was not available within the timeout period.    osErrorISR              =  0x82,       ///< not allowed in ISR context: the function cannot be called from interrupt service routines.    osErrorISRRecursive     =  0x83,       ///< function called multiple times from ISR with same object.    osErrorPriority         =  0x84,       ///< system cannot determine priority or thread has illegal priority.    osErrorNoMemory         =  0x85,       ///< system is out of memory: it was impossible to allocate or reserve memory for the operation.    osErrorValue            =  0x86,       ///< value of a parameter is out of range.    osErrorOS               =  0xFF,       ///< unspecified RTOS error: run-time error but no other error message fits.    os_status_reserved      =  0x7FFFFFFF  ///< prevent from enum down-size compiler optimization.} osStatus;

CMSIS-RTOS API一些可选项控制是否开启(cmsis-os.h):

#defineosFeature_Pool1///< Memory Pools:    1=available, 0=not available#define osFeature_MailQ        1       ///< Mail Queues:     1=available, 0=not available#define osFeature_MessageQ     1       ///< Message Queues:  1=available, 0=not available#define osFeature_Signals      0       ///< maximum number of Signal Flags available per thread#define osFeature_Semaphore    30       ///< maximum count for ef osSemaphoreCreate function#define osFeature_Wait         0       ///< osWait function: 1=available, 0=not available#define osFeature_SysTick      1       ///< osKernelSysTick functions: 1=available, 0=not available

2.1. 内核信息和控制

API 描述
osKernelInitialize 初始化RTOS内核
osKernelStart 启动RTOS内核
osKernelRunning Query if the RTOS kernel is running
osKernelSysTick (可选) Get RTOS kernel system timer counter
osKernelSysTickFrequency (可选) RTOS kernel system timer frequency in Hz
osKernelSysTickMicroSec (可选) Convert microseconds value to RTOS kernel system timer value

osKernelInitialize

osStatusosKernelInitialize(void);

返回值:status code

osKernelStart

osStatusosKernelStart(void);

返回值:status code

osKernelRunning

int32_tosKernelRunning(void);

返回值:0表示RTOS未启动,1表示RTOS已经启动

osKernelSysTick

uint32_tosKernelSysTick(void);

返回值:RTOS内核系统当前的时间

2.2. 线程管理

##连接符的作用是连接两个字符串,合为一个字符串。

CMSIS-RTOS API 存放线程参数管理的结构体如下:typedefstructos_thread_def{

char*name;///< Thread name    os_pthread      pthread;    ///< start address of thread function    osPriority      tpriority;  ///< initial thread priority    uint32_t        instances;  ///< maximum number of instances of that thread function    k_stack_t      *stackbase;  ///< base address of task    uint32_t        stacksize;  ///< stack size requirements in bytes; 0 is default stack size    k_timeslice_t   timeslice;  ///< timeslice    k_task_t       *task;} osThreadDef_t;

CMSIS-RTOS API 定义线程的宏如下:

#defineosThreadDef(name,priority,instances,stacksz)

k_task_ttask_handler_##name;k_stack_ttask_stack_##name[(stacksz)];constosThreadDef_tos_thread_def_##name={#name,(os_pthread)(name),(osPriority)(priority),(instances),(&((task_stack_##name)[0])),(stacksz),((k_timeslice_t)0u),(&(task_handler_##name))}

宏定义中的 instances 表示基于此任务参数,创建出几个任务实例,比如instances为2,则会创建出两个任务。

CMSIS-RTOS API定义的获取线程参数结构体的宏如下:

#defineosThread(name)

&os_thread_def_##name

管理线程参数的API如下:

osThreadCreate

其中osThreadId被定义为k_task_t指针类型:typedefk_task_t*osThreadId;

返回值:TencentOS-tiny中的任务控制块类型指针。

osThreadTerminate

osStatusosThreadTerminate(osThreadIdthread_id);

返回值:osStatus

osThreadYield

osStatusosThreadYield(void);

返回值:osStatus

osThreadGetID

osThreadIdosThreadGetId(void);

osThreadSetPriority

osStatusosThreadSetPriority(osThreadIdthread_id,osPrioritypriority);

osThreadGetPriority

osPriorityosThreadGetPriority(osThreadIdthread_id);

使用时需要特别注意,在TencentOS-tiny中,调用CMSIS-RTOS API提供的优先级选项设置之后,实际设置的任务值是不同的。

CMSIS-RTOS API提供的线程优先级宏定义如下:

typedefenum{

osPriorityIdle=-3,///< priority: idle (lowest)    osPriorityLow           = -2,          ///< priority: low    osPriorityBelowNormal   = -1,          ///< priority: below normal    osPriorityNormal        =  0,          ///< priority: normal (default)    osPriorityAboveNormal   = +1,          ///< priority: above normal    osPriorityHigh          = +2,          ///< priority: high    osPriorityRealtime      = +3,          ///< priority: realtime (highest)    osPriorityError         =  0x84        ///< system cannot determine priority or thread has illegal priority} osPriority;在TecentOS-tiny中实现的时候进行了转化:

statick_prio_tpriority_cmsis2knl(osPriorityprio)

{if(prio==osPriorityError){returnK_TASK_PRIO_INVALID;}return(k_prio_t)(3-prio);}staticosPrioritypriority_knl2cmsis(k_prio_tprio){return(osPriority)(3-prio);}

比如创建线程时设置为 osPriorityNormal=0,则「实际设置的任务优先级为3」。

2.3. 通用等待函数

CMSIS-RTOS提供的等待函数API如下:

osDelay

osStatusosDelay(uint32_tmillisec);

返回值:osStatus。

CMSIS-RTOS API提供的存储定时器参数的结构体如下:typedefstructos_timer_def{

os_ptimercb;///< start address of a timer function    k_timer_t                *timer;} osTimerDef_t;

CMSIS-RTOS API提供的定义一个软件定时器的宏定义如下:

#defineosTimerDef(name,function)

k_timer_ttimer_handler_##name;constosTimerDef_tos_timer_def_##name={(os_ptimer)(function),(&(timer_handler_##name))}

CMSIS-RTOS API定义的获取软件定时器参数结构体的宏如下:

#defineosTimer(name)

&os_timer_def_##name

CMSIS-RTOS API提供的软件定时器管理API如下:

osTimerCreate

osTimerIdosTimerCreate(constosTimerDef_t*timer_def,os_timer_typetype,void*argument);

其中osTimerId被定义为k_timer_t指针类型:

typedefk_timer_t*osTimerId;

type参数为 os_timer_type 类型,表示软件定时器的类型为单次触发或者周期触发:

typedefenum{

osTimerOnce=0,///< one-shot timer    osTimerPeriodic         =     1        ///< repeating timer} os_timer_type;

osTimerStart

osStatusosTimerStart(osTimerIdtimer_id,uint32_tmillisec);

返回值:osStatus。

osTimerStop

osStatusosTimerStop(osTimerIdtimer_id)

返回值:osStatus。

osTimerDelete

osStatusosTimerDelete(osTimerIdtimer_id);

返回值:osStatus。

2.5. 信号量管理

CMSIS-RTOS API提供的存储信号量参数的结构体如下:

typedefstructos_semaphore_def{

uint32_tdummy;///< dummy value.    k_sem_t                    *sem;} osSemaphoreDef_t;

CMSIS-RTOS API提供的定义一个信号量的宏定义如下:

#defineosSemaphoreDef(name)

k_sem_tsem_handler_##name;constosSemaphoreDef_tos_semaphore_def_##name={0,(&(sem_handler_##name))}

CMSIS-RTOS API定义的获取信号量参数结构体的宏如下:

#defineosSemaphore(name)

&os_semaphore_def_##name

CMSIS-RTOS API提供的信号量管理API如下:

API 描述
osSemaphoreCreate 创建一个信号量
osSemaphoreWait 等待信号量
osSemaphoreRelease 释放信号量
osSemaphoreDelete 删除信号量

osSemaphoreCreate

osSemaphoreIdosSemaphoreCreate(constosSemaphoreDef_t*semaphore_def,int32_tcount);

其中 osSemaphoreId 被定义为k_sem_t指针类型:

typedefk_sem_t*osSemaphoreId;

osSemaphoreWait

int32_tosSemaphoreWait(osSemaphoreIdsemaphore_id,uint32_tmillisec);

返回值:int32_t ,正常返回当前count数,失败返回-1。

如果需要阻塞延时,参数应该设置为CMSIS-RTOS API提供的宏定义 osWaitForever :

#defineosWaitForever0xFFFFFFFF///< wait forever timeout value

osSemaphoreRelease

osStatusosSemaphoreRelease(osSemaphoreIdsemaphore_id);

返回值:osStatus。

osSemaphoreDelete

osStatusosSemaphoreDelete(osSemaphoreIdsemaphore_id);

返回值:osStatus。

2.6. 互斥锁管理

CMSIS-RTOS API提供的存储互斥锁参数的结构体如下:

typedefstructos_mutex_def{

uint32_tdummy;///< dummy value.    k_mutex_t                  *mutex;} osMutexDef_t;

CMSIS-RTOS API提供的定义一个互斥锁的宏定义如下:

#defineosMutexDef(name)

k_mutex_tmutex_handler_##name;constosMutexDef_tos_mutex_def_##name={0,(&(mutex_handler_##name))}

CMSIS-RTOS API定义的获取互斥锁参数结构体的宏如下:

#defineosMutex(name)

&os_mutex_def_##name

CMSIS-RTOS API提供的互斥锁管理API如下:

API 描述
osMutexCreate 创建一个互斥锁
osMutexWait 等待获取互斥锁
osMutexRelease 释放互斥锁
osMutexDelete 删除互斥锁

osMutexCreate

osMutexIdosMutexCreate(constosMutexDef_t*mutex_def);

其中 osMutexId 被定义为k_mutex_t指针类型:

typedefk_mutex_t*osMutexId;

osMutexWait

osStatusosMutexWait(osMutexIdmutex_id,uint32_tmillisec);

返回值:osStatus 。

如果需要阻塞延时,参数应该设置为CMSIS-RTOS API提供的宏定义 osWaitForever :

#defineosWaitForever0xFFFFFFFF///< wait forever timeout value

osMutexRelease

osStatusosMutexRelease(osMutexIdmutex_id);

返回值:osStatus。

osMutexDelete

osStatusosMutexDelete(osMutexIdmutex_id);

返回值:osStatus。

2.7. 静态内存池管理

CMSIS-RTOS API提供的存储静态内存池参数的结构体如下:

typedefstructos_pool_def{

uint32_tpool_sz;///< number of items (elements) in the pool    uint32_t                    item_sz;    ///< size of an item    void                       *pool;       ///< pointer to memory for pool    k_mmblk_pool_t             *mmblk_pool; ///< memory blk pool handler} osPoolDef_t;

CMSIS-RTOS API提供的定义一个互斥锁的宏定义如下:

#defineosPoolDef(name,no,type)

k_mmblk_pool_tmmblk_pool_handler_##name;uint8_tmmblk_pool_buf_##name[(no)*sizeof(type)];constosPoolDef_tos_pool_def_##name={(no),sizeof(type),(&((mmblk_pool_buf_##name)[0])),(&(mmblk_pool_handler_##name))}

CMSIS-RTOS API定义的获取互斥锁参数结构体的宏如下:

#defineosPool(name)

&os_pool_def_##name

CMSIS-RTOS API提供的互斥锁管理API如下:

API 描述
osPoolCreate 创建一块固定大小的静态内存池
osPoolAlloc 申请分配内存
osPoolCAlloc 申请分配一块内存并全部初始化为0
osPoolFree 申请回收内存

osPoolCreate

osPoolIdosPoolCreate(constosPoolDef_t*pool_def);

其中 osPoolId 被定义为 k_mmblk_pool_t 指针类型:

typedefk_mmblk_pool_t*osPoolId;

osPoolAlloc

void*osPoolAlloc(osPoolIdpool_id);

osPoolCAlloc

void*osPoolCAlloc(osPoolIdpool_id);

osPoolFree

osStatusosPoolFree(osPoolIdpool_id,void*block);

返回值:osStatus。

2.8. 消息队列管理

CMSIS-RTOS API提供的存储消息队列参数的结构体如下:

typedefstructos_messageQ_def{

uint32_tqueue_sz;///< number of elements in the queue    uint32_t                    item_sz;    ///< size of an item    void                       *pool;       ///< memory array for messages    k_msg_q_t                  *queue;      ///< queue handler} osMessageQDef_t;

CMSIS-RTOS API提供的定义一个消息队列的宏定义如下:

#defineosMessageQDef(name,queue_sz,type)

k_msg_q_tmsg_q_handler_##name;constosMessageQDef_tos_messageQ_def_##name={(queue_sz),sizeof(type),NULL,(&(msg_q_handler_##name))}

CMSIS-RTOS API定义的获取消息队列参数结构体的宏如下:

#defineosMessageQ(name)

&os_messageQ_def_##name

CMSIS-RTOS API提供的消息队列管理API如下:

API 描述
osMessageCreate 初始化一个消息队列
osMessagePut 向消息队列中加入数据
osMessageGet 从消息队列中取出数据

osMessageCreate

osMessageQIdosMessageCreate(constosMessageQDef_t*queue_def,osThreadIdthread_id);

其中 osMessageQId 被定义为 k_msg_q_t 指针类型:

typedefk_msg_q_t*osMessageQId;

osMessagePut

osStatusosMessagePut(osMessageQIdqueue_id,uint32_tinfo,uint32_tmillisec);

返回值:osStatus 。

因为TencentOS-tiny中消息队列实现机制的不同,此API中的 millisec 参数未用到。

osMessageGet

osEventosMessageGet(osMessageQIdqueue_id,uint32_tmillisec);

返回值:osEvent ,其中包含了事件信息和错误码,以及消息队列收到的值。

如果需要阻塞延时,参数应该设置为CMSIS-RTOS API提供的宏定义 osWaitForever :

#defineosWaitForever0xFFFFFFFF///< wait forever timeout value

3. 使用示例

3.1. 任务创建示例

#include

任务运行结果如下:

task1isrunning...task2isrunning...task1isrunning...task2isrunning...task1isrunning...task2isrunning...

3.2. 软件定时器使用示例

#includevoidtimer1_cb(void*arg){printf("timer1istimeout!");}voidtimer2_cb(void*arg){printf("timer2istimeout!");}osTimerDef(timer1,timer1_cb);osTimerDef(timer2,timer2_cb);voidapplication_entry(void*arg){osTimerIdtimer1;osTimerIdtimer2;timer1=osTimerCreate(osTimer(timer1),osTimerOnce,NULL);timer2=osTimerCreate(osTimer(timer2),osTimerPeriodic,NULL);osTimerStart(timer1,5000);osTimerStart(timer2,1000);return;}

运行结果如下:

timer2istimeout!timer2istimeout!timer2istimeout!timer2istimeout!timer1istimeout!timer2istimeout!timer2istimeout!timer2istimeout!timer2istimeout!

3.3. 信号量使用示例

#includeosSemaphoreIdsync_sem_id;osSemaphoreDef(sync_sem);voidtask1_entry(void*arg){while(1){printf("task1iswaitingsemforever...");osSemaphoreWait(sync_sem_id,osWaitForever);printf("task1getsem!");}}osThreadDef(task1_entry,osPriorityNormal,1,512);voidtask2_entry(void*arg){while(1){printf("task2willreleaseasem...");osSemaphoreRelease(sync_sem_id);osDelay(1000);}}osThreadDef(task2_entry,osPriorityNormal,1,512);voidapplication_entry(void*arg){sync_sem_id=osSemaphoreCreate(osSemaphore(sync_sem),0);osThreadCreate(osThread(task1_entry),NULL);osThreadCreate(osThread(task2_entry),NULL);return;}

运行结果为:

task1iswaitingsemforever...task1getsem!task1iswaitingsemforever...task2willreleaseasem...task1getsem!task1iswaitingsemforever...task2willreleaseasem...task1getsem!task1iswaitingsemforever...task2willreleaseasem...task1getsem!task1iswaitingsemforever...task2willreleaseasem...task1getsem!task1iswaitingsemforever...

3.4. 互斥锁使用示例

#include

运行结果为:

task1getmutex,doingsth...task1finishdosth!task2getmutex,doingsth...task2finishdosth!task1getmutex,doingsth...task1finishdosth!task1getmutex,doingsth...task1finishdosth!task2getmutex,doingsth...

3.5. 动态内存使用示例

#includetypedefstructblk_st{intid;char*payload;}blk_t;#defineMMBLK_BLK_NUM10osPoolDef(MemPool,MMBLK_BLK_NUM,blk_t);osPoolIdmem_pool_id;voidtask1_entry(void*arg){blk_t*ptr=NULL;osStatuserr;/*打印出一个块的大小*/printf("blocksizeis%dbytes",sizeof(blk_t));/*申请一个块*/ptr=osPoolAlloc(mem_pool_id);if(ptr==NULL){printf("ammblkallocfail");return;}else{printf("ammblkallocsuccess");}/*使用该块*/ptr->id=1;ptr->payload="hello";printf("mmblkid:%dpayload:%s",ptr->id,ptr->payload);/*使用完毕之后释放*/err=osPoolFree(mem_pool_id,ptr);if(err!=osOK){printf("ammblkfreefail,err=%d",err);return;}else{printf("ammblkfreesuccess");}while(1){tos_task_delay(1000);}}#defineSTK_SIZE_TASK11024osThreadDef(task1_entry,osPriorityNormal,1,STK_SIZE_TASK1);voidapplication_entry(void*arg){//初始化静态内存池mem_pool_id=osPoolCreate(osPool(MemPool));if(mem_pool_id==NULL){printf("mmblkpoolcreatefail");return;}else{printf("mmblkpoolcreatesuccess");}//创建任务osThreadCreate(osThread(task1_entry),NULL);return;}

运行结果为:

mmblkpoolcreatesuccessblocksizeis8bytesammblkallocsuccessmmblkid:1payload:helloammblkfreesuccess

3.6. 消息队列使用示例

#include#defineSTK_SIZE_TASK_RECEIVER512#defineSTK_SIZE_TASK_SENDER512#defineMESSAGE_MAX10osMessageQIdmsg_q_id;osMessageQDef(msg_q,MESSAGE_MAX,uint32_t);voidtask_receiver_entry(void*arg){osEventevent;osStatusret;uint32_tvalue;while(1){event=osMessageGet(msg_q_id,osWaitForever);ret=event.status;if(ret==osOK){value=event.value.v;printf("receiver:msgincoming[%s]",(char*)value);}}}osThreadDef(task_receiver_entry,osPriorityNormal,1,STK_SIZE_TASK_RECEIVER);voidtask_sender_entry(void*arg){char*msg_prio_0="msg0";char*msg_prio_1="msg1";char*msg_prio_2="msg2";printf("sender:postamessgae:[%s]",msg_prio_2);osMessagePut(msg_q_id,(uint32_t)msg_prio_2,0);printf("sender:postamessgae:[%s]",msg_prio_1);osMessagePut(msg_q_id,(uint32_t)msg_prio_1,0);printf("sender:postamessgae:[%s]",msg_prio_0);osMessagePut(msg_q_id,(uint32_t)msg_prio_0,0);}osThreadDef(task_sender_entry,osPriorityNormal,1,STK_SIZE_TASK_SENDER);voidapplication_entry(void*arg){msg_q_id=osMessageCreate(osMessageQ(msg_q),NULL);osThreadCreate(osThread(task_receiver_entry),NULL);osThreadCreate(osThread(task_sender_entry),NULL);return;}

运行结果为:

sender:postamessgae:[msg2]sender:postamessgae:[msg1]sender:postamessgae:[msg0]receiver:msgincoming[msg2]receiver:msgincoming[msg1]receiver:msgincoming[msg0]

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:看云原生实战就来这里,侬晓得伐?
下一篇:三维数据接口(三维数据体)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~