标题:
uC/OSIII的消息队列处理机制(3)
[打印本页]
作者:
yuyang911220
时间:
2015-5-27 21:35
标题:
uC/OSIII的消息队列处理机制(3)
延迟推送中,OS_IntQPost()函数的接收者是中断延迟处理任务OS_IntQTask(),(这两个函数都定义在ucosiii\source的os_int.c文件中)该任务处理中再调用OS_QPost()函数,结果就是OS_QPost()调用点由中断中转移到中断处理任务中,节省了关中断时间。延迟推送和中断机制不是这里讨论的重点,所以直接进入OS_QPost()函数:
void OS_QPost (OS_Q *p_q,
void *p_void,
OS_MSG_SIZE msg_size,
OS_OPT opt,
CPU_TS ts,
OS_ERR *p_err) /*入口参数与OS_QPost一样*/
{
OS_OBJ_QTY cnt;
OS_OPT post_type;
OS_PEND_LIST *p_pend_list;
OS_PEND_DATA *p_pend_data;
OS_PEND_DATA *p_pend_data_next;
OS_TCB *p_tcb;
CPU_SR_ALLOC();
OS_CRITICAL_ENTER();
p_pend_list = &p_q->PendList; /*这里是找出该队列下的OS_PEND_LIST列表*/
if (p_pend_list->NbrEntries == (OS_OBJ_QTY)0) {
/* 如果列表里显示等待的任务TCB数目为0,也就是没有任务pend该队列,就没必要查
找相关的任务进行推送,直接把消息保存下来就好了*/
部分代码略。
/*那么就调用OS_MsgQPut,将消息存储到队列中的消息链表中*/
OS_MsgQPut(&p_q->MsgQ,
p_void,
msg_size,
post_type,
ts,
p_err);
OS_CRITICAL_EXIT();
return;
}
/* 如果列表里显示等待的任务TCB数目不为0,也就是有任务正在pend该队列,就必须把消息推送给它,就会执行以下代码*/
cnt = 要推送的数量;代码略;
p_pend_data = p_pend_list->HeadPtr; /*从p_pend_list里找出p_pend_data链表*/
while (cnt > 0u) {
p_tcb = p_pend_data->TCBPtr; /*从p_pend_data里找出等待的任务TCB*/
p_pend_data_next = p_pend_data->NextPtr;
OS_Post((OS_PEND_OBJ *)((void *)p_q), /*推送到等待的任务TCB*/
p_tcb,
p_void,
msg_size,
ts);
p_pend_data = p_pend_data_next;
cnt--; /*按要推送的数量cnt循环,直到退出*/
}
OS_CRITICAL_EXIT_NO_SCHED();
if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0) {
OSSched(); /* 进行任务调度 */
}
*p_err = OS_ERR_NONE;
}
可见,OS_QPost 函数中又包含了两层调用:如果没有任务等待该消息队列,就调用OS_MsgQPut函数;如果有任务在等待,就调用OS_Post把消息推送给正在等待的任务。
简单介绍下这两个函数,它们是最后一级了,内容基本都是查找排序算法,没有太多的架构知识可讲了:
OS_MsgQPut函数(定义在ucosiii\source的OS_msg.c中)负责从OS_MSG_POOL中取出一个空闲的OS_MSG,将消息写入到它内部,然后将该OS_MSG挂到对应的消息队列下面。
OS_Post函数(定义在ucosiii\source的OS_core.c中)是直接向任务推送消息的函数,它先判断任务是单队列QPend还是MultiPend:
如果是单队列QPend,就把消息内容指针直接写到TCB里面MsgPtr和MsgSize中:
p_tcb->MsgPtr = p_void; /* Deposit message in OS_TCB of task waiting */
p_tcb->MsgSize = msg_size;
注意这两个成员变量,是定义在任务TCB结构体中的两个成员,是伴随TCB一生的,可以随时取用。
如果是MultiPend,则调用OS_Post1函数,把消息内容指针写到OS_PEND_DATA中专供MultiPend使用的几个字段中,这个在前面介绍OS_PEND_DATA时有介绍,可以回头去再看一下。写入代码如下:
p_pend_data->RdyObjPtr = p_obj;
p_pend_data->RdyMsgPtr = p_void;
p_pend_data->RdyMsgSize = msg_size;
p_pend_data->RdyTS = ts;
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0