有时候一个任务需要和其他任务进行“交流”,这个交流就是消息传递,也称任务间的通信,在UCOSIII中可以通过消息队列作为中介发布任务,也可以直接发布给任务。
一:消息队列
1:一般概念
消息一般包括:指向数据的指针,表明数据长度的变量和记录消息发布时刻的时间戳,指针指向的可以是一块数据区甚至是一个函数,消息的内容必须保持可见性,因为发布数据采用的是引用传递是指针传递而不是值传递,也就是说,发布的数据本身不产生数据拷贝。
在UCOSIII中只有消息队列。消息队列是用户创建的内核对象数量不限制。
对于消息队列的读取既可以采用先进先出,也可以采用后进先出的方式。
任务可以指定一个超时时间,如果任务在这段时间内没有接受到消息的话就会唤醒任务,并且返回一个错误码告诉UCOSIII超时,任务是因为超时而被唤醒的,而不是接收到了消息,如果指定为0的话,任务就会一直等待下去。
消息队列中有一个链表,记录了所有正在等待消息的任务,,当一则消息被发布到队列中时,最高优先级的任务将获得该消息,发布方也可以向等待队列中所有任务广播这一消息。
二:常用API函数
1:创建消息队列
void OSQCreate (OS_Q *p_q,
CPU_CHAR *p_name,
OS_MSG_QTY max_qty,
OS_ERR *p_err)
p_q:指向一个消息队列,消息队列的存储空间必须由应用程序分配,采用如下的语句定义一个消息队列 OS_Q Msg_Que
p_name:消息队列的名字
max_qty:消息队列的长度,必须大于0,当然,如果缓冲池中没有足够的OS_Msgs可用,那么发送消息将会失败,并且返回相应的错误码。
2:等待消息队列
当一个任务想要从消息队列中接收到一个消息的话,就需要使用函数OSQPend().当任务调用这个函数时,如果消息队列中至少有一个消息时,这些消息就会返回给函数调用者。
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)
p_q:指向一个消息队列
timeout:等待消息的超时时间,如果在指定时间没有接收到消息时,任务就会被唤醒,接着运行。这个参数也可以是0,表示任务将一直等待下去,直到接收到消息。
opt:用来选择是否选用阻塞模式
OS_OPT_PEND_BLOCKING:如果没有任何消息的话,就阻塞任务,一直等待,直到接收到消息。
OS_OPT_PEND_NON_BLOCKING:如果消息队列没有任何消息的话,就直接返回。
p_msg_size:指向一个变量用来表示接收到的消息长度(字节)
p_ts:指向一个时间戳,表示什么时候接收到消息,如果赋值为0,表示没有时间戳要求。
如果消息队列中,没有任何消息,并且参数opt为OS_OPT_PEND_NON_BLOCKING,那么调用OSQPend()函数的任务将会被挂起,直到接收到消息或者超时。如果有消息发送给队列,但是同时有多个任务在等待这个消息,那么UCOSIII将恢复等待中的优先级最高的任务。
3:向消息队列发送消息
可以通过函数向消息队列发送消息,如果队列是满的,就可以,OSQPOST()就会立刻返回,并且返回一个特定的错误代码。
void OSQPost (OS_Q *p_q,
void *p_void,
OS_MSG_SIZE msg_size,
OS_OPT opt,
OS_ERR *p_err)
p_q:指向一个消息队列
p_void:指向实际发送的内容
msg_size:设定消息的大小,单位为字节
opt:用来选择消息发送的类型,基本类型有以下四种
OS_OPT_POST_ALL:发送给所有
OS_OPT_POST_FIFO:待发送消息保存在消息队列的末尾
OS_OPT_POST_LIFO:待发送消息保存在消息队列的头部
OS_OPT_POST_NO_SCHED:禁止在本函数内进行任务调度
组合类型有:
OS_OPT_POST_ALL+OS_OPT_POST_FIFO
OS_OPT_POST_ALL+OS_OPT_POST_LIFO
OS_OPT_POST_NO_SCHED+OS_OPT_POST_FIFO
OS_OPT_POST_NO_SCHED+OS_OPT_POST_LIFO
OS_OPT_POST_ALL+OS_OPT_POST_FIFO+OS_OPT_POST_NO_SCHED
OS_OPT_POST_ALL+OS_OPT_POST_LIFO+OS_OPT_POST_NO_SCHED
三:任务内建消息队列常用API函数
1:等待任务内建消息
void *OSTaskQPend (OS_TICK timeout,
OS_OPT opt,
OS_MSG_SIZE *p_msg_size,
CPU_TS *p_ts,
OS_ERR *p_err)
timeout:等待消息的超时时间,如果在指定时间没有接收到消息时,任务就会被唤醒,接着运行。这个参数也可以是0,表示任务将一直等待下去,直到接收到消息。
opt:用来选择是否选用阻塞模式
OS_OPT_PEND_BLOCKING:如果没有任何消息的话,就阻塞任务,一直等待,直到接收到消息。
OS_OPT_PEND_NON_BLOCKING:如果消息队列没有任何消息的话,就直接返回。
p_msg_size:指向一个变量用来表示接收到的消息长度(字节)
p_ts:指向一个时间戳,表示什么时候接收到消息,如果赋值为0,表示没有时间戳要求。
2:发送任务内建消息
void OSTaskQPost (OS_TCB *p_tcb,
void *p_void,
OS_MSG_SIZE msg_size,
OS_OPT opt,
OS_ERR *p_err)
p_tcb:指向接收消息任务的tcb,可以通过指定一个null指针或函数调用者的tcb地址来向该函数调用者发送一条自己的信息。
p_void:发送的一条消息
msg_szie:指定发送消息的大小(字节)
opt:指定发送的操作
OS_OPT_POST_FIFO
OS_OPT_POST_LIFO
上面两个选项可以和下面这个结合使用
OS_OPT_POST_NO_SCHED:指定该选项时,不会进行任务调度



