标签:
Ucos的事件分为时钟,信号量,互斥性信号量,消息队列,以及消息邮箱
首先说信号量
信号量在ucos中的类型定义为OS_EVENT_TYPE_SEM,在任务控制块ecb中,主要是用到的是信号量计数器OSEventCnt,当有任务申请信号量的时候,如果信号量OSEventCnt的值大于0,则将OSEventCnt-1是任务继续运行,如果OSEventCnt已经为0,那么任务将会被挂到任务等代表中,当别的任务发送信号量的时候,被挂起的任务得到信号量,并设置为ready准备进行下一次调度,如果这时候任务等待表中没有了等待任务,那么信号量计数器OSEventCnt只是简单地+1
信号量是不使用事件控制块的OSEventPtr成员
使用信号量之前必须先创建信号量,并在程序内部通过变量保存下来
OSSemCreate,参数为信号量的初始值,返回得到的信号量ecb指针
请求信号量
OSSemPend,参数为信号量指针,超时事件以及错误代码指针,当超时时间为0说明等待时间无限长
当一个任务请求信号量时,如果希望能够允许一个任务在信号量不够的情况下继续执行不进入等待状态,可以使用函数OSSemAccept
发送信号量使用OSSemPost,参数为事件结构体指针
删除信号量OSSemDel,参数为信号量ECB指针,删除条件以及错误信息指针,其中删除的条件为选择不论任务等待表是否为空都删除和等待为空删除
查询信号量状态OSSemQuery,返回错误信息,里面地各个参数为OS_SEM_DATA的函数,用于存放当前查询的信号量的数量
互斥型信号量与信号量的区别是互斥信号量只有0和1两种选择,而信号量可以很多选择(类似于只能两个人使用的东西和很多人可以使用的东西)
使用互斥型信号量会造成优先级反转的问题,也就是低优先级的任务占有了信号量,造成高优先级的任务等待信号量,反而不能抢断低优先级任务的情况
Ucos为了解决这种问题,策略是在任务在获得信号量的时候将任务的优先级提升到所有任务最高优先级上,从而尽快的用完共享资源并释放信号,释放信号之后恢复任务原来的优先级别
互斥型信号量在事件类型上为OS_EVENT_TYPE_MUTEX,他将OSEventCnt分为了高八位和低八位,低八位存放信号值,高八位存放为了避免优先级反转而要将任务提升道德高优先级prio
创建互斥型信号量OSMutexCreate,参数一个是优先级别一个是错误信息,其中,优先级别标识要提升的高优先级信号量,低八位一般是0xff
请求互斥型信号量, OSMutexPend,参数为互斥型信号量的指针,等待时间,以及错误信息指针,
if ((INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE) {
pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8; pevent->OSEventCnt |= OSTCBCur->OSTCBPrio; pevent->OSEventPtr = (void *)OSTCBCur;
if (OSTCBCur->OSTCBPrio <= pip) { OS_EXIT_CRITICAL();
*perr = OS_ERR_PIP_LOWER;
} else {
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
}
return;
}
首先检测当前事件的低八位,为0xff进入if选择,将低八位设置为系统当前任务(也就是时间请求任务)的优先级,事件指针指针指向当前任务tcb,然后检测任务的优先级和pip的比对.设置错误,比pip大,申请成功,pip的来源是当前事件ECB计数器的高八位.在创建互斥信号量的时候有这样的操作
pevent->OSEventCnt = (INT16U)((INT16U)prio << 8u) | OS_MUTEX_AVAILABLE;
也就是创建的互斥信号量的提升优先级,当前任务优先级比提升优先级高(数值低一点),就可以直接获取信号量.
如果低于,后面会进行一次正在运行的任务的优先级的提升,让当前占有信号量的的任务的权限提升,还涉及到ready表的切换等
发送互斥型信号量
OSMutexPost,参数为信号量指针
获取互斥型信号量的状态
OSMutexQuery,参数中有一个是用来保存互斥型信号量状态的结构OS_MUTEX_DATA
删除互斥型信号量
OSMutexDel
关于互斥型信号量任务处理过程中的权限提升问题后面在单独写文章讨论
消息邮箱,用于适应不同数据的传送需求,其实质就是讲数据缓冲区关联到时间控制块ECB的OSEventPrt,同时时间控制块的OSEventType为常数OS_EVENT_TYPE_MBOX,具体操作如下
OSMboxCreate,创建消息邮箱
OSMboxPend请求消息邮箱,返回消息邮箱指针,注意查看peerr指针是否成功返回
OSMboxPost发送消息邮箱
OSMboxPostOpt 以广播的形式事件等待任务表中全部任务发送消息
OSMboxQuery 查询邮箱状态
OSMboxDel 删除邮箱
最后还有一个消息队列
标签:
原文地址:http://www.cnblogs.com/dengxiaojun/p/4322478.html