【RTX操作系统教程】第16章 消息邮箱(上)

标签:
cosiiiemwinrtxstm32f407安富莱 |
分类: RTX及其中间件 |
第16章
消息邮箱
前面几个章节主要给大家讲解了任务间的同步和资源共享机制,本章节为大家讲解任务间的通信机制消息邮箱,RTX的消息邮箱其实就是消息队列,注意和uCOS-II中的消息邮箱区分开,uCOS-II的消息邮箱只能实现一个数据的传递。这里的消息邮箱可以实现多个数据的传递。
本章教程配套的例子含Cortex-M3内核的STM32F103和Cortex-M4内核的STM32F407。
16.1 消息邮箱
16.2 消息邮箱API函数
16.3 实验例程说明(任务间通信)
16.4 实验例程说明(中断方式通信)
16.5
16.1 消息邮箱
16.1.1 消息邮箱的概念及其作用
RTX的消息邮箱实际上就是消息队列,通过内核提供的服务,任务或中断服务子程序可以将一个消息(注意,RTX消息邮箱传递的是消息的地址而不是实际的数据)放入到消息队列。同样,一个或者多个任务可以通过内核服务从消息队列中得到消息。通常,先进入消息队列的消息先传给任务,也就是说,任务先得到的是最先进入到消息队列的消息,即先进先出的原则(FIFO)。
也许有不理解的初学者会问采用消息邮箱多麻烦,搞个全局数组不是更简单,其实不然。在裸机编程时,使用全局数组的确比较方便,但是在加上RTOS后就是另一种情况了。使用全局数组相比消息邮箱主要有如下四个问题:
u
u
u
u
16.1.2 RTX 任务间消息邮箱的实现
任务间消息邮箱的实现是指各个任务之间使用消息邮箱实现任务间的通信。下面我们通过如下的框图来说明一下RTX消息邮箱的实现,让大家有一个形象的认识。
运行条件:
u
u
u
运行过程主要有以下两种情况:
u
u
上面就是一个简单的RTX任务间消息邮箱通信过程。
16.1.3 RTX 中断方式消息邮箱的实现
RTX中断方式消息邮箱的实现是指中断函数和RTX任务之间使用消息邮箱。下面我们通过如下的框图来说明一下RTX消息邮箱的实现,让大家有一个形象的认识。
运行条件:
u
u
u
运行过程主要有以下两种情况:
u
u
上面就是一个简单RTX消息邮箱通信过程。实际应用中,中断方式的消息机制切记注意以下四个问题:
u
u
u
u
l
l
16.2消息邮箱API函数
使用如下8个函数可以实现RTX消息邮箱:
u
u
u
u
u
u
u
u
关于这8个函数的讲解及其使用方法可以看教程第3章3.3小节里面说的参考资料rlarm.chm文件
这里我们重点的说一下函数os_mbx_declare,os_mbx_init,os_mbx_send,os_mbx_wait,isr_mbx_check和isr_mbx_send。
16.2.1 函数os_mbx_declare
函数原型:
#define os_mbx_declare( \
U32 name [4 + cnt]
函数描述:
函数os_mbx_declare定义了消息邮箱的大小和消息邮箱名,用于消息邮箱的初始化。其实就是通过宏定义的方式定义了一个数组U32类型的数组name[4 + cnt]。定义成32位数组是因为CM3/CM4是32位机,地址也就是32位的,从而指针变量也就是固定的32位变量。RTX的消息邮箱传递的是变量的地址,而不是变量的内容,所以要将邮箱定义成32位数组。
u
u
一般的应用中,消息邮箱支持20个消息就够了。
使用举例:
#include
os_mbx_declare (mailbox, 10);
16.2.2函数os_mbx_init
函数原型:
void os_mbx_init (
函数描述:
函数os_mbx_init用于消息邮箱的初始化。其实就是将函数os_mbx_declare定义的数组进行初始化用于消息邮箱的FIFO。
u
u
使用举例:
#include
os_mbx_declare (mailbox, 10);
static void AppObjCreate (void)
{
}
16.2.3函数os_mbx_send
函数原型:
OS_RESULT os_mbx_send (
函数描述:
函数os_mbx_send用于向消息邮箱存放数据指针,或者说数据地址。如果消息邮箱已经满了,调用此函数的任务将被挂起,等待消息邮箱可用,直到消息邮箱有空间可用或者超时时间溢出才会返回。
u
u
u
u
返回值OS_R_TMO,表示消息邮箱已经满了,在设置的超时时间范围内也没有等到可用的空间。
使用这个函数要注意以下问题:
1.
2.
使用举例:
#include
os_mbx_declare (mailbox, 10);
static void AppObjCreate (void)
{
}
__task void AppTaskUserIF(void)
{
}
16.2.4函数os_mbx_wait
函数原型:
OS_RESULT os_mbx_wait (
函数描述:
函数os_mbx_wait用于从消息邮箱中获取消息。如果消息邮箱为空,调用此函数的任务将被挂起,直到消息邮箱有消息可用或是设置的超时时间溢出才会返回。
u
u
u
u
返回值OS_R_TMO,表示消息邮箱为空,在设置的超时时间范围内也没有等到消息。
返回值OS_R_MBX,表示在设置的超时时间范围内收到消息。
使用这个函数要注意以下问题:
1.
2.
使用举例:
#include
os_mbx_declare (mailbox, 10);
static void AppObjCreate (void)
{
}
__task void AppTaskMsgPro(void)
{
}
这里对函数os_mbx_wait的第二个参数再做一下解释。
u
u
u
os_mbx_wait(&mailbox, (void *)&pMsg, usMaxBlockTime)。&pMsg就是表示指针变量在内存所在的地址。
u
char *p1;
void *p2;
p1 = (char *)p2
如果细心的同学会发现,邮箱发送函数os_mbx_send和接收函数os_mbx_wait消息指针传递都是用的void指针类型,这样就给消息数据传递带来了极大的方便,方便在哪里了呢?这样的话使用消息邮箱传递任意数据类型变量都变的十分方便,用户只需做一下强制类型转换即可。
16.2.5函数isr_mbx_check
函数原型:
OS_RESULT isr_mbx_check (
函数描述:
函数isr_mbx_check用来检测消息邮箱剩余空间可以存储的消息个数。建议配合函数isr_mbx_send一起使用。
u
u
使用这个函数要注意以下问题:
1.
2.
使用举例:
u
#include
os_mbx_declare (mailbox, 10);
static void AppObjCreate (void)
{
}
void EXTI0_IRQHandler (void){
if (isr_mbx_check (&mailbox) != 0) {
}
u
#include
os_mbx_declare (mailbox, 10);
static void AppObjCreate (void)
{
}
void EXTI0_IRQHandler (void){
}
16.2.6函数isr_mbx_send
函数原型:
void isr_mbx_send (
函数描述:
函数isr_mbx_send用于向消息邮箱存放数据指针,或者说数据地址。如果消息邮箱已经满了,再次调用此函数会造成消息邮箱溢出。所以调用此函数前,强烈建议调用函数isr_mbx_check进行检测,检测是否还有空间可用。
u
u
使用这个函数要注意以下问题:
1.
2.
使用举例:
u
#include
os_mbx_declare (mailbox, 10);
static void AppObjCreate (void)
{
}
void EXTI0_IRQHandler (void){
if (isr_mbx_check (&mailbox) != 0) {
}
u
#include
os_mbx_declare (mailbox, 10);
static void AppObjCreate (void)
{
}
void EXTI0_IRQHandler (void){
}