微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > μC/OS-II的任务之间的通讯与同步

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

时间:10-08 来源:互联网 点击:

图F6.6描述了任务、中断服务子程序和邮箱之间的关

系,这里用符号“I”表示邮箱。邮箱包含的内容是一个指向一条消息的指针。一个邮箱只能包

含一个这样的指针(邮箱为满时),或者一个指向NULL的指针(邮箱为空时)。从图F6.6可以看出,任务或者中断服务子程序可以调用函数OSMboxPost(),但是只有任务可以调用函数OSMboxPend()和OSMboxQuery()。

图F6.6任务、中断服务子程序和邮箱之间的关系

6.7.1 建立一个邮箱,OSMboxCreate()

程序清单L6.14是OSMboxCreate()函数的源代码,基本上和函数OSSemCreate()相似。不同之处在于事件控制块的类型被设置成OS_EVENT_TYPE_MBOX[L6.14(1)], 以及使用.OSEventPtr域来容纳消息指针,而不是使用.OSEventCnt域[L6.14(2)]。

OSMboxCreate()函数的返回值是一个指向事件控制块的指针[L6.14(3)]。这个指针在调用函数OSMboxPend(),OSMboxPost(),OSMboxAccept()和OSMboxQuery()时使用。因此,该指针可以看作是对应邮箱的句柄。值得注意的是,如果系统中已经没有事件控制块可用,函数OSMboxCreate()将返回一个NULL指针。

邮箱一旦建立,是不能被删除的。比如,如果有任务正在等待一个邮箱的信息,这时删除该邮箱,将有可能产生灾难性的后果。

程序清单L6.14建立一个邮箱

OS_EVENT*OSMboxCreate(void*msg)

{

OS_EVENT*pevent;

OS_ENTER_CRITICAL();

pevent=OSEventFreeList;

if(OSEventFreeList!=(OS_EVENT*)0){

OSEventFreeList=(OS_EVENT*)OSEventFreeList->OSEventPtr;

}

OS_EXIT_CRITICAL();

if(pevent!=(OS_EVENT*)0){

pevent->OSEventType=OS_EVENT_TYPE_MBOX;(1)

pevent->OSEventPtr=msg;(2)

OSEventWaitListInit(pevent);

}

return(pevent);(3)

}

6.7.2 等待一个邮箱中的消息,OSMboxPend()

程序清单L6.15是OSMboxPend()函数的源代码。 同样, 它和OSSemPend()也很相似,因此,在这里只讲述其中的不同之处。OSMboxPend()首先检查该事件控制块是由 OSMboxCreate()函数建立的[L6.15(1)]。当.OSEventPtr域是一个非NULL的指针时,说明该邮箱中有可用的消息[L6.15(2)]。这种情况下,OSMboxPend()函数将该域的值复制到局部变量msg中,然后将.OSEventPtr置为NULL[L6.15(3)]。这正是我们所期望的,也是执行 OSMboxPend()函数最快的路径。

如果此时邮箱中没有消息是可用的(.OSEventPtr域是NULL指针),OSMboxPend()函数检查它的调用者是否是中断服务子程序[L6.15(4)]。象OSSemPend()函数一样,不能在中断服务子程序中调用OSMboxPend(),因为中断服务子程序是不能等待的。这里的代码同样是为了以防万一。但是,如果邮箱中有可用的消息,即使从中断服务子程序中调用OSMboxPend()函数,也一样是成功的。

如果邮箱中没有可用的消息,OSMboxPend()的调用任务就被挂起,直到邮箱中有了消息或者等待超时[L6.15(5)]。当有其它的任务向该邮箱发送了消息后(或者等待时间超时),这时,该任务再一次成为最高优先级任务,OSSched()返回。这时,OSMboxPend()函数要检查是否有消息被放到该任务的任务控制块中[L6.15(6)]。如果有,那么该次函数调用成功,对应的消息被返回到调用函数。

程序清单L6.15等待一个邮箱中的消息

void*OSMboxPend(OS_EVENT*pevent,INT16Utimeout,INT8U*err)

{

void*msg;

OS_ENTER_CRITICAL();

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

OS_EXIT_CRITICAL();

*err=OS_ERR_EVENT_TYPE;

return((void*)0);

}

msg=pevent->OSEventPtr;

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

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

OS_EXIT_CRITICAL();

*err=OS_NO_ERR;

}elseif(OSIntNesting>0){(4)

OS_EXIT_CRITICAL();

*err=OS_ERR_PEND_ISR;

}else{

OSTCBCur->OSTCBStat|=OS_STAT_MBOX;(5)

OSTCBCur->OSTCBDly=timeout;

OSEventTaskWait(pevent);

OS_EXIT_CRITICAL();

OSSched();

OS_ENTER_CRITICAL();

if((msg=OSTCBCur->OSTCBMsg)!=(void*)0){(6)

OSTCBCur->OSTCBMsg=(void*)0;

OSTCBCur->OSTCBStat=OS_STAT_RDY;

OSTCBCur->OSTCBEventPtr=(OS_EVENT*)0;

OS_EXIT_CRITICAL();

*err=OS_NO_ERR;

}elseif(OSTCBCur->OSTCBStatOS_STAT_MBOX){(7)

OSEventTO(pevent);(8)

OS_EXIT_CRITICAL();

msg=(void*)0;(9)

*err=OS_TIMEOUT;

}else{

msg=pevent->OSEventPtr;(10)

pevent->OSEventPtr=(void*)0;

(11)

OSTCBCur->OSTCBEventPtr=(OS_EVENT*)0;(12)

OS_EXIT_CRITICAL();

*err=OS_NO_ERR;

}

}

return(msg);

}

在OSMboxPend()函数中,通过检查任务控制块中的

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top