欣欣学习网,老工程师带你学习单片机技术,欢迎来坐坐。
首  页 | 学习NIOSII | 学习C51 | 学习CPLD | 51+CPLD实验板 | | | MY-RTOS

 系统简介
 系统启动
 创建任务
 等待与休眠
 使用互斥量
 使用信号量
 信号量组
 使用事件
 使用事件组
 消息队列
 动态内存管理
 只读内存管理
 临界段与内核锁
 任务复位与终止


玛雅实时操作系统(MY-RTOS)

消 息 队 列


版权声明:玛雅实时操作系统(MY-RTOS)软件及其说明文档由 欣欣学习网 版主 Stoneway QI 创作,作者保留其版权。任何人可以免费在其产品设计或著作中使用或引用该软件及其说明文档,但要求保留原作品当中的版权声明,并注明引用段落的出处。

-- Stoneway QI 主页: http://www.xxworks.com 邮箱: Stonewayqi@hotmail.com

当需要有大量的消息在任务间有次序的传递的时候,使用事件往往不能达到预期的效果,此时可以借助消息队列来完成这一工作。消息队列是玛雅系统专门为消息传递而设置的机制,有8位消息队列、16位消息队列和32位消息队列之分。消息队列中可以缓冲消息接收者来不及取走的消息,缓冲深度由应用程序根据需求设定。

在使用消息队列之前首先要对其进行定义,并定义一个用于缓冲消息的数组,然后调用系统函数OSInitCircle()对其初始化。玛雅系统要求这些变量都要定义成全局变量,或者静态局部变量,也允许在动态内存中建立这些变量。用于缓冲消息的数组的类型要与待缓冲的消息的类型相匹配,即:缓冲8位字长的消息要定义U8型的数组,缓冲16字长的消息要定义U16型的数组,而缓冲32位字长的消息要定义U32型的数组。该数组的长度即是消息列的消息缓冲深度。

函数OSInitCircle()有4个入口参数,第1个入口参数是指向待初始化的消息队列的指针,第2个入口参数是指向缓冲区起始地址的指针,第3个入口参数用于传递消息队列的缓冲深度,第4个入口参数用于传递消息队列的类型。当该函数返回值为OS_STATUS_OK时,表示成功完成初始化,其它值则分别代表各种错误。以建立1个32位字长,缓冲深度为20个消息的消息队列为例,代码如下:

...
U32 Buffer[20];                                     //定义缓冲数组
OS_CIRCLE Circle;         ;                         //定义成全局变量类型的消息队列
...
void main(void)
{
    BSP(); // 硬件初化
    OSInit(72000); //玛雅系统初始化
    OSInitCircle(&Circle, Buffer, 20, OS_CIRCLE_MODE_32BIT);  //对消息队列做初始化
    ...
    while(1)
    {
        ...
    }
}                       (1)

系统函数OSPushCircle()用来向消息队列中压入消息,而系统函数OSPopCircle()则用来从消息队列中弹出消息,先被压入的消息优先被弹出。函数OSPushCircle()有两个入口参数,第1个入口参为是消息队列指针,指向待操作的消息队列,第2个参数是U32型变量,用于传递消息代码。当该函数返回值为OS_STATUS_OK时,表示成功将消息压入消息队列。其它值分别代表各种错误。函数OSPopCircle()也有两个入口参数,第1个入口参数是指向待操作消息队列的指针,指2个入口参数是void型指针,用于指向1个保存返回消息的变量,该变量的类型要与消息队列的类型相匹配。当该函数的返回值为OS_STATUS_OK时,表示成功的从消息队列中弹出消息,其它值则分别代表各和错误。

...
#define MSG1   ...
#define MSG2   ...
...
void main(void)
{
    U32 Msg = 0;
    U8 MsgId = 0;
    ...
    ...    
    while(1)
    {
        ...
        if(OSPopCircle(&Circle, &Msg) == OS_STATUS_OK)
        {                                               
            ...                //成功的取到1个消息加以处理
        }
        ...
    }
}        

void Task1(void)
{
    ...
    while(1)
    {
        ...
        if(OSPushCircle(&Circle, MSG1) == OS_STATUS_OK)  
        {
            ...                //成功的将消息压入消息队列
        }
        ...
    }
}                       (2)

在玛雅系统中,允许任务和中断服务程序向消息队列中压入消息,也允许任务和中断服务程序从消息队列中弹出消息。消息的压入与弹出无论成功与否,相关的系统函数都会立刻返回,而不会产生等待。玛雅系统允许多个任务或中断服务程序向同一个消息队列压入消信,也允许多个任务和中断服务程序从同一个消息队列中弹出消息。

在有些情况下,任务需从消息队列中成功的弹出1个消息之后才能做下一步的处理,而返复的调用系统函数从消息队列中弹消息无疑是浪费宝贵的CPU资源。这时,可以使用系统函数OSWaitCircle()来化解这一问题。当队列中没有消息可以取出时,该函数会使任务进入等待状态,直到获得消息或超时退出。该函数有3个入口参数,第1个入口参数是指向消息队列的指针,第2个入口参数是指向用于保存返回消息的变量的指针,第3个入口参数用于传递限定时间,单位为系统节拍,当取值为-1时表示无限期等待。当该函数返回值为OS_STATUS_OK时,表示成功的从消息队列中获得消息,其它值则代表各种错误。使用该函数的示例代码如下:

...
#define MSG1   ...
#define MSG2   ...
...
OS_SEM CircleSem = {0, 0};
...
void main(void)
{
    U32 Msg = 0;
    U8 MsgId = 0;
    ...
    ...    
    while(1)
    {
        ...
        if(OSWaitCircle(&Circle, &Msg, 1000) == OS_STATUS_OK)
        {                                               
            ...                              //获得消并做出处理
        }
        else
        {
            ...                              //超时而未获得消息
        }
    }
}                        (3)

有些情况下,需要放弃消息队列中已有的消息,这时可以调用系统函数OSResetCircle()来清空消息队列。

...
...
void main(void)
{
    U32 Msg = 0;
    ...
    ...    
    while(1)
    {
        ...
        OSResetCircle(&Circle);   //清空消息队列中已有的消息
        ...
    }
}                       (4)


管理员信箱: stonewayqi@hotmail.com

欣 欣 学 习 网

粤ICP备2023138008号