一、消息队列
主要作用:为多个任务或者中断服务程序间通信提供了一个队列保存消息,定向或广播式发布消息。
消息一般包含:指向数据的指针,表明数据长度的变量和记录消息发布时刻的时间戳,指针指向的可以是一块数据区或者甚至是一个函数。
消息队列与信号量的对比:
两者都在多任务间进行,信号量更像是一种授权,他只能告诉一个任务是否能够继续进行下去回答YES OR NO的问题,而消息队列能传递的内容丰富得多,可以实现多任务间配合工作。
消息队列的代码实现:
UCOS III中消息队列其实就是一个单链表,每个节点数据结构由OS_MSG结构体定义里面的内容包括下一节点地址指针(NextPtr)、该节点消息长度(MsgSize)、消息的时间戳(MsgTs)、以及消息内容真正的起始指针。
整个消息链表由OS_MSG_Q结构体变量管理,该结构体变量成员包含,单链表的起始节点指针(OutPtr)和末尾节点指针(InPtr)、消息链表容量(NbrEnTriesSize)、当前已使用节点数(NbrEntries)、历史最多使用节点数(NbrEntriesMax)
最后是消息队列信息结构体OS_Q,包含消息队列的类型(type)、名称字符串指针(NamePtr)、
和消息队列的指针。
UCOS III中消息队列的API函数
常用的包括创建、发布、等待消息函数(红色部分)
创建函数
void OSQCreate (OS_Q *p_q, //消息队列信息结构体指针
CPU_CHAR *p_name, //消息队列名称字符串指针
OS_MSG_QTY max_qty, //最大消息数
OS_ERR *p_err) //报错返回值
发布函数
void OSQPost (OS_Q *p_q, //消息队列信息结构体指针
void *p_void, //要发布的内容的指针
OS_MSG_SIZE msg_size, //该内容大小
OS_OPT opt, //发布选项
OS_ERR *p_err) //报错返回值
【注】发布消息候并不是直接把消息传达给某个其他任务,而是在消息队列中创建一个新的节点,将消息先保存,如果有对应任务等待该消息就将该消息指针传递给他。
发布选项(opt):
- OS_OPT_POST_ALL:将消息发送给所有等待该消息队列的任务(广播的意思),需要和选项OS_OPT_POST_FIFO或者OS_OPT_POST_LIFO配合使用;
- OS_OPT_POST_FIFO:待发送消息保存在消息队列的末尾;
- OS_OPT_POST_LIFO:待发送的消息保存在消息队列的开头;
- OS_OPT_POST_NO_SCHED:禁止在本函数内执行任务调度。
我们可以使用上面四种基本类型来组合出其他几种类型,如下:
OS_OPT_POST_FIFO + OS_OPT_POST_ALL
OS_OPT_POST_LIFO + OS_OPT_POST_ALL
OS_OPT_POST_FIFO + OS_OPT_POST_NO_SCHED
OS_OPT_POST_LIFO + OS_OPT_POST_NO_SCHED
OS_OPT_POST_FIFO + OS_OPT_POST_ALL + OS_OPT_POST_NO_SCHED
OS_OPT_POST_LIFO + OS_OPT_POST_ALL + OS_OPT_POST_NO_SCHED
等待函数:
void *OSQPend (OS_Q *p_q, //消息队列信息结构体指针
OS_TICK timeout, //最大等待时间
OS_OPT opt, //等待选项
OS_MSG_SIZE *p_msg_size, //指向一个变量用于保存消息长度
CPU_TS *p_ts, //指向一个变量用于保存消息的时间戳
OS_ERR *p_err) //返回错误信息
等待选项(opt):
- OS_OPT_PEND_BLOCKING:若消息队列为空,则一直等待
- OS_OPT_PEND_NON_BLOCKING:若消息队列为空,返回