- 在UCOSII中,是使用信号量、邮箱(消息邮箱)和消息队列这些被称作事件的中间环节来实现任务之间的通信的。
1.事件
PS:
任务1是发信方,任务2是收信方;
任务1:负责把信息发送到事件上,这项操作叫 发送事件;
任务2:通过读取事件操作对事件进行查询,如果有信息则读取,否则等待。 读事件操作叫 请求事件。
UCOSII 使用事件控制块(ECB)的数据结构来描述 信号量、邮箱和消息队列 这些事件。
typedef struct
{
INT8U OSEventType; //事件的类型
INT16U OSEventCnt; //信号量计数器
void *OSEventPtr; //消息或消息队列的指针
INT8U OSEventGrp; //等待事件的任务组
INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; //任务等待表
#if OS_EVENT_NAME_EN>0u
INT8U *OSEventName; //事件名
#endif
}OS_EVENT;
2.信号量
- 信号量是一类事件。使用信号量的目的,是为了给共享资源设立一个标志,该标志表示该共享资源的占用情况。当一个任务在访问共享资源之前,就可以先对这个标志进行查询,从而在了解资源被占用的情况之后,再来决定自己的行为。
信号量可以分为2种:
- 二值型信号量:(互斥型信号量),任何时候只能一个人占用。
- N值信号量:(计数型信号量),可以同时有多个人使用。
(1)创建信号量函数
OS_EVENT*OSSemCreate(INT16U cnt);
//该函数的返回值为已创建的信号量的指针,而参数cnt 是信号量计数器(OSEventCnt)的初始值。
(2)请求信号量函数
void OSSemPend(OS_EVENT *pevent,INT16U timeout,INT8U *err);
//参数pevent 是被请求信号量的指针;timeout为等待时限;err为错误信息
为防止任务因得不到信号量而处于长期的等待状态,函数OSSemPend允许用参数timeout设置一个等待时间的限制,当任务等待时间超过timeout时可以结束等待状态而进入就绪状态。如果参数timeout被设置为0,则表明任务的等待时间无限长。
(3)发送信号量函数
任务获得信号量,并在访问共享资源结束以后,必须要释放信号量,释放信号量也叫做发送信号量。通过OSSemPost函数实现。
OSSemPost函数在对信号量的计数器操作之前,首先要检查是否还有等待该信号量的任务。如果没有,就把信号量计数器OSEventCnt +1;如果有,则调用调度器OS_Sched()去运行等待任务中优先级别最高的任务。
INT8U OSSemPost(OS_EVENT *pevent);
// pevent 信号量指针,该函数在调用成功后,返回值为OS_ON_ERR,否则会根据具体错误返回OS_ERR_EVENT_TYPE、OS_SEM_OVF.
(4)删除信号量函数
OS_EVENT *OSSemDel(OS_EVENT *pevent,INT8U opt,INT8U *err);
// pevent 删除信号量指针,opt 删除条件选项,err 错误信息。
3.邮箱
- 消息缓冲区:在多任务系统中,需要在任务与任务之间通过传递一个数据(这种数据叫“消息”)的方式来进行通信。存储该数据的缓冲区 称作消息缓冲区。
- 邮箱:用来传递消息缓冲区指针的数据结构 叫邮箱。
- 消息邮箱:在UCOSII中,通过事件控制块的OSEventPrt 来传递消息缓冲区指针,同时使事件控制块的成员OSEventType 为常数 OS_EVENT_TYPE_MBOX,则该事件控制块 就叫消息邮箱。
相关函数:
//1.创建邮箱函数
OS_EVENT *OSMboxCreate(void msg);
//msg,消息的指针;函数返回值为消息邮箱的指针;
//2.向邮箱发送消息函数
INT8U OSMboxPost(OS EVENT *pevent,void *msg);
// pevent,消息邮箱的指针;msg ,消息指针;
//3.请求邮箱函数
//作用: 查看邮箱指针OSEventPrt是否为NULL,如果不是NULL就把邮箱中的消息指针返回给调用函数的任务,同时用OS_NO_ERR 通过函数
//的参数err通知任务获取消息成功。如果邮箱指针为NULL,则使任务进入等待状态,并引发1次任务调度。
void *OSMboxPend(OS_EVENT *pevent,INT16U timeout,INT8U *err);
//pevent,请求邮箱指针;timeout,等待时限;err,错误信息;
//4.查询邮箱状态函数
INT8U *OSMboxQuery(OS_EVENT *pevent,OS_MBOX_DATA *pdata);
//pevent,消息邮箱指针;pdata,存放邮箱信息的结构;
//5.删除邮箱函数
OS_EVENT *OSMboxDel(OS_EVENT *pevent,INT8U opt,INT8U *err);
//pevent,消息邮箱指针;opt,删除选项;err,错误信息;