1、UCOSIII任务间通信
1.1、任务间通信
一个任务或者中断服务程序有时候需要和另一个任务交流信息,这个就是消息传递的过程就叫做任务间通信;任务间的消息传递可以通过2种途径:一是通过全局变量,二是通过发布消息。
使用全局变量的时候每个任务或者中断服务程序都必须保证其对全局变量的独占访问。消息也可以通过消息队列作为中介发布给任务。
1.2 什么是消息?
消息包含一下几个部分:指向数据的指针,数据的长度和记录消息发布时刻的
时间戳,指针指向的可以是一块数据区域或者甚至是一个函数。 消息的内容必须一直保持可见性,可见性是指代表消息的变量必须在接收消息的任务代码范围内有效。这是因为发布的数据采用的是指针传递,也就是引用传递,并不是值传递。也就是说,发布的消息本身并不产生拷贝,我们可以使用动态内存分配的方式来给消息分配一个内存块,或者,也可以传递一个指向全局变量、全局数据结构、全局数组或者函数的指针。
2、UCOSIII消息队列
2.1消息队列的操作:
中断服务程序只能使用OSQPost()函数,在UCOSIII中对于消息队列的读取是先进先出FIFO,也可以后进先出LIFO的方式,采用后进先出的方式发布的消息会绕过其他所有位于消息队列中的消息而最先传递给任务。
小沙漏表示任务指定一个超时时间,如果任务在这段时间内没接收到消息就会唤醒任务,并返回错误码告诉UCOIII任务是被超时而唤醒的不是因为接收到了消息。超时时间设置为0那任务就会一直等待下去,知道接收到消息。
消息队列中有一个列表,就是消息队列记录了所有正在等待获得消息的任务,当一则消息发布到队列中时,最高优先级任务获得该消息,发布方也可以向消息队列中所有等待的任务广播一则消息。
2.2 消息队列是UCOSIII中的一个内核对象,为结构体OS_Q。
struct os_q {
OS_OBJ_TYPE Type;
CPU_CHAR *NamePtr;
OS_PEND_LIST PendList;
#if OS_CFG_DBG_EN > 0u
OS_Q *DbgPrevPtr;
OS_Q *DbgNextPtr;
CPU_CHAR *DbgNamePtr;
#endif
OS_MSG_Q MsgQ //消息列表
};
OS_MSG_Q也是一个结构体,如下:
struct os_msg_q {
OS_MSG *InPtr;
OS_MSG *OutPtr;
OS_MSG_QTY NbrEntriesSize;
OS_MSG_QTY NbrEntries;
OS_MSG_QTY NbrEntriesMax;
};
消息发布以后会被存放在OS_MSG类型的数据结构中,OS_MSG如下:
struct os_msg {
OS_MSG *NextPtr;
void *MsgPtr;
OS_MSG_SIZE MsgSize;
CPU_TS MsgTS;
};
2.3 消息队列API函数
2.3.1 创建消息队列
void OSQCreate (OS_Q *p_q, //指向一个消息队列,采用OS_Q Msg_Que定//义一个消息队列
CPU_CHAR *p_name, //消息队列的名字
OS_MSG_QTY max_qty, //消息队列的长度,必须大于0
OS_ERR *p_err) //保存错误码
2.3.2 等待消息队列
void *OSQPend (OS_Q *p_q,//指向一个消息队列
OS_TICK timeout,//等待消息的超时时间
OS_OPT opt,//选择是否使用阻塞模式,有2个选项
OS_MSG_SIZE *p_msg_size,//指向一个变量用来表示接收到消息长度
CPU_TS *p_ts,//指向一个时间戳,表明什么时候接收到消息
OS_ERR *p_err)
2.3.3 向消息队列发送消息
void OSQPost (OS_Q *p_q,//指向一个消息队列
void *p_void,//指向实际发送的内容
OS_MSG_SIZE msg_size,//设定消息的大小,字节数
OS_OPT opt,//选择消息发送操作的类型,基本有四种也可结合
OS_ERR *p_err)
3、UCOSIII任务内建消息队列
同任务内嵌信号量一样,UCOSIII的每个任务中也有内建消息队列。而且多个任务等待同一个消息队列的应用很少见,UCOSIII中每个任务多有其内建消息队列的话用户可以不用通过外部的消息队列而直接向任务发布消息。
如果需要使用任务内建消息队列功能的时候需要将宏OS_CFG_TASK_Q_EN置1来使能相关的代码。
任务内建消息队列的函数在os_task.c中
3.1等待任务内建消息
void *OSTaskQPend (OS_TICK timeout,//等待消息的超时时间
OS_OPT opt,//是否使用阻塞模式
OS_MSG_SIZE *p_msg_size,//存放消息大小的变量
CPU_TS *p_ts,//时间戳
OS_ERR *p_err)
3.2 发送任务内建消息
void OSTaskQPost (OS_TCB *p_tcb,//指向接收消息任务的TCB
void *p_void,//发送给一个任务的消息
OS_MSG_SIZE msg_size,//消息的大小
OS_OPT opt,//发送操作类型:LIFO和FIFO
OS_ERR *p_err)