uC/OS-III
[TOC]
1、信号量
1.1、二值信号量
1.2、计数型信号量
二值信号量会存在一个优先级翻转的问题,可使用互斥信号量解决
| 函数 | 描述 |
|---|
| OSSemCreate() | 创建一个信号量 |
| OSSemDel() | 删除一个信号量 |
| OSSemPend() | 尝试获取信号量资源 |
| OSSemPendAbort() | 终止任务挂起等待信号量资源 |
| OSSemPost() | 释放信号量资源 |
| OSSemSet() | 强制设置信号量的资源数 |
void OSSemCreate( OS_SEM *p_sem, //指向信号量结构体的指针
CPU_CHAR *p_name, //指向作为信号量名的 ASCII 字符串的指针
OS_SEM_CTR cnt, //信号量资源数的初始值
OS_ERR *p_err) //指向接收错误代码变量的指针
OS_OBJ_QTY OSSemDel( OS_SEM *p_sem, //指向信号量结构体的指针
OS_OPT opt, //函数操作选项
OS_ERR *p_err) //指向接收错误代码变量的指针
OS_SEM_CTR OSSemPend(OS_SEM *p_sem, //指向信号量结构体的指针
OS_TICK timeout, //任务挂起等待信号量的最大允许时间
OS_OPT opt, //函数操作选项
CPU_TS *p_ts, //指向接收信号量接收时的时间戳的变量的指针
OS_ERR *p_err) //指向接收错误代码变量的指针
timeout=0表示一直等下去
opt:OS_OPT_PEND_BLOCKING 指定信号量无效时,任务挂起以等待信号量
OS_OPT_PEND_NON_BLOCKING 信号量无效时,任务直接返回。
OS_OBJ_QTY OSSemPendAbort( OS_SEM *p_sem, //指向信号量结构体的指针
OS_OPT opt, //函数操作选项
OS_ERR *p_err) //指向接收错误代码变量的指针
OS_SEM_CTR OSSemPost( OS_SEM *p_sem, //指向信号量结构体的指针
OS_OPT opt, //函数操作选项
OS_ERR *p_err) //指向接收错误代码变量的指针
opt:OS_OPT_POST_1,只释放信号量给最高优先级且就绪的任务,类似于UDP的点播(主要应用在二值信号量上)
OS_OPT_POST_ALL,释放给所有等待信号量的任务,类似于UDP的广播(主要应用在计数型信号量上)
void OSSemSet( OS_SEM *p_sem, //指向信号量结构体的指针
OS_SEM_CTR cnt, //信号量资源数设置后的值
OS_ERR *p_err) //指向接收错误代码变量的指针
1.3、互斥信号量
| 函数 | 描述 |
|---|
| OSMutexCreate() | 创建一个互斥信号量 |
| OSMutexDel() | 删除一个互斥信号量 |
| OSMutexPend() | 尝试获取互斥信号量 |
| OSMutexPendAbort() | 终止任务挂起等待互斥信号量 |
| OSMutexPost() | 释放互斥信号量 |
void OSMutexCreate( OS_MUTEX* p_mutex, //指向互斥信号量结构体的指针
CPU_CHAR* p_name, //指向作为互斥信号量名的ASCII 字符串的指针
OS_ERR* p_err) //指向接收错误代码变量的指针
OS_OBJ_QTY OSMutexDel(OS_MUTEX* p_mutex, //指向互斥信号量结构体的指针
OS_OPT opt, //函数操作选项
OS_ERR* p_err) //指向接收错误代码变量的指针
opt: OS_OPT_DEL_NO_PEND 要在mutex 等待列表上没有等待任务的时候才可以删除mutex。
OS_OPT_DEL_ALWAYS 不管mutex 等待列表上是否有等待的任务都直接删除mutex。
void OSMutexPend( OS_MUTEX* p_mutex, //指向互斥信号量结构体的指针
OS_TICK timeout, //任务挂起等待互斥信号量的最大允许时间
OS_OPT opt, //函数操作选项
CPU_TS* p_ts, //指向接收互斥信号量接收时的时间戳的变量的指针
OS_ERR* p_err) //指向接收错误代码变量的指针
timeout: 0=无限等待
opt: OS_OPT_PEND_BLOCKING 一开始获取不到信号量就阻塞任务,阻塞的时候根据参数timeout 决定。
OS_OPT_PEND_NON_BLOCKING 一开始获取不到信号量就退出函数,继续运行任务。
OS_OBJ_QTY OSMutexPendAbort( OS_MUTEX* p_mutex, //指向互斥信号量结构体的指针
OS_OPT opt, //函数操作选项
OS_ERR* p_err) //指向接收错误代码变量的指针
opt: OS_OPT_PEND_ABORT_1 只是强制解除等待mutex 的最高任务。
OS_OPT_PEND_ABORT_ALL 将等待mutex 的所有任务都强制解除等待状态。
void OSMutexPost( OS_MUTEX* p_mutex, //指向互斥信号量结构体的指针
OS_OPT opt, //函数操作选项
OS_ERR* p_err) //指向接收错误代码变量的指针
opt: OS_OPT_POST_NO_SCHED 发布mutex 后不要进行调度。
OS_OPT_POST_NONE 这个是默认的选项,发布mutex 后进行任务调度。
1.4、任务内嵌信号量
| 函数 | 描述 |
|---|
| OSTaskSemPend() | 等待任务信号量(常用) |
| OSTaskSemPost() | 发布任务信号量(常用) |
| OSTaskSemPendAbort() | 取消等待任务信号量 |
| OSTaskSemSet() | 强行设置任务信号量计数 |
OS_SEM_CTR OSTaskSemPend (OS_TICK timeout, //等待超时时间
OS_OPT opt, //选项
CPU_TS *p_ts, //返回时间戳
OS_ERR *p_err) //返回错误类型
timeout: 如果在指定的节拍数内没有收到信号量任务就会因为等待超时而恢复运行,如果timeout为0的话任务就会-一直等待,直到收到信号量。
opt: 用于选择是否使用阻塞模式。
OS_OPT_PEND_BLOCKING指定互斥信号量被占用时,任务挂起等待该互斥信号量。
OS_OPT_PEND_NON_BLOCKING指定当互斥信号量被占用时,直接返回任务。
注意!当设置为OS_OPT_PEND_NON_BLOCKING,是timeout参数就没有意义了,应该设置为0。
OS_SEM_CTR OSTaskSemPost (OS_TCB *p_tcb, //目标任务
OS_OPT opt, //选项
OS_ERR *p_err) //返回错误类型
opt: 用来指定是否进行任务调度操作
OS_OPT_POST_NONE 不指定特定的选项
OS_OPT_POST_NO_SCHED 禁止在本函数内执行任务调度操作。
2、事件标志
事件标志与信号量一样属于任务间同步的一种机制,但是信号量一般用于任务间的单事件同步,而对于任务间的多事件同步,仅仅使用信号量就显得力不从心了。为此 µC/OS-III 提供了事件标志这一机制,事件标志就能够很好地处理任务间的多任务同步。
事件标志是一个用于指示事件是否发生的比特位,因为一个事件是否发生只有两种情况,分别为事件发生和事件未发生,因此只需一个比特位就能够表示事件是否发生,µC/OS-III 用1表示事件发生,用0 表示事件未发生。
| 函数 | 描述 |
|---|
| OSFlagCreate() | 创建一个事件标志组 |
| OSFlagDel() | 删除一个事件标志组 |
| OSFlagPend() | 等待事件标志组中的事件 |
| OSFlagPendAbort() | 终止挂起等待事件标志组中的事件 |
| OSFlagPendGetFlagRdy() | 获取任务等待到的事件 |
| OSFlagPost() | 设置事件标志组中的事件 |
void OSFlagCreate( OS_FLAG_GRP* p_grp, //指向事件标志组结构体的指针
CPU_CHAR* p_name, //指向作为事件标志组名的ASCII 字符串的指针
OS_FLAGS flags, //事件标志组的初始值
OS_ERR* p_err) //指向接收错误代码变量的指针
//返回值 被终止挂起等待事件标志任务的数量
OS_OBJ_QTY OSFlagDel( OS_FLAG_GRP* p_grp, //指向事件标志组结构体的指针
OS_OPT opt, //函数操作选项
OS_ERR* p_err); //指向接收错误代码变量的指针
//返回值 任务实际等待到的事件标志
OS_FLAGS OSFlagPend( OS_FLAG_GRP* p_grp, //指向事件标志组结构体的指针
OS_FLAGS flags, //等待的事件标志
OS_TICK timeout, //任务挂起等待事件标志的最大允许时间
OS_OPT opt, //函数操作选项
CPU_TS* p_ts, //指向接收等待到事件时的时间戳的变量的指针
OS_ERR* p_err) //指向接收错误代码变量的指针
flags: bit 序列,任务需要等待事件标志组的哪个位就把这对应位置1,根据设置这个序列可以是8bit、16bit、32 bit。 比如任务需要等待时间标志组的 bit0 和 bit1 时(无论是等待置位还清零),flag 的值就为0x03。
timeout: 指定等待事件标志组的超时时间(时钟节拍数),如果在指定的超时间内所等待的一个或多个事件没有发生,那么任务恢复运行。如果此值设置为0则任务就将一直等待下去,到一个或多个事件发生。
opt: 决定任务等待的条件是所有标志置位、所有标志清零、任意一个标志位置位还是任意一个标志位清零,具体的定义如下。
OS_OPT_PEND_FLAG_CLR_ALL 等待事件标志组所有的位清零
OS_OPT_PEND_FLAG_CLR_ANY 等待事件标志组中任意一个标志清零
OS_OPT_PEND_FLAG_SET_ALL 等待事件标志组中所有的位置位
OS_OPT_PEND_FLAG_SET_ANY 等待事件标志组中任意一个标志置位
调用上面四个选项的时候还可以搭配下三个选项
OS_OPT_PEND_FLAG_CONSUME 用来设置是否继续保留该事件标志的状态。
OS_OPT_PEND_NON_BLOCKING 标志组不满足条件时不挂起任务。
OS_OPT_PEND_BLOCKING 标志组不满足条件时挂起任务。
这里应该注意选项OS_OPT_PEND_FLAG_CONSUME 的使用方法,如果我们希望任务等待事件标志组的任意一个置位,并在满足条后将对应清零那么就可以搭配使用选项OS_OPT_PEND_FLAG_CONSUME 。
//返回值 被终止挂起任务的数量
OS_OBJ_QTY OSFlagPendAbort( OS_FLAG_GRP* p_grp, //指向事件标志组结构体的指针
OS_OPT opt, //函数操作选项
OS_ERR* p_err) //指向接收错误代码变量的指针
//返回值 任务获取到的事件标志
OS_FLAGS OSFlagPendGetFlagsRdy(OS_ERR *p_err) //指向接收错误代码变量的指针
//返回值 事件标志组更新后的事件标志值
OS_FLAGS OSFlagPost( OS_FLAG_GRP* p_grp, //指向事件标志组结构体的指针
OS_FLAGS flags, //等待的事件标志
OS_OPT opt, //函数操作选项
OS_ERR* p_err) //指向接收错误代码变量的指针
flags: 决定对哪些位清零和置,当 opt 参数为OS_OPT_POST_FLAG_SET的时,参数flags中置位的就会在事件标志组对应的位也将被置位。当 opt 为 OS_OPT_POST_FLAG_CLR 的时候参数flags中置位的位在事件标志组中对应的位将中被清零。
opt: OS_OPT_POST_FLAG_SET 对标志位进行置位操作
OS_OPT_POST_FLAG_CLR 对标志位进行清零操作
3、临界段
在 UCOS 中,临界区的访问方式依赖于中断 ISR 是否启用延迟传递。如果OS_CFG_ISR_POST_DEFERRED_EN = 0,则访问内部临界区时直接禁止中断即可。若 OS_CFG_ISR_POST_DEFERRED_EN = 1,则访问临界区时需要锁住调度器。
在使用临界段时需要先调用函数 CPU_SR_ALLOC() ,该函数会初始化一个 cpu_sr 局部变量,在调用进入临界段及退出临界段宏中会使用该局部变量。
| 函数 | 作用 | 描述 |
|---|
| OS_CRITICAL_ENTER() | 进入临界区 | 通过 OSSchedLockNestingCtr 加 1 为调度器上锁。这个值就是用来决定调度器是否别被上锁,当此值不为 0 时,就表示调度器已经上锁。 |
| OS_CRITICAL_EXIT() | 退出临界区 | 使 OSSchedLockNestingCtr 减 1,并且当此值达到 0 时,调用调度器。 |
| OS_CRITICAL_EXIT_NO_SCHED() | 退出临界区 | 使 OSSchedLockNestingCtr 减1,但是当此值为 0 时,也不调用调度器 |
4、时间片轮转调度
UCOSIII 支持多个任务拥有相同优先级,这些任务采用时间片轮转调度方法进行任务调度 。 要 想 采 用 时 间 片 轮 转 调 度 , 就 需 将 os_cgf.h 文 件 中 的 宏OS_CFG_SCHED_ROUND_ROBIN_EN 定义为 1。这样时间片轮转调度的代码才会被编译。否则不能使用时间片轮转调度。
| 函数 | 作用 |
|---|
| OSSchedRoundRobinCfg() | 使能或失能UCOSIII,并且设置系统时钟节拍(也叫时间片长度)。 |
| OSSchedRoundRobinYield() | 当一个任务想放弃本次时间片的时候,就可以调用该函数。 |
void OSSchedRoundRobinCfg (CPU_BOOLEAN en, //状态
OS_TICK dflt_time_quanta, //时间片
OS_ERR *p_err) //返回错误类型
设置系统时钟频率OSCfg_TickRate_Hz为200Hz时,每个时钟节拍就是1/200=0.005s=5ms
dflt_time_quanta的取值n就决定了系统的时间片长度,为5*n(ms),若n=0,UCOSIII则会使用系统默认的时间片长度OSCfg_TickRate_Hz/10。
en:决定了打开或关闭时间片轮状调度机制。参数DEF_ENABLED表示开启,DEF_DISABLED表示关闭。
5、内存管理
在使用内存管理之前首先要创建存储区,存储区控制块:OS_MEM
| 函数 | 作用 |
|---|
| OSMemCreate() | 创建存储区 |
| OSMemGet() | 获取存储块 |
| OSMemPut() | 释放存储块 |
void OSMemCreate(OS_MEM *p_mem, //指向存储区控制块地址,一般为一个OS_MEM结构体
CPU_CHAR *p_name, //指向存储区的名字
void *p_addr, //存储区所有存储空间基地址
OS_MEM_QTY n_blks, //存储区中存储块个数
OS_MEM_SIZE blk_size,//存储块大小
OS_ERR *p_err) //返回的错误码
void *OSMemGet(OS_MEM *p_mem, //要使用的存储区
OS_ERR *p_err) //返回的错误码
void *OSMemPut(OS_MEM *p_mem, //指向存储区控制块,也就是要接受存储块的那个存储区
void *p_blk, //指向存储块,要归还的存储块
OS_ERR *p_err) //返回的错误码
6、时间管理
6.1 、延时
| 函数 | 描述 |
|---|
| OSTimeDly() | 延时执行任务n 个时基 |
| OSTimeDlyHMSM() | 延时执行任务 |
| OSTimeDlyResume() | 恢复处于延时状态的任务 |
| OSTimeGet() | 获得当前的时基计数值 |
| OSTimeSet() | 设置当前的时基计数值(谨慎使用) |
| OSTimeTick() | 用于标记,表示发生了一个时基中断 |
void OSTimeDly(OS_TICK dly, //指定延时的长度,单位为时间节拍
OS_OPT opt, //延时模式
OS_ERR *p_err) //返回错误类型
如果延时时间dly>0,则会发生任务调度; 0表示不延时
void OS_TimeDlyHMSM(CPU_INT16U hours,//延时小时
CPU_INT16U minutes,//分钟
CPU_INT16U seconds,//秒
CPU_INT32U milli,//毫秒
OS_OPT opt, //延时选项,范围大小
OS_ERR *p_err)//返回错误类型
| 延时选项 | 描述(OSTickCtr 为系统时钟节拍计数器) |
|---|
| OS_OPT_TIME_HMSM_STRICT | 延时时间参数严格按照实际的时间格式 任务延时的小时数(099) 任务延时的分钟数(059) 任务延时的秒数(059) 任务延时的毫秒数(0999) |
| OS_OPT_TIME_HMSM_NON_STRICT | 延时时间参数无需严格按照实际的时间格式 任务延时的小时数(0999) 任务延时的分钟数(09999) 任务延时的秒数(065535) 任务延时的毫秒数(04294967295) |
| OS_OPT_TIME_DLY | 任务延时的结束时刻为OSTickCtr=OSTickCtr+dly |
| OS_OPT_TIME_TIMEOUT | 任务延时的结束时刻为OSTickCtr=OSTickCtr+dly |
| OS_OPT_TIME_PERIODIC | 任务延时的结束时刻为 OSTickCtr= OSTCBCurPtr->TickCtrPrev+dly |
| OS_OPT_TIME_MATCH | 任务延时的结束时刻为OSTickCtr=dly |
void OSTimeDlyResume (OS_TCB *p_tcb,//需要恢复的任务的任务控制块
OS_ERR *p_err)//返回错误类型
一个任务可以通过调用这个函数来“解救”那些因为调用了 OSTimeDly() 或者 OSTimeDlyHMSM() 函数而进入等待态的任务
6.2、软件定时器
需要使用软件定时器需将 OS_CFG_TMR_EN 配置为 1
| 函数 | 描述 |
|---|
| OSTmrCreate() | 创建和设置定时器 |
| OSTmrDel() | 删除一个定时器 |
| OSTmrRemainGet() | 获得定时器的剩余期限值 |
| OSTmrSet() | 设置软件定时器的延时时间、周期、超时回调函数及其参数等 |
| OSTmrStart() | 开始定时器运行 |
| OSTmrStateGet() | 获得定时器当前的状态 |
| OSTmrStop() | 暂停定时器 |
void OSTmrCreate (OS_TMR *p_tmr, //指向软件定时器结构体的指针
CPU_CHAR *p_name, //名指向作为软件定时器名的ASCII 字符串的指针
OS_TICK dly, //软件定时器的开启延时时间
OS_TICK period, //周期定时器的定时周期时间
OS_OPT opt, //选择单次还是周期定时器
OS_TMR_CALLBACK_PTR p_callback,//指向软件定时器超时回调函数的指针
void *p_callback_arg, //指向软件定时器超时回调函数参数的指针
OS_ERR *p_err) //指向接收错误代码变量的指针
opt: OS_OPT_TMR_ONE_SHOT 单次定时器
OS_OPT_TMR_ONE_PERIODIC 周期定时器
CPU_BOOLEAN OSTmrDel( OS_TMR* p_tmr, //指向软件定时器结构体的指针
OS_ERR* p_err) //指向接收错误代码变量的指针
OS_TICK OSTmrRemainGet( OS_TMR* p_tmr, //指向软件定时器结构体的指针
OS_ERR* p_err) //指向接收错误代码变量的指针
void OSTmrSet( OS_TMR* p_tmr, //指向软件定时器结构体的指针
OS_TICK dly, //软件定时器的延时启动时间
OS_TICK period, //周期定时器的定时周期时间
OS_TMR_CALLBACK_PTR p_callback, //指向软件定时器超时回调函数的指针
void* p_callback_arg, //指向软件定时器超时回调函数参数的指针
OS_ERR* p_err) //指向接收错误代码变量的指针
CPU_BOOLEAN OSTmrStart( OS_TMR* p_tmr, //指向软件定时器结构体的指针
OS_ERR* p_err) //指向接收错误代码变量的指针
//返回值 软件定时器的状态
OS_STATE OSTmrStateGet( OS_TMR* p_tmr, //指向软件定时器结构体的指针
OS_ERR* p_err) //指向接收错误代码变量的指针
//返回值 停止软件定时器是否成功
CPU_BOOLEAN OSTmrStop( OS_TMR* p_tmr, //指向软件定时器结构体的指针
OS_OPT opt, //函数操作选项
void* p_callback_arg, //指向传给软件定时器超时回调函数的参数的指针
OS_ERR* p_err) //指向接收错误代码变量的指针
opt: OS_OPT_TMR_NONE 只需要停止定时器,不执行指定事件
OS_OPT_TMR_CALLBACK 停止定时器,并执行回调函数
OS_OPT_TMR_CALLBACK_ARG 停止定时器,并执行回调函数,且将p_callback_arg作为新的实参
6.3、时间戳
| 函数 | 描述 |
|---|
| OS_TS_GET() | 获取时间戳 |
| CPU_TS32_to_uSec() | 将时间戳转换为以微秒为单位的时间数值 |
7、中断管理
| 函数 | 描述 |
|---|
| OSIntEnter() | 任务在进入中断服务函数时需要首先调用 OSIntEnter () 函数标记进入中断,方便中断嵌套管理。 |
| OSIntExit() | 与 OSIntEnter () 函数相对应, 任务在退出中断服务函数时需要首调用 OSIntExit () 函数标记退出中断,方便中断嵌套管理。 |
| CPU_IntDisMeasMaxGet() | 关中断时间(要测量关中断时间,除了要使能测量关中断时间功能外,还须在程序初始化时调用CPU_Init() 函数) |
| CPU_IntDisMeasMaxCurReset() | 测量某程序段运行过程中的最大关中断时间的功能函数。(要使用该功能,同样需要进行跟CPU_IntDisMeasMaxGet()函数一样的初始化。) |
| CPU_IntDisMeasMaxCurGet() | 用于结束程序段的最大关中断时间的测量,并返回测量的时间。 |
8、任务相关
| 函数 | 描述 |
|---|
| OSTaskCreate() | 创建任务 |
| OSTaskDel() | 删除任务 |
| OSTaskSuspend() | 挂起任务 |
| OSTaskResume() | 恢复任务 |
| OSStatTaskCPUUsageInit() | 统计任务 |
void OSTaskCreate( OS_TCB* p_tcb, // 指向任务控制块的指针
CPU_CHAR* p_name, //指向作为任务名的ASCII 字符串的指针
OS_TASK_PTR p_task, //指向任务函数的指针
void* p_arg, // 指向任务函数参数的指针
OS_PRIO prio, //任务的任务优先级
CPU_STK* p_stk_base, //指向任务栈起始地址的指针
CPU_STK_SIZE stk_limit, //任务的任务栈“水位”限制大小
CPU_STK_SIZE stk_size, //任务的任务栈大小
OS_MSG_QTY q_size, //任务内嵌消息队列的大小
OS_TICK time_quanta, //任务的时间片
void* p_ext, //指向用户自定义数据的指针
OS_OPT opt, //任务选项
OS_ERR* p_err); //指向接收错误代码变量的指针
void OSTaskDel( OS_TCB* p_tcb, //指向任务控制块的指针
OS_ERR* p_err) //指向接收错误代码变量的指针
void OSTaskSuspend( OS_TCB* p_tcb, //指向任务控制块的指针
OS_ERR* p_err) //指向接收错误代码变量的指针
此函数用于无条件地挂起任务,被挂起的任务不会参与任务调度,如果被挂起的任务是当前正在运行的任务,那么就会发起任务调度,将 CPU 的使用权交给另一个任务。被函数OSTaskSuspend()挂起的任务只能通过函数 OSTaskResume()恢复。如果任务挂起等待其他内核对象,那么即使任务被该函数恢复后,也将继续挂起等待内核对象。
void OSTaskResume( OS_TCB* p_tcb, //指向任务控制块的指针
OS_ERR* p_err) //指向接收错误代码变量的指针
此函数用于恢复被函数 OSTaskSuspend()挂起的任务,并且只有该函数才能恢复被函数OSTaskSuspend()挂起的任务,由此可见,被函数OSTaskSuspend()挂起的任务只能由另一个任务通过函数OSTaskResume()进行恢复。
9、消息队列
9.1、任务间消息
消息队列中包含了消息,这些消息可以通过消息队列进行传输,也可以以直接送到指定的任务中,因为每个任务都可以有独自的内嵌消息队列。通过消息队列传输的消息,可以发送给多个任务。
参数 OS_CFG_MSG_POOL_SIZE 定义了支持的最大消息池大小
| 函数 | 描述 |
|---|
| OSQCreate() | 创建一个消息队列 |
| OSQDel() | 删除一个消息队列 |
| OSQFlush() | 清空消息队列中的所有消息 |
| OSQPend() | 获取消息队列中的消息 |
| OSQPendAbort() | 终止任务挂起等待消息队列 |
| OSQPost() | 发送消息到消息队列 |
void OSQCreate( OS_Q* p_q, //指向消息队列结构体的指针
CPU_CHAR* p_name, //指向作为消息队列名的ASCII 字符串的指针
OS_MSG_QTY max_qty, //消息队列的大小
OS_ERR* p_err) //指向接收错误代码变量的指针
max_qty:必须大于0
OS_OBJ_QTY OSQDel( OS_Q* p_q, //指向消息队列结构体的指针
OS_OPT opt, //函数操作选项
OS_ERR* p_err) //指向接收错误代码变量的指针
OS_MSG_QTY OSQFlush( OS_Q* p_q, //指向消息队列结构体的指针
OS_ERR* p_err) //指向接收错误代码变量的指针
void *OSQPend( OS_Q* p_q, //指向消息队列结构体的指针
OS_TICK timeout, //任务挂起等待消息队列的最大允许时间
OS_OPT opt, //函数操作选项
OS_MSG_SIZE* p_msg_size, //指向用于接收消息大小变量的指针
CPU_TS* p_ts, //指向接收消息队列接收时的时间戳的变量的指针
OS_ERR* p_err) //指向接收错误代码变量的指针
timeout: 0表示一直等待下去
opt: OS_OPT_PEND_BLOCKING 如果没有任何消息存在的话就阻塞任务,一直等待,直到接收到消息。
OS_OPT_PEND_NON_BLOCKING 如果消息队列没有任何消息的话任务就直接返回。
OS_OBJ_QTY OSQPendAbort( OS_Q* p_q, //指向消息队列结构体的指针
OS_OPT opt, //函数操作选项
OS_ERR* p_err) //指向接收错误代码变量的指针
void OSQPost( OS_Q* p_q, //指向消息队列结构体的指针
void* p_void, //指向消息的指针
OS_MSG_SIZE msg_size, //消息的大小,单位:字节
OS_OPT opt, //函数操作选项
OS_ERR* p_err) //指向接收错误代码变量的指针
opt: OS_OPT_POST_ALL 将消息发送给所有等待该消息队列的任务,需要和选项 OS_OPT_POST_FIFO 或者OS_OPT_POST_LIFO 配合使用。
OS_OPT_POST_FIFO 待发送消息保存在消息队列的末尾
OS_OPT_POST_LIFO 待发送的消息保存在消息队列的开头
OS_OPT_POST_NO_SCHED 禁止在本函数内执行任务调度。
9.2、任务内嵌消息队列
| 函数 | 描述 |
|---|
| OSTaskQFlush() | 清空任务内嵌消息队列中的所有消息 |
| OSTaskQPend() | 获取任务内嵌消息队列中的消息 |
| OSTaskQPendAbort() | 终止任务挂起等待任务内嵌消息队列 |
| OSTaskQPost() | 发送消息到任务内嵌消息队列 |
OS_MSG_QTY OSTaskQFlush( OS_TCB* p_tcb, //指向任务控制块的指针
OS_ERR* p_err) //指向接收错误代码变量的指针
void *OSTaskQPend( OS_TICK timeout, //任务挂起等待任务内嵌消息队列的最大允许时间
OS_OPT opt, //函数操作选项
OS_MSG_SIZE* p_msg_size //指向用于接收消息大小变量的指针
CPU_TS* p_ts, //指向接收消息队列接收时的时间戳的变量的指针
OS_ERR* p_err) //指向接收错误代码变量的指针
timeout: 0表示一直等待下去
opt: OS_OPT_PEND_BLOCKING 如果没有任何消息存在的话就阻塞任务,一直等待,直到接收到消息。
OS_OPT_PEND_NON_BLOCKING 如果消息队列没有任何消息的话任务就直接返回。
CPU_BOOLEAN OSTaskQPendAbort( OS_TCB* p_tcb, //指向任务控制块的指针
OS_OPT opt, //函数操作选项
OS_ERR* p_err) //指向接收错误代码变量的指针
void OSTaskQPost( OS_TCB* p_tcb, //指向任务控制块的指针
void* p_void, //指向消息的指针
OS_MSG_SIZE msg_size, //消息的大小,单位:字节
OS_OPT opt, //函数操作选项
OS_ERR* p_err) //指向接收错误代码变量的指针
opt: OS_OPT_POST_FIFO 待发送消息保存在消息队列的末尾
OS_OPT_POST_LIFO 待发送的消息保存在消息队列的开头
FreeRTOS
1、临界段
临界区是指那些必须完整运行的区域,在临界区中的代码必须完整运行,不能被打断。例如一些使用软件模拟的通信协议,通信协议在通信时,必须严格按照通信协议的时序进行,不能被打断。在正常中断中,如果中断优先级大于等于configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY所设置的值时,进入临界段后终端将被屏蔽。
| 函数 | 描述 |
|---|
| taskENTER_CRITICAL() | 进入临界区 |
| taskENTER_CRITICAL_FROM_ISR() | 中断进入临界区 |
| taskEXIT_CRITICAL() | 退出临界区 |
| taskEXIT_CRITICAL_FROM_ISR(x) | 中断退出临界区 |
2、任务相关
| 函数 | 描述 |
|---|
| xTaskCreate() | 动态方式创建任务 |
| xTaskCreateStatic() | 静态方式创建任务 |
| xTaskCreateRestricted() | 动态方式创建使用 MPU 限制的任务 |
| xTaskCreateRestrictedStatic() | 静态方式创建使用 MPU 限制的任务 |
| vTaskDelete() | 删除任务 |
| vTaskSuspend() | 挂起任务 |
| vTaskResume() | 恢复被挂起的任务 |
| xTaskResumeFromISR() | 在中断中恢复被挂起的任务 |
| uxTaskPriorityGet() | 获取任务优先级 |
| vTaskPrioritySet() | 设置任务优先级 |
| uxTaskGetSystemState() | 获取所有任务的状态信息 |
| vTaskGetInfo() | 获取单个任务的状态信息 |
| xTaskGetApplicationTaskTag() | 获取任务 Tag |
| xTaskGetCurrentTaskHandle() | 获取当前任务的任务句柄 |
| xTaskGetHandle() | 获取指定任务的任务句柄 |
| xTaskGetIdleTaskHandle() | 获取空闲任务的任务句柄 |
| uxTaskGetStackHighWaterMark() | 获取任务的任务栈历史剩余最小值 |
| eTaskGetState() | 获取任务状态 |
| pcTaskGetName() | 获取任务名 |
| xTaskGetTickCount() | 获取系统时钟节拍计数器的值 |
| xTaskGetTickCountFromISR() | 中断中获取系统使用节拍计数器的值 |
| xTaskGetSchedulerState() | 获取任务调度器状态 |
| uxTaskGetNumberOfTasks() | 获取系统中任务的数量 |
| vTaskList() | 以“表格”形式获取所有任务的信息 |
| vTaskGetRunTimeStats() | 获取任务的运行时间等信息 |
| vTaskSetApplicationTaskTag() | 设置任务 Tag |
| SetThreadLocalStoragePointer() | 设置任务的独有数据记录数组指针 |
| GetThreadLocalStoragePointer() | 获取任务的独有数据记录数组指针 |
BaseType_t xTaskCreate(
TaskFunction_t pxTaskCode, //指向任务函数的指针
const char * const pcName, //任务名,最大长度为 configMAX_TASK_NAME_LEN
const configSTACK_DEPTH_TYPE usStackDepth,//任务堆栈大小,单位:字(注意,单位不是字节)
void * const pvParameters,//传递给任务函数的参数
UBaseType_t uxPriority,//任务优先级,最大值为(configMAX_PRIORITIES-1)
TaskHandle_t * const pxCreatedTask);//任务句柄,任务成功创建后,会返回任务句柄
此函数用于使用动态的方式创建任务,任务的任务控制块以及任务的栈空间所需的内存,均由 FreeRTOS 从 FreeRTOS 管理的堆中分配,若使用此函数,需要在 FreeRTOSConfig.h 文件中将宏 configSUPPORT_DYNAMIC_ALLOCATION 配置为 1。
TaskHandle_t xTaskCreateStatic(
TaskFunction_t pxTaskCode,//指向任务函数的指针
const char * const pcName,//任务名,最大长度为 configMAX_TASK_NAME_LEN
const uint32_t ulStackDepth,//任务堆栈大小,单位:字(注意,单位不是字节)
void * const pvParameters,//传递给任务函数的参数
UBaseType_t uxPriority,//任务优先级,最大值为(configMAX_PRIORITIES-1)
StackType_t * const puxStackBuffer,//任务栈指针,内存由用户分配提供
StaticTask_t * const pxTaskBuffer);//任务控制块指针,内存由用户分配提供
此函数用于使用静态的方式创建任务,任务的任务控制块以及任务的栈空间所需的内存,需 要 由 用 户 分 配 提 供 ,若 使 用 此 函 数 , 需 要 在 FreeRTOSConfig.h 文 件 中 将 宏configSUPPORT_STATIC_ALLOCATION 配置为 1。
TaskHandle_t xTaskCreateRestricted(
const TaskParameters_t * const pxTaskDefinition,//指向任务参数结构体的指针,建结构体中包含任务函数、任务名、任务优先级等任务参数
TaskHandle_t * pxCreatedTask);//任务句柄,任务成功创建后,会返回任务句柄。任务句柄就是任务的任务控制块
此函数用于使用动态的方式创建受 MPU 保护的任务,任务的任务控制块以及任务的栈空间所需的内存,均由 FreeRTOS 从 FreeRTOS 管理的堆中分配,若使用此函数,需要将宏configSUPPORT_DYNAMIC_ALLOCATION 和宏 portUSING_MPU_WRAPPERS 同时配置为 1。
BaseType_t xTaskCreateRestrictedStatic(
const TaskParameters_t * const pxTaskDefinition,//指向任务参数结构体的指针,建结构体中包含任务函数、任务名、任务优先级等任务参数
TaskHandle_t * pxCreatedTask);//任务句柄,任务成功创建后,会返回任务句柄。任务句柄就是任务的任务控制块
此函数用于使用静态的方式创建受 MPU 保护的任务,此函数创建的任务的任务控制块以及任务的栈 空间所需的内存,需要 由用户 自行分配提供, 若使用此函数,需要将 宏configSUPPORT_STATIC_ALLOCATION 和宏portUSING_MPU_WRAPPERS 同时配置为 1。
void vTaskDelete(TaskHandle_t xTaskToDelete);//待删除任务的任务句柄
此函数用于删除已被创建的任务,被删除的任务将被从就绪态任务列表、阻塞态任务列表、挂起态任务列表和事件列表中移除,要注意的是,空闲任务会负责释放被删除任务中由系统分配的内存,但是由用户在任务删除前申请的内存,则需要由用户在任务被删除前提前释放,否则将导致内存泄露。若使用此函数,需要在FreeRTOSConfig.h文件中将宏INCLUDE_vTaskDelete配置为 1。
void vTaskSuspend(TaskHandle_t xTaskToSuspend);//待挂起任务的任务句柄
此 函 数 用 于 挂 起 任 务 , 若 使 用 此 函 数 , 需 要 在 FreeRTOSConfig.h 文 件 中 将 宏INCLUDE_vTaskSuspend 配置为 1。
void vTaskResume(TaskHandle_t xTaskToResume);//待恢复任务的任务句柄
此函数用于在任务中恢复被挂起的任务,若使用此函数,需要在 FreeRTOSConfig.h 文件中将宏 INCLUDE_vTaskSuspend 配置为 1。
BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume);//待恢复任务的任务句柄
此函数用于在中断中恢复被挂起的任务,若使用此函数,需要在 FreeRTOSConfig.h 文件中将宏 INCLUDE_xTaskResumeFromISR 配置为 1。
UBaseType_t uxTaskPriorityGet(const TaskHandle_t xTask);//待获取优先级的任务
此函数用于获取指定任务的任务优先级,若使用此函数,需在 FreeRTOSConfig.h 文件中设置配置项 INCLUDE_uxTaskPriorityGet 为 1。
void vTaskPrioritySet(
TaskHandle_t xTask, //待设置优先级的任务
UBaseType_t uxNewPriority); //任务优先级
此函数用于设置指定任务的优先级,若使用此函数,需在 FreeRTOSConfig.h 文件中设置配置项 INCLUDE_vTaskPrioritySet 为 1。
UBaseType_t uxTaskGetSystemState(
TaskStatus_t * const pxTaskStatusArray, //接收信息变量数组的首地址
const UBaseType_t uxArraySize, //接收信息变量数组的大小
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime); //系统总运行时间
此函数用于获取所有任务的状态信息,若使用此函数,需在 FreeRTOSConfig.h 文件中设置配置项 configUSE_TRACE_FACILITY 为 1。
void vTaskGetInfo(
TaskHandle_t xTask, //指定获取信息的任务
TaskStatus_t * pxTaskStatus, //接收任务信息的变量
BaseType_t xGetFreeStackSpace, //任务栈历史剩余最小值
eTaskState eState); //任务状态
此函数用于获取指定任务的任务信息,若使用此函数,需在 FreeRTOSConfig.h 文件中设置配置项 configUSE_TRACE_FACILITY 为 1。
TaskHookFunction_t xTaskGetApplicationTaskTag(TaskHandle_t xTask); //待获取 Tag 的任务
此函数用于获取指定任务的 Tag,若使用此函数,需在 FreeRTOSConfig.h 文件中设置配置项 configUSE_APPLICATION_TASK_TAG 为 1。
TaskHandle_t xTaskGetCurrentTaskHandle(void);//任务句柄
此 函 数 用 于 获 取 当 前 系 统 正 在 运 行 的 任 务 的 任 务 句 柄 , 若 使 用 此 函 数 , 需 在FreeRTOSConfig.h 文件中设置配置项 INCLUDE_xTaskGetCurrentTaskHandle 为 1。
TaskHandle_t xTaskGetHandle(const char * pcNameToQuery); //任务名
此函数用于通过任务名获取任务句柄,若使用此函数,需在 FreeRTOSConfig.h 文件中设置配置项 INCLUDE_xTaskGetHandle 为 1。
TaskHandle_t xTaskGetIdleTaskHandle(void);
此函数用于获取空闲任务的任务句柄,若使用此函数,需在 FreeRTOSConfig.h 文件中设置配置项 INCLUDE_xTaskGetIdleTaskHandle 为 1。
UBaseType_t uxTaskGetStackHighWaterMark(TaskHandle_t xTask); //待获取任务栈历史剩余最小值的任务
此 函 数 用 于 获 取 指 定 任 务 的 任 务 栈 的 历 史 剩 余 最 小 值 , 若 使 用 此 函 数 , 需 在。FreeRTOSConfig.h 文件中设置配置项 INCLUDE_uxTaskGetStackHighWaterMark 为 1。
eTaskState eTaskGetState(TaskHandle_t xTask); //待获取状态的任务
此函数用于获取指定任务的状态,若使用此函数,需在 FreeRTOSConfig.h 文件中设置配置项 INCLUDE_eTaskGetState 为 1。
char * pcTaskGetName(TaskHandle_t xTaskToQuery); //任务句柄
此函数用于获取指定任务的任务名
volatile TickType_t xTaskGetTickCount(void); //系统时钟节拍计数器的值
此函数用于获取系统时钟节拍计数器的值
volatile TickType_t xTaskGetTickCountFromISR(void);
此函数用于在中断中获取系统时钟节拍计数器的值
BaseType_t xTaskGetSchedulerState(void);
此函数用于获取任务调度器的运行状态
UBaseType_t uxTaskGetNumberOfTasks(void);
此函数用于获取系统中任务的数量
void vTaskList(char * pcWriteBuffer); //接收任务信息的缓存指针
此函数用于以“表格”的形式获取系统中任务的信息,若使用此函数,需在 FreeRTOSConfig.h文 件 中 同 时 设 置 配 置 项 configUSE_TRACE_FACILITY 和 配 置 项configUSE_STATS_FORMATTING_FUNCTIONS 为 1。
void vTaskGetRunTimeStats(char * pcWriteBuffer); //接收任务运行时间和状态等信息的缓存指针
此 函 数 用 于 获 取 指 定 任务 的 运 行 时 间 、 运 行 状态 等 信 息 , 若 使 用 此 函数 , 需 在FreeRTOSConfig.h 文 件 中 同 时 设 置 配 置 项 configGENERATE_RUN_TIME_STATS 、configUSE_STATS_FORMATTING_FUNCTIONS、configSUPPORT_DYNAMIC_ALLOCATION为 1。
void vTaskSetApplicationTaskTag(
TaskHandle_t xTask, //待插入 Tag 的任务
TaskHookFunction_t pxTagValue);//Tag 指针
此函数用于设置指定任务的 Tag,若使用此函数,需在 FreeRTOSConfig.h 文件中设置配置项 configUSE_APPLICATION_TASK_TAG 为 1。
void vTaskSetThreadLocalStoragePointer(
TaskHandle_t xTaskToSet, //待设置的任务
BaseType_t xIndex, //设置的指针
void * pvValue) //值
此函数用于设置指定任务的独有数据数组指针
void *pvTaskGetThreadLocalStoragePointer(
TaskHandle_t xTaskToQuery, //待获取的任务
BaseType_t xIndex); //收的指针
此函数用于获取指定任务的独有数据数组指针
3、列表和列表项
3.1、函数接口
| 函数 | 描述 |
|---|
| vListInitialise() | 初始化列表 |
| vListInitialiseItem() | 初始化列表项 |
| vListInsertEnd() | 列表末尾插入列表项 |
| vListInsert() | 列表插入列表项 |
| uxListRemove() | 列表移除列表项 |
void vListInitialise(List_t * const pxList);//待初始化列表
此函数用于初始化列表,在定义列表之后,需要先对其进行初始化,只有初始化后的列表,才能够正常地被使用。
void vListInitialiseItem(ListItem_t * const pxItem);//待初始化列表项
此函数用于初始化列表项,如同列表一样,在定义列表项之后,也需要先对其进行初始化,只有初始化有的列表项,才能够被正常地使用。
void vListInsertEnd(
List_t * const pxList,//列表
ListItem_t * const pxNewListItem);//待插入列表项
此函数用于将待插入列表的列表项插入到列表 pxIndex 指针指向列表项的前面,是一种无序的插入方法。
void vListInsert(
List_t * const pxList,//列表
ListItem_t * const pxNewListItem);//待插入列表项
此函数用于将待插入列表的列表项按照列表项值升序排序的顺序,有序地插入到列表中。
UBaseType_t uxListRemove(ListItem_t * const pxItemToRemove);//待移除的列表项
此函数用于将列表项从列表项所在列表中移除。
3.2、宏定义
| 宏定义 | 描述 |
|---|
| listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) | 设置列表项的拥有者 |
| listGET_LIST_ITEM_OWNER( pxListItem ) | 获取列表项的拥有者 |
| listSET_LIST_ITEM_VALUE( pxListItem, xValue ) | 设置列表项的值 |
| listGET_LIST_ITEM_VALUE( pxListItem ) | 获取列表项的值 |
| listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) | 获取列表头部列表项的值 |
| listGET_HEAD_ENTRY( pxList ) | 获取列表的头部列表项 |
| listGET_NEXT( pxListItem ) | 获取列表项的下一个列表项 |
| listGET_END_MARKER( pxList ) | 获取列表的尾部列表项 |
| listLIST_IS_EMPTY( pxList ) | 判断列表是否为空 |
| listCURRENT_LIST_LENGTH( pxList ) | 获取列表包含的列表项数量 |
| listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) | 获取下一个列表项的拥有者 |
| listREMOVE_ITEM( pxItemToRemove ) | 将列表项从列表中移除 |
| listINSERT_END( pxList, pxNewListItem ) | 列表末尾插入列表项 |
| listGET_OWNER_OF_HEAD_ENTRY( pxList ) | 获取列表头部列表项的拥有者 |
| listIS_CONTAINED_WITHIN( pxList, pxListItem ) | 判断列表项是否在列表中 |
| listLIST_ITEM_CONTAINER( pxListItem ) | 获取列表项所在列表 |
| listLIST_IS_INITIALISED( pxList ) | 判断列表是否完成初始化 |
4、系统启动流程及任务相关
FreeRTOS 中的任务就四种状态,分别为运行态、就绪态、阻塞态和挂起态,这四种状态中,除了运行态,其他三种任务状态的任务都有其对应的任务状态列表,FreeRTOS 使用这些任务状态列表来管理处于不同状态的任务。
| 函数 | 描述 |
|---|
| vTaskStartScheduler() | 启动任务调度器 |
| xTaskEndScheduler() | 停止任务调度器 |
| xPortStartScheduler() | 完成启动任务调度器中与硬件架构相关的配置部分,以及启动第一个任务 |
| prvStartFirstTask() | 初始化启动第一个任务前的环境,主要是重新设置 MSP 指针,并使能全局中断 |
| vPortSVCHandler() | SVC 的中断服务函数 |
| prvInitialiseNewTask() | 创建任务时,初始化任务控制块中的成员变量 |
| pxPortInitialiseStack() | 初始化任务栈 |
| prvAddNewTaskToReadList() | 将新建的任务添加到就绪态任务列表中, |
| prvDeleteTCB() | 用于释放待删除任务所占的内存空间 |
| vTaskSwitchContext() | 用于更新 pxCurrentTCB 指向就绪态任务列表中优先级最高的任务 |
| prvIdleTask() | 空闲任务主要用于处理待删除任务列表和低功耗 |
5、内核控制
| 函数 | 描述 |
|---|
| taskYIELD() | 请求切换任务 |
| taskENTER_CRITICAL() | 在任务中进入临界区 |
| taskEXIT_CRITICAL() | 在任务中退出临界区 |
| taskENTER_CRITICAL_FROM_ISR() | 在中断服务函数中进入临界区 |
| taskEXIT_CRITICAL_FROM_ISR() | 在中断服务函数中退出临界区 |
| taskDISABLE_INTERRUPTS() | 关闭受 FreeRTOS 管理的中断 |
| taskENABLE_INTERRUPTS() | 打开中断 |
| vTaskStartScheduler() | 开启任务调度器 |
| vTaskEndScheduler() | 关闭任务调度器 |
| vTaskSuspendAll() | 挂起任务调度器 |
| xTaskResumeAll() | 恢复任务调度器 |
| vTaskStepTick() | 设置系统时钟节拍计数器 |
| xTaskCatchUpTicks() | 中断后修正系统时钟节拍 |
6、时间管理
| 函数 | 描述 |
|---|
| vTaskDelay() | 任务延时函数,延时单位:系统时钟节拍 |
| vTaskDelayUntil() | 任务绝对延时函数,延时单位:系统时钟节拍 |
| xTaskAbortDelay() | 终止任务延时函数 |
void vTaskDelay( const TickType_t xTicksToDelay ) //系统时钟节拍
如需使用子函数,需要的 FreeRTOSConfig.h 文件中将配置项 INCLUDE_vTaskDelay 配置为 1。
FreeRTOS 是以系统时钟节拍作为计量的时间单位 的 , 而 系 统 时 钟 节 拍 对 应 的 物 理 时 间 长 短 于FreeRTOSConfig.h 文 件 中 的 配 置 项configTICK_RATE_HZ 有关,配置项 configTICK_RATE_HZ 是用于置系统时钟节拍的频率的,若将此配置项配置成了 1000,即系统时钟节拍的频率为 1000,换算过来,一个系统时钟节拍就是 1 毫秒。
如果传入的参数为 0,那表明不进行任务延时,而是强制进行一次任务切换。
BaseType_t xTaskDelayUntil(
TickType_t * const pxPreviousWakeTime, //上一次阻塞超时时间
const TickType_t xTimeIncrement) //延时的时间
对任务进行延时的操作,是相对于任务上一次阻塞超时的时间,而不是相对于系统当前的时钟节拍计数器的值,因此,函数能够更准确地以一定的频率进行任务延时,更加适用于需要按照一定频率运行的任务。
BaseType_t xTaskAbortDelay( TaskHandle_t xTask )//任务控制块
用于终止处于阻塞态任务的阻塞
7、队列
队列是一种任务到任务、任务到中断、中断到任务数据交流的一种机制。在队列中可以存储数量有限、大小固定的多个数据,队列中的每一个数据叫做队列项目,队列能够存储队列项目的最大数量称为队列的长度,在创建队列的时候,就需要指定所创建队列的长度及队列项目的大小。
基于队列,FreeRTOS 实现了多种功能,其中包括队列集、互斥信号量、计数型信号量、二值信号量、递归互斥信号量。
7.1、创建列表
| 函数 | 描述 |
|---|
| xQueueCreate() | 动态方式创建队列 |
| xQueueCreateStatic() | 静态方式创建队列 |
#define xQueueCreate( uxQueueLength, \ /* 队列长度 */
uxItemSize ) \ /* 队列项目的大小 */
xQueueGenericCreate( ( uxQueueLength ), \
( uxItemSize ), \
( queueQUEUE_TYPE_BASE ))
用于使用动态方式创建队列,队列所需的内存空间由 FreeRTOS 从 FreeRTOS 管理的堆中分配。
#define xQueueCreateStatic( uxQueueLength, \ /* 队列长度 */
uxItemSize, \ /* 队列项目的大小 */
pucQueueStorage, \ /* 队列存储区域的起始地址 */
pxQueueBuffer) \ /* 静态队列结构体 */
xQueueGenericCreateStatic( ( uxQueueLength ), \
( uxItemSize ), \
( pucQueueStorage ), \
( pxQueueBuffer ), \
( queueQUEUE_TYPE_BASE ))
用于使用静态方式创建队列,队列所需的内存空间需要由用户手动分配并提供。
#define queueQUEUE_TYPE_BASE ( ( uint8_t ) 0U ) /* 队列 */
#define queueQUEUE_TYPE_SET ( ( uint8_t ) 0U ) /* 队列集 */
#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U ) /* 互斥信号量 */
#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( uint8_t ) 2U ) /* 计数型信号量 */
#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U ) /* 二值信号量 */
#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( uint8_t ) 4U ) /* 递归互斥信号量 */
7.2、列表写入消息
| 函数 | 描述 |
|---|
| xQueueSend() | 往队列的尾部写入消息 |
| xQueueSendToBack() | 同 xQueueSend() |
| xQueueSendToFront() | 往队列的头部写入消息 |
| xQueueOverwrite() | 覆写队列消息(只用于队列长度为 1 的情况) |
| xQueueSendFromISR() | 在中断中往队列的尾部写入消息 |
| xQueueSendToBackFromISR() | 同 xQueueSendFromISR() |
| xQueueSendToFrontFromISR() | 在中断中往队列的头部写入消息 |
| xQueueOverwriteFromISR() | 在中断中覆写队列消息(只用于队列长度为 1 的情况) |
#define xQueueSend( xQueue, \
pvItemToQueue, \
xTicksToWait) \
xQueueGenericSend( ( xQueue ), \
( pvItemToQueue ), \
( xTicksToWait ), \
queueSEND_TO_BACK)
#define xQueueSendToBack( xQueue, \
pvItemToQueue, \
xTicksToWait) \
xQueueGenericSend( ( xQueue ), \
( pvItemToQueue ), \
( xTicksToWait ), \
queueSEND_TO_BACK)
#define xQueueSendToFront( xQueue, \
pvItemToQueue, \
xTicksToWait) \
xQueueGenericSend( ( xQueue ), \
( pvItemToQueue ), \
( xTicksToWait ), \
queueSEND_TO_FRONT)
#define xQueueOverwrite( xQueue, \
pvItemToQueue) \
xQueueGenericSend( ( xQueue ), \
( pvItemToQueue ), \
0, \
queueOVERWRITE)
#define queueSEND_TO_BACK ( ( BaseType_t ) 0 ) /* 写入队列尾部 */
#define queueSEND_TO_FRONT ( ( BaseType_t ) 1 ) /* 写入队列头部 */
#define queueOVERWRITE ( ( BaseType_t ) 2 ) /* 覆写队列 */
BaseType_t xQueueGenericSend( QueueHandle_t xQueue, //待写入的队列
const void * const pvItemToQueue, //待写入消息
TickType_t xTicksToWait, //阻塞超时时间
const BaseType_t xCopyPosition); //写入的位置
用于在任务中往队列的指定位置写入消息
#define xQueueSendFromISR( xQueue, \
pvItemToQueue, \
pxHigherPriorityTaskWoken) \
xQueueGenericSendFromISR( ( xQueue ), \
( pvItemToQueue ), \
( pxHigherPriorityTaskWoken ), \
queueSEND_TO_BACK)
#define xQueueSendToBackFromISR( xQueue, \
pvItemToQueue, \
pxHigherPriorityTaskWoken) \
xQueueGenericSendFromISR( ( xQueue ), \
( pvItemToQueue ), \
( pxHigherPriorityTaskWoken ), \
queueSEND_TO_BACK)
#define xQueueSendToFrontFromISR( xQueue, \
pvItemToQueue, \
pxHigherPriorityTaskWoken) \
xQueueGenericSendFromISR( ( xQueue ), \
( pvItemToQueue ), \
( pxHigherPriorityTaskWoken ), \
queueSEND_TO_FRONT)
#define xQueueOverwriteFromISR( xQueue, \
pvItemToQueue, \
pxHigherPriorityTaskWoken) \
xQueueGenericSendFromISR( ( xQueue ), \
( pvItemToQueue ), \
( pxHigherPriorityTaskWoken ), \
queueOVERWRITE)
BaseType_t xQueueGenericSendFromISR(
QueueHandle_t xQueue, //待写入的队列
const void * const pvItemToQueue, //待写入的消息
BaseType_t * const pxHigherPriorityTaskWoken, //需要任务切换标记
const BaseType_t xCopyPosition); //写入的位置
用于在中断中往队列的指定位置写入消息
7.3、列表读取消息
| 函数 | 描述 |
|---|
| xQueueReceive() | 从队列头部读取消息,并删除消息 |
| xQueuePeek() | 从队列头部读取消息 |
| xQueueReceiveFromISR() | 在中断中从队列头部读取消息,并删除消息 |
| xQueuePeekFromISR() | 在中断中从队列头部读取消息 |
BaseType_t xQueueReceive( QueueHandle_t xQueue, //待读取的队列
void * const pvBuffer, //信息读取缓冲区
TickType_t xTicksToWait); //阻塞超时时间
于在任务中,从队列中读取消息,并且消息读取成功后,会将消息从队列中移除。消息的读取是通过拷贝的形式传递的,具体拷贝数据的大小,为队列项目的大小。
BaseType_t xQueuePeek( QueueHandle_t xQueue, //待读取的队列
void * const pvBuffer, //信息读取缓冲区
TickType_t xTicksToWait); //阻塞超时时间
在任务中,从队列中读取消息,此函数在成功读取消息后,并不会移除已读取的消息。
BaseType_t xQueueReceiveFromISR(
QueueHandle_t xQueue, //待读取的队列
void * const pvBuffer, //信息读取缓冲区
BaseType_t * const pxHigherPriorityTaskWoken);//需要任务切换标记
用于在中断中,从队列中读取消息,并且消息读取成功后,会将消息从队列中移除。
BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, //待读取的队列
void * const pvBuffer); //信息读取缓冲区
用于在中断中,从队列中读取消息,此函数在成功读取消息后,并不会移除已读取的消息。
7.4、队列集
| 函数 | 描述 |
|---|
| xQueueCreateSet() | 创建队列集 |
| xQueueAddToSet() | 队列添加到队列集中 |
| xQueueRemoveFromSet() | 从队列集中移除队列 |
| xQueueSelectFromSet() | 获取队列集中有有效消息的队列 |
| xQueueSelectFromSetFromISR() | 在中断中获取队列集中有有效消息的队列 |
QueueSetHandle_t xQueueCreateSet(const UBaseType_t uxEventQueueLength);//队列集可容纳的队列数量
BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, //待添加的队列
QueueSetHandle_t xQueueSet); //队列集
用于往队列集中添加队列,要注意的时,队列在被添加到队列集之前,队列中不能有有效的消息。
BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, //待移除的队列
QueueSetHandle_t xQueueSet); //队列集
数用于从队列集中移除队列,要注意的时,队列在从队列集移除之前,必须没有有效的消息
QueueSetMemberHandle_t xQueueSelectFromSet(
QueueSetHandle_t xQueueSet, //队列集
TickType_t const xTicksToWait); //阻塞超时时间
用于在任务中获取队列集中有有效消息的队列
QueueSetMemberHandle_t xQueueSelectFromSetFromISR(
QueueSetHandle_t xQueueSet ); //队列集
用于在中断中获取队列集中有有效消息的队列
8、信号量
信号量是一种解决同步问题的机制,可以实现对共享资源的有序访问。其中,“同步”指的是任务间的同步,即信号量可以使得一个任务等待另一个任务完成某件事情后,才继续执行;而“有序访问”指的是对被多任务或中断访问的共享资源(如全局变量)的管理,当一个任务在访问(读取或写入)一个共享资源时,信号量可以防止其他任务或中断在这期间访问(读取或写入)这个共享资源。
8.1、二值信号量
二值信号量实际上就是一个队列长度为 1 的队列,因此二值信号量只能容纳一个资源,在这种情况下,队列就只有空和满两种情况。
| 函数 | 描述 |
|---|
| xSemaphoreCreateBinary() | 使用动态方式创建二值信号量 |
| xSemaphoreCreateBinaryStatic() | 使用静态方式创建二值信号量 |
| xSemaphoreTake() | 获取信号量 |
| xSemaphoreTakeFromISR() | 在中断中获取信号量 |
| xSemaphoreGive() | 释放信号量 |
| xSemaphoreGiveFromISR() | 在中断中释放信号量 |
| vSemaphoreDelete() | 删除信号量 |
8.2、计数型信号量
计数型信号量相当于队列长度大于0 的队列,因此计数型信号量能够容纳多个资源,这是在计数型信号量被创建的时候确定的。
| 函数 | 描述 |
|---|
| xSemaphoreCreateCounting() | 使用动态方式创建计数型信号量 |
| xSemaphoreCreateCountingStatic() | 使用静态方式创建计数型信号量 |
| xSemaphoreTake() | 获取信号量 |
| xSemaphoreTakeFromISR() | 在中断中获取信号量 |
| xSemaphoreGive() | 释放信号量 |
| xSemaphoreGiveFromISR() | 在中断中释放信号量 |
| vSemaphoreDelete() | 删除信号量 |
| uxSemaphoreGetCount() | 获取计数型信号量资源数 |
#define xSemaphoreCreateCounting( uxMaxCount, /* 计数型信号量最大值 */
uxInitialCount ) /* 计数型信号量初始值 */
8.3、互斥信号量
互斥信号量其实就是一个拥有优先级继承的二值信号量。互斥信号量使用和二值信号量相同的 API 操作函数,所以互斥信号量也可以设置阻塞时间,不同于二值信号量的是互斥信号量具有优先级继承的机制。互斥信号量不能用于中断服务函数中。
| 函数 | 描述 |
|---|
| xSemaphoreCreateMutex() | 使用动态方式创建互斥信号量 |
| xSemaphoreCreateMutexStatic() | 使用静态方式创建互斥信号量 |
| xSemaphoreTake() | 获取信号量 |
| xSemaphoreGive() | 释放信号量 |
| vSemaphoreDelete() | 删除信号量 |
8.4、递归互斥信号量
| 函数 | 描述 |
|---|
| xSemaphoreCreateRecursiveMutex() | 使用动态方式创建递归互斥信号量 |
| xSemaphoreCreateRecursiveMutexStatic() | 使用静态方式创建递归互斥信号量 |
| xSemaphoreTakeRecursive() | 获取递归互斥信号量 |
| xSemaphoreGiveRecursive() | 释放递归互斥信号量 |
| vSemaphoreDelete() | 删除信号量 |
递归互斥信号量可以看作是特殊的互斥信号量,与互斥信号量不同的是,递归互斥信号量在被获取后,可以被其持有者重复获取,当然递归互斥信号量的持有者需要释放递归互斥信号量与之获取递归互斥信号量相同的次数,递归互斥信号量才算被释放。
递归互斥信号量与互斥信号量一样,也具备优先级继承机制,因此也不能在中断服务函数中使用递归互斥信号量。
9、软件定时器
如果要使能软件定时器功能,那需要在 FreeRTOSConfig.h 文件中将 configUSE_TIMERS 配置项配置成 1。不能在该回调函数中使用可能会导致任务阻塞的 API 函数。
软件定时器功能是可选的,用户可以根据需要配置 FreeRTOSConfig.h 文件中的configUSE_TIMERS,同时 FreeRTOSConfig.h 文件中还有一些其他与软件定时器相关的配置项。
| 函数 | 描述 |
|---|
| xTimerCreate() | 动态方式创建软件定时器 |
| xTimerCreateStatic() | 静态方式创建软件定时器 |
| xTimerStart() | 开启软件定时器定时 |
| xTimerStartFromISR() | 在中断中开启软件定时器定时 |
| xTimerStop() | 停止软件定时器定时 |
| xTimerStopFromISR() | 在中断中停止软件定时器定时 |
| xTimerReset() | 复位软件定时器定时 |
| xTimerResetFromISR() | 在中断中复位软件定时器定时 |
| xTimerChangePeriod() | 更改软件定时器的定时超时时间 |
| xTimerChangePeriodFromISR() | 在中断中更改软件定时器的定时超时时间 |
| xTimerDelete() | 删除软件定时器 |
TimerHandle_t xTimerCreate(
const char * const pcTimerName,//软件定时器名
const TickType_t xTimerPeriodInTicks, //定时超时时间,单位:系统时钟节拍
const UBaseType_t uxAutoReload,//定时器模式,pdTRUE:周期定时器,pdFALSE:单次定时器
void * const pvTimerID, //软件定时器 ID,用于多个软件定时器公用一个超时回调函数
TimerCallbackFunction_t pxCallbackFunction); //软件定时器超时回调函数
动态方式创建软件定时器
TimerHandle_t xTimerCreateStatic(
const char * const pcTimerName, //软件定时器名
const TickType_t xTimerPeriodInTicks, //定时超时时间,单位:系统时钟节拍
const UBaseType_t uxAutoReload, //定时器模式,pdTRUE:周期定时器,pdFALSE:单次定时器
void * const pvTimerID, //软件定时器 ID,用于多个软件定时器公用一个超时回调函数
TimerCallbackFunction_t pxCallbackFunction, //软件定时器超时回调函数
StaticTimer_t * pxTimerBuffer); //创建软件定时器所需的内存空间
静态方式创建软件定时器
BaseType_t xTimerStart( TimerHandle_t xTimer, //待开启的软件定时器的句柄
const TickType_t xTicksToWait); //发送命令到软件定时器命令队列的最大等待时间
在任务中开启软件定时器
BaseType_t xTimerStartFromISR( TimerHandle_t xTimer, //待开启的软件定时器的句柄
BaseType_t * const pxHigherPriorityTaskWoken);//用于标记函数退出后是否需要进行任务切换
在中断中开启软件定时器
BaseType_t xTimerStop( TimerHandle_t xTimer, //待停止的软件定时器的句柄
const TickType_t xTicksToWait); //发送命令到软件定时器命令队列的最大等待时间
在任务中停止软件定时器
BaseType_t xTimerStopFromISR( TimerHandle_t xTimer, //待停止的软件定时器的句柄
BaseType_t * const pxHigherPriorityTaskWoken); //用于标记函数退出后是否需要进行任务切换
在中断中停止软件定时器
BaseType_t xTimerReset( TimerHandle_t xTimer, //待复位的软件定时器的句柄
const TickType_t xTicksToWait); //发送命令到软件定时器命令队列的最大等待时间
在任务中复位软件定时器
BaseType_t xTimerResetFromISR( TimerHandle_t xTimer, //待复位的软件定时器的句柄
BaseType_t * const pxHigherPriorityTaskWoken);//用于标记函数退出后是否需要进行任务切换
在中断中复位软件定时器
BaseType_t xTimerChangePeriod( TimerHandle_t xTimer, //待更改定时超时时间的软件定时器的句柄
const TickType_t xNewPeriod, //新的定时超时时间,单位:系统时钟节拍
const TickType_t xTicksToWait); //发送命令到软件定时器命令队列的最大等待时间
在任务中更改软件定时器的定时超时
BaseType_t xTimerChangePeriodFromISR(
TimerHandle_t xTimer, //待更改定时超时时间的软件定时器的句柄
const TickType_t xNewPeriod, //新的定时超时时间,单位:系统时钟节拍
BaseType_t * const pxHigherPriorityTaskWoken); //用于标记函数退出后是否需要进行任务切换
在中断中更改软件定时器的定时超时时间
BaseType_t xTimerDelete( TimerHandle_t xTimer, //待删除的软件定时器的句柄
const TickType_t xTicksToWait); //发送命令到软件定时器命令队列的最大等待时间
删除软件定时器
10、事件标志组
| 函数 | 描述 |
|---|
| xEventGroupCreate() | 使用动态方式创建事件标志组 |
| xEventGroupCreateStstic() | 使用静态方式创建事件标志组 |
| vEventGroupDelete() | 删除事件标志组 |
| xEventGroupWaitBits() | 等待事件标志位 |
| xEventGroupSetBits() | 设置事件标志位 |
| xEventGroupSetBitsFromISR() | 在中断中设置事件标志位 |
| xEventGroupClearBits() | 清零事件标志位 |
| xEventGroupClearBitsFromISR() | 在中断中清零事件标志位 |
| xEventGroupGetBits() | 获取事件组中各事件标志位的值 |
| xEventGroupGetBitsFromISR() | 在中断中获取事件组中各事件标志位的值 |
| xEventGroupSync() | 设置事件标志位,并等待事件标志位 |
EventGroupHandle_t xEventGroupCreate(void);
动态方式创建事件标志组
EventGroupHandle_t xEventGroupCreateStatic(
StaticEventGroup_t * pxEventGroupBuffer); //创建事件标志组所需的内存空间
静态方式创建事件标志组
void vEventGroupDelete(EventGroupHandle_t xEventGroup); //待删除的事件标志组句柄
删除事件标志组
EventBits_t xEventGroupWaitBits(
EventGroupHandle_t xEventGroup, //等待的事件标志组
const EventBits_t uxBitsToWaitFor, //等待的事件标志位,可以用逻辑或等待多个事件标志位
const BaseType_t xClearOnExit, //成功等待到事件标志位后,清除事件组中对应的事件标志位
const BaseType_t xWaitForAllBits, //等待 uxBitsToWaitFor 中的所有事件标志位(逻辑与)
TickType_t xTicksToWait) //获取等待的阻塞时间
等待事件标志位
EventBits_t xEventGroupSetBits(
EventGroupHandle_t xEventGroup, //待操作的事件标志组
const EventBits_t uxBitsToSet) //待设置的事件标志位
在任务中设置事件标志位
BaseType_t xEventGroupSetBitsFromISR(
EventGroupHandle_t xEventGroup, //待操作的事件标志组
const EventBits_t uxBitsToSet, //带设置的事件标志位
BaseType_t * pxHigherPriorityTaskWoken) //用于标记函数退出后是否需要进行任务切换
在中断中设置事件标志位
EventBits_t xEventGroupClearBits(
EventGroupHandle_t xEventGroup, //待操作的事件标志组
const EventBits_t uxBitsToClear) //待清零的事件标志位
在任务中清零事件标志位
BaseType_t xEventGroupClearBitsFromISR(
EventGroupHandle_t EventGroup, //待操作的事件标志组
const EventBits_t uxBitsToClear) //带清零的事件标志位
在中断中清零事件标志位
EventBits_t xEventGroupGetBits(xEventGroup); //待获取事件标志位值的事件组
在任务中获取事件组中事件标志位值
EventBits_t xEventGroupGetBitsFromISR(EventGroupHandle_t xEventGroup); //待获取事件标志位值的事件组
在中断中获取事件标志位
EventBits_t xEventGroupSync(
EventGroupHandle_t xEventGroup, //等待事件标志所在事件组
const EventBits_t uxBitsToSet, //达到同步点后,要设置的事件标志
const EventBits_t uxBitsToWaitFor, //等待的事件标志
TickType_t xTicksToWait) //等待的阻塞时间
此函数一般用于多任务同步,其中每个任务都必须等待其他任务达到同步点,然后才能继续执行。
11、任务通知
FreeRTOS 内核 V8.2.0 版本发布的时候,FreeRTOS 新增了任务通知这个功能,任务通知也是用于任务间进行同步和通讯的一种机制,但是相对于前面章节介绍的队列、事件标志组和信号量等而言,任务通知在内存占用和效率方面都有很大的优势。
| 函数 | 描述 |
|---|
| xTaskNotify() | 发送任务通知 |
| xTaskNotifyAndQuery() | 发送任务通知 |
| xTaskNotifyGive() | 发送任务通知 |
| xTaskNotifyFromISR() | 在中断中发送任务通知 |
| xTaskNotifyAndQueryFromISR() | 在中断中发送任务通知 |
| vTaskNotifyGiveFromISR() | 在中断中发送任务通知 |
| ulTaskNotifyTake() | 接收任务通知 |
| xTaskNotifyWait() | 接收任务通知 |
- 所列出的 API 函数都是对任务通知相关数组中下标为 0 的元素进行操作
#define xTaskNotify( xTaskToNotify, \
ulValue, \
eAction) \
xTaskGenericNotify( (xTaskToNotify), \
(tskDEFAULT_INDEX_TO_NOTIFY), \
(ulValue), \
(eAction), \
NULL)
用于往指定任务发送任务通知,通知方式可以自由指定,并且不获取发送任务通知前任务通知的通知值。
#define xTaskNotifyAndQuery( xTaskToNotify, \
ulValue, \
eAction, \
pulPreviousNotifyValue) \
xTaskGenericNotify( (xTaskToNotify), \
(tskDEFAULT_INDEX_TO_NOTIFY), \
(ulValue), \
(eAction), \
(pulPreviousNotifyValue))
用于往指定任务发送任务通知,通知方式可以自由指定,并且获取发送任务通知前任务通知的通知值。
#define xTaskNotifyGive( xTaskToNotify) \
xTaskGenericNotify( (xTaskToNotify), \
(tskDEFAULT_INDEX_TO_NOTIFY), \
(0), \
eIncrement, \
NULL)
此函数用于往指定任务发送任务通知,通知方式为将通知值加 1,并且不获取发送任务通知前任务通知的通知值。
BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, //接收任务通知的任务
UBaseType_t uxIndexToNotify, //任务的指定通知(任务通知相关数组下标)
uint32_t ulValue, //通知值
eNotifyAction eAction, //通知方式
uint32_t * pulPreviousNotificationValue); //用于获取发送通知前的通知值
#define xTaskNotifyFromISR( xTaskToNotify, \
ulValue, \
eAction, \
pxHigherPriorityTaskWoken) \
xTaskGenericNotifyFromISR( (xTaskToNotify), \
(tskDEFAULT_INDEX_TO_NOTIFY), \
(ulValue), \
(eAction), \
NULL, \
(pxHigherPriorityTaskWoken))
用于在中断中往指定任务发送任务通知,通知方式可以自由指定,并且不获取发送任务通知前任务通知的通知值,但获取发送通知后是否需要进行任务切换的标志。
#define xTaskNotifyAndQueryFromISR( xTaskToNotify, \
ulValue, \
eAction, \
pulPreviousNotificationValue, \
pxHigherPriorityTaskWoken) \
xTaskGenericNotifyFromISR( (xTaskToNotify), \
(tskDEFAULT_INDEX_TO_NOTIFY), \
(ulValue), \
(eAction), \
(pulPreviousNotificationValue), \
(pxHigherPriorityTaskWoken))
数用于在中断中往指定任务发送任务通知,通知方式可以自由指定,并且获取发送任务通知前任务通知的通知值,和发送通知后是否需要进行任务切换的标志。
#define vTaskNotifyGiveFromISR( xTaskToNotify, \
pxHigherPriorityTaskWoken ) \
vTaskGenericNotifyGiveFromISR( (xTaskToNotify), \
(tskDEFAULT_INDEX_TO_NOTIFY), \
( pxHigherPriorityTaskWoken));
用于在中断中往指定任务发送任务通知,通知方式为将通知值加 1,并且不获取发送任务通知前任务通知的通知值,但获取发送通知后是否需要进行任务切换的标志。
BaseType_t xTaskGenericNotifyFromISR(
TaskHandle_t xTaskToNotify, //接收任务通知的任务
UBaseType_t uxIndexToNotify, //任务的指定通知(任务通知相关数组下标)
uint32_t ulValue, //通知值
eNotifyAction eAction, //通知方式
uint32_t * pulPreviousNotificationValue, //用于获取发送通知前的通知值
BaseType_t * pxHigherPriorityTaskWoken); //用于标记函数退出后是否需要进行任务切换
void vTaskGenericNotifyGiveFromISR(
TaskHandle_t xTaskToNotify, //接收任务通知的任务
UBaseType_t uxIndexToNotify, //任务的指定通知(任务通知相关数组下标)
BaseType_t * pxHigherPriorityTaskWoken); //用于标记函数退出后是否需要进行任务切换
#define ulTaskNotifyTake( xClearCountOnExit, \
xTicksToWait) \
ulTaskGenericNotifyTake( (tskDEFAULT_INDEX_TO_NOTIFY), \
(xClearCountOnExit), \
(xTicksToWait))
用于获取任务通知的通知值,并且在成功获取任务通知的通知值后,可以指定将通知值清零或减 1。
xClearCountOnExit=pdTRUE 在接收到任务通知后,将任务通知的通知值清零
xClearCountOnExit=pdFALSE 在接收任务通知后,将任务通知的通知值减 1
uint32_t ulTaskGenericNotifyTake(
UBaseType_t uxIndexToWaitOn, //任务的指定通知(任务通知相关数组下标)
BaseType_t xClearCountOnExit, //指定在成功接收通知后,将通知值清零或减 1
TickType_t xTicksToWait); //阻塞等待任务通知值的最大时间
#define xTaskNotifyWait( ulBitsToClearOnEntry, \
ulBitsToClearOnExit, \
pulNotificationValue, \
xTicksToWait) \
xTaskGenericNotifyWait( tskDEFAULT_INDEX_TO_NOTIFY, \
(ulBitsToClearOnEntry), \
(ulBitsToClearOnExit), \
(pulNotificationValue), \
(xTicksToWait))
用于等待任务通知通知值中的指定比特位被置一,此函数可以在等待前和成功等待到任务通知通知值中的指定比特位被置一后清零指定比特位,并且还能获取等待超时后任务通知的通知值。
BaseType_t xTaskGenericNotifyWait(
UBaseType_t uxIndexToWaitOn, //任务的指定通知(任务通知相关数组下标)
uint32_t ulBitsToClearOnEntry, //等待前指定清零的任务通知通知值比特位
uint32_t ulBitsToClearOnExit, //成功等待后指定清零的任务通知通知值比特位
uint32_t * pulNotificationValue,//等待超时后任务通知的通知值
TickType_t xTicksToWait);//阻塞等待任务通知值的最大时间
| 函数 | 描述 |
|---|
| xTaskNotifyIndexed() | 发送任务通知 |
| xTaskNotifyAndQueryIndexed() | 发送任务通知 |
| xTaskNotifyGiveIndexed() | 发送任务通知 |
| xTaskNotifyIndexedFromISR() | 在中断中发送任务通知 |
| xTaskNotifyAndQueryIndexedFromISR() | 在中断中发送任务通知 |
| vTaskNotifyGiveIndexedFromISR() | 在中断中发送任务通知 |
| ulTaskNotifyTakeIndexed() | 接收任务通知 |
| xTaskNotifyWaitIndexed() | 接收任务通知 |
- 所列出的 API 函数可以指定对任务通知相关数组中的元素进行操作
12、内存管理
| 函数 | 描述 |
|---|
| pvPortMalloc() | 申请内存,申请单位为字节 |
| vPortFree() | 释放内存 |