日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ucos通信邮箱的理解

發(fā)布時間:2023/12/15 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ucos通信邮箱的理解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

? 學習過信號量之后再來看郵箱,發(fā)現(xiàn)他們是非常相似的,甚至有時候郵箱可以當做信號量來使用,郵箱相對信號量而言,只是多傳遞一個指針變量

和信號量相似,ucos提供了5個對郵箱操作的函數(shù)它們是:

1.建立一個郵箱,OSMboxCreate()

2.等待一個郵箱的消息? OSMboxPend()

3.發(fā)送一個消息到郵箱,OSMboxPost()

4.無等待從郵箱中得到一個消息,OSMboxAccept();

5.查詢一個郵箱的狀態(tài) OSMboxQuery();

使用郵箱之前,必須先建立該郵箱,該操作可以通過調(diào)用OSMboxCreate函數(shù)來完成,并且要指定指針的初始化值,一般情況下,這個初始值是NULL,

但也可以初始化一個郵箱,使其在最開始就包含一條消息,如果使用郵箱的目的是用來通知任務某一個事件已經(jīng)發(fā)生(發(fā)送一條消息),那么就要初始化該郵箱為null,

如果用戶用郵箱來共享資源,那么就要初始化該郵箱為一個非null指針,在這種情況下,該郵箱被當成一個二值信號量使用

? 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)

?

? }

仔細看看,其實和創(chuàng)建一個信號量的過程幾乎是一樣的,先申請一個空事件控制塊,接著初始化這個事件控制塊,最后返回一個紙箱這個事件控制塊的,不同之處在于事件

控制塊的類型被設置成OS_EVENT_TYPE_MBOX 以及使用OSEventPtr來容納消息指針。

?

接著來看等待郵箱函數(shù)實現(xiàn)代碼:

void *OSMboxPend(OS_EVENT *pevent,INT16U timeout,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;

???? }else if(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;

?????????? }

????????? else if(OSTCBCur->OSTCBStat&OS_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);

}

同樣,它和OSSemPend()也相似,說白了就是先看有沒有有用的消息,要使沒有,就該把任務掛起來。

OSMboxPend首先檢查該事件控制塊是由OSMboxCreate()函數(shù)建立(1)。當OSEventPtr域是一個非

NULL的指針時,說明該郵箱有可用的消息(2);這種情況下,OSMboxPend()函數(shù)將該域的值復制到句柄變量

msg中,然后將OSEventPtr置為null,這正是我們期望的,也是執(zhí)行OSMboxPend函數(shù)最快的路徑。

如果此時郵箱中沒有消息是可用的額(OSEventPtr域是null指針),OSMboxPend函數(shù)檢查它的調(diào)用者是否是中斷服務子程序。

像OSSemPend函數(shù)一樣,不能在中斷服務子程序中調(diào)用OSMboxPend(),因為中斷服務子程序是不能等待的,但是如果郵箱有可用的消息,

即使從中斷服務子程序中調(diào)用OSMboxPend()函數(shù),也一樣是成功的。如果沒有可用的消息,OSMboxPend的調(diào)用任務就被掛起,直到郵箱中有了

消息或者等待超時時(5).當有其它任務向該郵箱發(fā)送了消息(或等待時間超時時),這時,該任務再一次成為最高任務優(yōu)先級任務,OSSched()返回,這時,

OSMboxPend()函數(shù)要檢查是否有消息被放到該任務的任務控制塊中(6),如果有,那么該函數(shù)調(diào)用成功,對應的消息被返回到調(diào)用的函數(shù)

?

發(fā)送一個消息到郵箱中OSMboxPost()的代碼如下:

INT8U OSMboxPost(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);

}

}

}

?

?

發(fā)送一個消息到郵箱和發(fā)送一個信號量也相似,就絲毫查看有沒有任務在等待這個消息,如果有就把哪個任務從睡眠態(tài)拉回就就緒態(tài)。

代碼的詳細解釋如下:

檢查了事件控制塊是否是一個郵箱后(1),OSMboxPost()函數(shù)還要檢查是否有任務等待該郵箱匯總的消息(2)。如果事件控制塊中的OSEventGrp域包含非零值,

就暗示有任務在等待該消息,這時,調(diào)用OSEventTaskRdy()將其中的最高級優(yōu)先級任務從等待列表中刪除,加入系統(tǒng)的就緒任務列表中,準備運行,然后,調(diào)用OSSched()(4)函數(shù),檢查該任務十分是系統(tǒng)中最高優(yōu)先級的就緒任務,如果是,這些任務切換【僅當OSMboxPost()】函數(shù)是由任務調(diào)用時,該任務得以執(zhí)行,如果該任務不是最高優(yōu)先級的任務,OSSched()返回,OSMboxPost()的調(diào)用函數(shù)繼續(xù)執(zhí)行,如果沒有任務任務等待該消息,指向消息的指針就被保存到郵箱中(6)(假設此時郵箱匯總的指針不是非NULL的【5】),這樣,下一個調(diào)用OSMboxPend函數(shù)的任務就可以立刻得到該消息了。

#define? TASK_STK_SIZE?? 512

char *s ;//MyTask發(fā)送的消息指針,

char *ss;//YouTask接收到的消息的指針

INT8U err;

INT8U y=0;

INT32U Times=0;

OS_EVENT *Str_Box;? //定義事件控制塊指針,定義消息郵箱的指針

OS_STK??? StartTask[TASK_STK_SIZE];

OS_STK???? MyTaskStk[TASK_STK_SIZE];

OS_STK???? YouTaskStk[TASK_STK_SIZE];

void StartTask(void *data);

void MyTask(void *data);

void YouTask(void *data);

void main(void)

{

??? OSInit();

??? Str_Box=OSMboxCreate((void*)0);//創(chuàng)建消息郵箱,返回值指向創(chuàng)建消息郵箱指針,初始值為null 表示創(chuàng)建的消息郵箱沒有內(nèi)容。

???? OSTaskCreate(StartTask,(void*)0,&StartTaskStk[TASK_STK_SIZE-1],0);?

?? ?OSStart();

}

?

void StartTask(void *pdata)

{

#if OS_CRITICAL_METHOD==3

??? OS_CPU_SR?? cpu_sr;

#endif

?? INT16S? key;

?? pdata=pdata;

?? OSStatInit();

?????? OSTaskCreate(MyTask,(void*)0,&StartTaskStk[TASK_STK_SIZE-1],1);?

?????????? OSTaskCreate(YouTask,(void*)0,&StartTaskStk[TASK_STK_SIZE-1],2);?

?? for(;;)

?? {

???????? if(PC_GetKey(&key)==TRUE)

???????? {

????????????? if(key==0x1B)

????????????? {

???????????????????? PC_DOSReturn();

??????????????? }

???????? }

?????????????? OSTimeDlyHMSM(0,0,3,0);

?? }

}

?

void MyTask(void *pdata)

{

#if OS_CRITICAL_METHOD==3

???? OS_CPU_SR? cpu_sr;

#endif

??? pdata=pdata;

? for(;;)

? {

?????? sprintf(s,"%d",times);//把Times賦值給s

??????? OSMboxPost(Str_Box,s);//發(fā)送消息s 其中兩個參數(shù)Str_Box是OS_EVENT *pevent表示消息郵箱指針,s是void*msg表示消息指針

???????????????????????????????????????????????? 該函數(shù)表示把消息s發(fā)送到消息郵箱Str_Box中

?????????????Times++;//MyTask的運行次數(shù)加1

??????????? OSTimeDlyHMSM(0,0,1,0);

? }

}

?

void YouTask(void *pdata)

{

? #if OS_CRITICAL_METHOD==3

??? OS_CPU_SR cpu_sr;

? #endif

?? pdata=pdata;

?? for(;;)

??? {

???????? ss=OSMboxPend(Str_Box,10,&err);//請求消息郵箱參數(shù)表示:Str_Box是消息郵箱指針,10表示等待時間 ss是郵箱中的消息指針

????????? OSTimeDlyHMSM(0,0,1,0);?? //等待1s

??? }

?

}

//OSMboxPend時指定等待時間為10,所以當?shù)却龝r間到了,即使郵箱中還是無消息,YouTask也會進入就緒態(tài)的,然后繼續(xù)往下運行,但是

?當OSMboxPend的等待時間設置為0,表示無限等待。

?

?

?

?

總結

以上是生活随笔為你收集整理的ucos通信邮箱的理解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。