UCOS下邮箱使用 2010.6.6

关于UCOS下邮箱使用的两个经验

在使用UCOS的邮箱时,遇到一些问题,现将一些小总结写下,希望对大家有所帮助。
     邮箱使用总结
1.数据的存放。
邮箱一般用来传递数据,不管何种类型都可以传递。在传递时,先把数据数据用void *进行类型变化,化为void *这种万用类型,而在接收邮箱的数据时,再还原成本身的数据类型。比如以下的两个例子:
一是传递指向一个数组的指针。发端采用如下方式:
OSMboxPost(ComSendMbox, (void *)ComBufRec);         
其中的ComBufRec就是数组名,也表示指向该数组的指针,将原来的字符型数组名(或指针)变成(void *)类型,而接收端,利用
send_ptr = (uint8 *)OSMboxPend(ComSendMbox, 0, &err);      
将(void *)类型还原为指针。

二是传递一个字符型变量。发端采用如下方式:
OSMboxPost(KeyMbox, (void *)key_value);              
其中的key_value就是字符型变量,将原来的字符型变量变成(void *)类型,而接收端,利用
key = (INT8U)OSMboxPend(KeyMbox, 0, &err);      
将(void *)类型还原为字符型变量。

2、关于在邮箱中不能存放传递0值的问题
在邮箱的传递中,如果把一个0值放入邮箱,经过void *类型变化后,变成了void *0,而判断邮箱中是否有数据正是通过判断邮箱中指向Message的指针是否为0来判断,这样虽然放入了一个0变量,但邮箱中却无法判断这个0值,认为邮箱中还是空。


 

 

ucos觉得使用它还是需要很多技巧性的,也就是说ucos需要技巧性的操作,今天我就我对邮箱这一块的看法说说。下面我用一个例子说一下

首先例子的功能就是创建一个邮箱myMbox利用它所存取的msg不同而进行相应的任务调度。程序片段如下

OS_EVENT *myMbox

Static INT8U TaskAMsg,TaskBMsg;

myMbox = OSMboxCreate((void *TaskAMsg

 

 

 

void TaskA(void *i)

{

for (;;)

{

if(OSMboxPend(myMbox,0,&myErr)== (void *)& TaskAMsg)

{

Uart_Printf("TaskA/n");

OSTimeDly(100); (1)

 

 

OSMboxPost(myMbox,(void *)& TaskBMsg);

 

 

OSTimeDly(100); (2)

 

 

}

}

}

 

 

 

void TaskB(void *i)

{

for (;;)

{

if(OSMboxPend(myMbox,0,&myErr) == (void *)& TaskBMsg)

{

Uart_Printf("TaskB/n");

OSTimeDly(100); (1)

OSMboxPost(myMbox,(void *)& TaskAMsg);

 

 

OSTimeDly(100); (2)

}

}


 

OSTaskCreate(TaskA, (void *)0, (void *)&Task_Stk5[STK_size_S - 1], 6);

OSTaskCreate(TaskB, (void *)0, (void *)&Task_Stk6[STK_size_S - 1], 7);

大概的程序片度如上,这里我特地把OSTimeDly分成两种情况放置,但程序运行的结果是一样的,个人认为放置在位置(2)上容易理解,下面我们要讨论的是放在位置一上是个怎么回事。

从程序中我们可以大概看出,首先创建了一个邮箱myMbox 初始化它的消息内容为TaskAMsg(想想这里可以初始化为TaskBMsg吗?)好了从任务A开始看起。首先程序运行当然是先执行TaskA了,因为它的优先级是最高的是吧。那么由于邮箱有初始化也就是msg = void*0;的情况,这个时候OSMboxPend就直接返回了Msg,它是一个地址。在if语句中判断是不是TaskA要等的消息,如果是就执行if语句的内容,从初始化我们知道这里肯定会执行if语句的内容了。那么好了打印完了之后就是OSTimeDly100)了,也就是说TaskA到了这里就开始被挂起100tick了。这时候是怎么挂起的呢,对就是直接从Rdy表中把它给删除掉,等到100tick过去后在重新添加近Rdy表。我们要注意的是,在这里TaskA没有被放在事件等待的Rdy里头。那么程序在这100tick期间去做什么去了呢!当然程序挂起了TaskA也就只能跑到TaskB去了。到了TaskB由于邮箱这个时候还没有消息(看清楚OSMboxPost放在OSTimeDly后面),也就是TaskB执行了OSMboxPend,但由于邮箱里头的msg是空的,那么它就将TaskB给挂起了,挂起了放在哪里了呢?注意了,这个时候TaskB就被添加在事件等待列表里头了。然后程序去做什么去了?这个时候如果TaskATaskB如果都还没有Rdy的话,那么程序就去执行IDLE任务拉。等到TaskAtick到了之后就执行OSMboxPost(myMbox,(void *)& TaskBMsg);也就是给myMbox投递一封邮件了,邮件的内容是TaskBMsg因为我们的收信人是TaskB。这个时候OSMboxPost首先会检查事件等待列表中是否有任务在等待,如果有的话就把里头优先级最高的任务给拿出来放到Rdy表里头去并且将我们刚才邮寄的信转发给它并放到它自己的信箱里头,这里我们是把给TaskB的信放在TaskBOSTCBMsg里头,然后看看这个任务是否已经就绪了,如果是就把它添加到Rdy里头去。那么这这里TaskB是不是已经就绪了呢?

 

是的,到这里,TaskB就被添加到Rdy表去了。跟着TaskA就回到if语句上,第一次判断邮箱是非空的,但里面的消息并不是TaskA所要的,这时候OSMboxPend还把邮箱清空了。第二次执行OSMboxPend的时候由于邮箱在第一次的时候被清空了,这个时候TaskA就被挂起拉,并且添加到事件等待列表中去。然后进行任务切换了,任务切换到TaskB去。执行OSMboxPend未执行完的语句。那么之前是执行到OSSched那里,现在往下去执行msg = OSTCBCur->OSTCBMsg;这条语句。我们知道刚才在TaskAOSMboxPost的时候它把信放在TaskBOSTCBMsg里头,那么这个时候OSMboxPend就不等待了,就执行if语句了哦。跟着的过程就和上面的一样了。到这里把OSTimeDly放在位置(1)的情况个人分析就结束了,那么放在位置(2)呢,这也太容易理解了吧。

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭