ucosii消息队列使用

ucosii消息队列简介

ucosii的消息队列源码定义在os_q.c文件;接口全部声明在ucos_ii.h,总共有如下接口:

void *OSQAccept(OS_EVENT *pevent,INT8U *perr);

说明:判断消息队列里是否含有消息,与OSQPend区别的是,如果没有消息,不会挂起线程;
其中pevent是指向消息队列的指针句柄,perr是异常返回值。

OS_EVENT *OSQCreate(void **start,  INT16U size);

说明:创建消息队列。
返回值是一个消息队列的句柄;
start是一个指针数组,用于缓存消息的指针,即是说一条消息的长度是可变的,只要将地址传过来即可;
size是指缓存数组可以缓存的消息数量。

OS_EVENT *OSQDel(OS_EVENT *pevent, INT8U opt, INT8U *perr);

说明:删除消息队列;删除后会将pevent->OSEventType置为无使用类型,所以再用OSQPend和OSQPost操作消息队列都无效。
返回值,如果成功则返回0,如果失败则返回pevent;
pevent是消息队列句柄;
opt可以是两个参数,OS_DEL_NO_PEND表示没有任务在等待该消息时才会删除消息,OS_DEL_ALWAYS即表示不管有没有任务在等待,都删除消息队列,如果有任务在等待该消息,会强制让任务标志为已经接收到该消息,然后进入就绪态;
perr异常返回值;
注意:删除消息后,最好不要将原指针置为NULL,因为在OSQPend和OSQPost没有空指针判断,可能会导致意想不到的结果。

INT8U OSQFlush(OS_EVENT *pevent);

说明:直译是刷新消息队列的内容;实际是复位消息队列,即把消息队列的内容清空;
pevent指向消息队列的句柄;

void *OSQPend(OS_EVENT *pevent, INT32U timeout, INT8U *perr);

说明:等待消息;
返回值,返回最先入队的消息的指针;消息的类型是自定义的,所以用的void型指针;
pevnet,消息队列句柄;
timeout,等待消息的超时时间,如果为0,则表示一直等待有消息为止,其它值则表示经过timeout个tick(一个tick就是一个systick的中断周期)后,就不在等待消息,往下执行;
perr,异常返回值;

INT8U OSQPendAbort(OS_EVENT *pevent, INT8U opt, INT8U *perr);

说明:根据字面意思是,中止任务等待该消息,就是说如果有任务由于等待该消息而挂起,则中止等待并将任务设为就绪态;
返回值,如果执行成功,返回中止该消息的任务数;如果失败返回0;
pevent,队列句柄;
opt,中止类型,OS_PEND_OPT_NONE,让其中一个任务(处在等待列表种最前的一个)停止等待消息;OS_PEND_OPT_BROADCAST,让所有在等该消息的任务停止等待;
perr,异常返回值

INT8U OSQPost (OS_EVENT *pevent, void *pmsg);

说明:发送一个消息;如果有较高优先级的任务在等待该消息,则消息不会进入缓冲区就切换到高优先级任务;
返回值,返回错误类型;
pevent,消息队列句柄;
pmsg,指向消息的指针,该消息可以是任意类型;

INT8U OSQPostFront (OS_EVENT *pevent,  void *pmsg);

说明:从前面插入队列,通常队列是先进先出,所以入队都是从后面入队的。该函数就是提供插队功能,入队的消息就是下一个出队的消息;
如果有较高优先级的任务在等待该消息,则消息不会进入缓冲区就切换到高优先级任务;
返回值,返回错误类型;
pevent,队列句柄;
pmsg,指向消息的指针;

INT8U OSQPostOpt (OS_EVENT *pevent, void *pmsg, INT8U opt);

说明:带参数的发送消息,具体参数类型看opt的描述;
返回值,返回错误类型;
pevent,队列句柄;
pmsg,指向消息的指针;
opt,OS_POST_OPT_NONE,使用该参数就如同调用OSQPost;
OS_POST_OPT_BROADCAST,广播该条消息,即向所有等待该队列的任务发送消息;
OS_POST_OPT_FRONT,使用该参数类似调用OSQPostFront;
OS_POST_OPT_NO_SCHED,该参数表示是否立刻切换到较高优先级的任务里处理该消息,如果用了该参数则不会立刻切换,需要先把消息放到队列缓冲区,运行完该函数才切换任务;
注意:这些opt参数可以或运算后才传入到函数;

INT8U OSQQuery (OS_EVENT *pevent, OS_Q_DATA *p_q_data);

说明:获取消息队列的信息;具体有哪些信息,可以看OS_Q_DATA结构体里面的成员;根据源码也可以分析得出;
返回值,返回错误类型;
pevent,队列句柄;
p_q_data,消息队列信息,1.等待该消息的任务列表(占用结构体两个成员);2.下一条出队的消息(FIFO规则);3.缓存的消息数量;4.消息队列的最大缓存数量;
注意:由于没用过该接口,分析可能有错

上述分析大多数都是从源码文件中的注释翻译得出,部分解析是根据源码逻辑分析得出,有些接口并不经常用到,所以可能分析的不够全面或有错误的地方,欢迎指正!

使用示例

#include "ucos_ii.h"
#define QUEUE_NUM 32 // 定义信息数量

static OS_EVENT * _msgQueue; //消息队列句柄
static void * _msgQueueCache[QUEUE_NUM]; //消息队列缓存区指针数值,每个元素指向一条消息,每条消息的内存最好是全局变量;

int isMsgInQueue(OS_EVENT *pevent, void *msg)
{
    if(pevent == NULL || msg == NULL)
    {
        return -1;
    }

    OS_Q *pq = NULL;
    pq = (OS_Q *)pevent->OSEventPtr;

    if(pq->OSQEntries == 0){
        return 0;
    }

    void ** msg_q = pq->OSQOut;
    while(msg_q != pq->OSQIn)
    {
        if(*msg_q == msg){
            return 1;
        }
        msg_q++;
        (msg_q == pq->OSQEnd) ? (msg_q = pq->OSQStart) : 0;
    }

    return 0;
}
/**
 * @brief 发送一条消息到缓存区,去重处理
 * @param[msg] 指向一条消息的地址,这个地址所在内存最好是全局变量
 * @return 1表示成功, 其它失败
 */
int sendMsgQueue(void * msg)
{
    if(isMsgInQueue(_msgQueue, msg))
    {
        return 1;
    }
    return (OSQPost(_msgQueue, msg) == OS_ERR_NONE);
}
/**
 * @brief 测试代码
 */
void testHalfDuplexTask(void *arg)
{
    INT8U err = OS_ERR_NONE;

    //创建消息队列。 第一个参数指定消息队列缓存区的起始地址;第二个参数指定缓存区的大小,即消息的数量
    _msgQueue = OSQCreate(&_msgQueueCache[0], QUEUE_NUM);

    uint8_t * msg = NULL;
    while(1)
    {
        msg = (uint8_t *)OSQPend(_msgQueue, 0, &err);
        if(msg != NULL && err == OS_ERR_NONE)
        {
            /*正常获取到一条消息*/
        }
    }
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值