c语言sscanf函数的用法是什么
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小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~