新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > μC/OS-II的任务之间的通讯与同步

μC/OS-II的任务之间的通讯与同步

作者: 时间:2016-10-08 来源:网络 收藏

程序清单L6.16向邮箱中发送一条消息

INT8UOSMboxPost(OS_EVENT*pevent,void*msg)

{

OS_ENTER_CRITICAL();

if(pevent->OSEventType!=OS_EVENT_TYPE_MBOX){(1)

OS_EXIT_CRITICAL();

return(OS_ERR_EVENT_TYPE);

}

if(pevent->OSEventGrp){(2)

OSEventTaskRdy(pevent,msg,OS_STAT_MBOX);(3)

OS_EXIT_CRITICAL();

OSSched();(4)

return(OS_NO_ERR);

}else{

if(pevent->OSEventPtr!=(void*)0){(5)

OS_EXIT_CRITICAL();

return(OS_MBOX_FULL);

}else{

pevent->OSEventPtr=msg;(6)

OS_EXIT_CRITICAL();

return(OS_NO_ERR);

}

}

}

6.7.4 无等待地从邮箱中得到一个消息,OSMboxAccept()

应用程序也可以以无等待的方式从邮箱中得到消息。这可以通过程序清单L6.17中的OSMboxAccept()函数来实现。OSMboxAccept()函数开始也是检查事件控制块是否是由OSMboxCreate()函数建立的 [L6.17(1)]。接着,它得到邮箱中的当前内容[L6.17(2)],并判断是否有消息是可用的[L6.17(3)]。如果邮箱中有消息,就把邮箱清空[L6.17(4)],而邮箱中原来指向消息的指针被返回给OSMboxAccept()的调用函数[L6.17(5)]。OSMboxAccept()函数的调用函数必须检查该返回值是否为NULL。如果该值是NULL,说明邮箱是空的,没有可用的消息。

如果该值是非NULL值,说明邮箱中有消息可用,而且该调用函数已经得到了该消息。中断服务子程序在试图得到一个消息时, 应该使用OSMboxAccept()函数, 而不能使用OSMboxPend()函数。

OSMboxAccept()函数的另一个用途是,用户可以用它来清空一个邮箱中现有的内容。

程序清单L6.17无等待地从邮箱中得到消息

void*OSMboxAccept(OS_EVENT*pevent)

{

void*msg;

OS_ENTER_CRITICAL();

if(pevent->OSEventType!=OS_EVENT_TYPE_MBOX){(1)

OS_EXIT_CRITICAL();

return((void*)0);

}

msg=pevent->OSEventPtr;(2)

if(msg!=(void*)0){(3)

pevent->OSEventPtr=(void*)0;(4)

}

OS_EXIT_CRITICAL();

return(msg);(5)

}

6.7.5 查询一个邮箱的状态,OSMboxQuery()

OSMboxQuery()函数使应用程序可以随时查询一个邮箱的当前状态。程序清单L6.18是该函数的源代码。它需要两个参数:一个是指向邮箱的指针pevent。该指针是在建立该邮箱时,由OSMboxCreate()函数返回的;另一个是指向用来保存有关邮箱的信息的OS_MBOX_DATA(见

uCOS_II.H)数据结构的指针pdata。在调用OSMboxCreate()函数之前,必须先定义该结构变量,

用来保存有关邮箱的信息。之所以定义一个新的数据结构,是因为这里关心的只是和特定邮箱

有关的内容,而非整个OS_EVENT数据结构的内容。后者还包含了另外两个域

(.OSEventCnt和.OSEventType),而OS_MBOX_DATA只包含邮箱中的消息指针(.OSMsg)和该邮箱现有的等待任务列表(.OSEventTbl[]和.OSEventGrp)。

和前面的所以函数一样,该函数也是先检查事件控制是否是邮箱[L6.18(1)]。然后,将邮箱中的等待任务列表[L6.18(2)]和邮箱中的消息[L6.18(3)]从OS_EVENT数据结构复制到OS_MBOX_DATA数据结构。

程序清单L6.18查询邮箱的状态

INT8UOSMboxQuery(OS_EVENT*pevent,OS_MBOX_DATA*pdata)

{

INT8Ui;

INT8U*psrc;

INT8U*pdest;

OS_ENTER_CRITICAL();

if(pevent->OSEventType!=OS_EVENT_TYPE_MBOX){(1)

OS_EXIT_CRITICAL();

return(OS_ERR_EVENT_TYPE);

}

pdata->OSEventGrp=pevent->OSEventGrp;(2)

psrc=pevent->OSEventTbl[0];

pdest=pdata->OSEventTbl[0];

for(i=0;i

*pdest++=*psrc++;

}

pdata->OSMsg=pevent->OSEventPtr;(3)

OS_EXIT_CRITICAL();

return(OS_NO_ERR);

}

6.7.6 用邮箱作二值信号量

一个邮箱可以被用作二值的信号量。 首先, 在初始化时, 将邮箱设置为一个非零的指针(如

void*1)。这样,一个任务可以调用OSMboxPend()函数来请求一个信号量,然后通过调用

OSMboxPost()函数来释放一个信号量。程序清单L6.19说明了这个过程是如何工作的。如果用

户只需要二值信号量和邮箱,这样做可以节省代码空间。这时可以将OS_SEM_EN设置为0,只使

用邮箱就可以了。

程序清单L6.19使用邮箱作为二值信号量

OS_EVENT*MboxSem;

voIDTask1(void*pdata)

{

INT8Uerr;

for(;;){

OSMboxPend(MboxSem,0,err);/*获得对资源的访问权*/

.

./*任务获得信号量,对资源进行访问*/

.

OSMboxPost(MboxSem,(void*)1);/*释放对资源的访问权*/

}

}

6.7.7 用邮箱实现延时,而不使用OSTimeDly()

邮箱的等待超时功能可以被用来模仿OSTimeDly()函数的延时,如程序清单L6.20所示。

如果在指定的时间段TIMEOUT内,没有消息到来,Task1()函数将继续执行。这和OSTimeDly(TIMEOUT)功能很相似。但是,如果Task2()在指定的时间结束之前,向该邮箱发送了一个“哑”消息,Task1()就会提前开始继续执行。这和调用OSTimeDlyResume()函数的功能是一样的。注意,这里忽略了对返回的消息的检查,因为此时关心的不是得到了什么样的消息。

程序清单L6.20使用邮箱实现延时

OS_EVENT*MboxTimeDly;

voidTask1(void*pdata)

{

INT8Uerr;

for(;;){

OSMboxPend(MboxTimeDly, TIMEOUT,err);/*延时该任务*/

.

./*延时结束后执行的代码*/

.

}

}

voidTask2(void*pdata)



关键词:

评论


相关推荐

技术专区

关闭