OSQPend的分析

void  *OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *perr)


pevent 消息队列事件指针;timout被消息队列阻塞的超时时间;perr错误代号存储地址

1、检查参数合法性,包括pevent地址是否为空、perr地址是否为空;事件类型是否为消息队列;中断嵌套层数是否大于0,大于0表示有中断在执行,此时不能调用本函数;任务锁嵌套层数是否大于0,大于0不能调用本函数

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

2、关中断,取得消息队列事件指针所指向的消息队列

if (pq->OSQEntries > 0) 

3、当消息队列入口地址大于0,表示消息队列中有数据,将消息队列中的数据出口地址赋值给一个地址变量pmsg,递增出口地址且递减入口地址数(减少消息队列中数据数量);当数据出口地址到了消息队列末端时,重新赋值数据出口地址,返回消息队列中数据地址,置位perr无错标志

4、设置当前任务的任务控制块状态为消息队列挂起,挂起状态为挂起中(还有超时和终止两种状态),设置超时时间

OS_EventTaskWait(pevent)————————————————需要了解void  OSTimeTick (void)中的内容:检测当超时时间马上要到(下一step就到),假如有事件位,清空事件位,并置位事件超时;没有事件位,置位事件OK;然后当该任务是挂起状态,则置位任务准备组和准备表。在systick中调用了该函数,该函数后是OSIntExit();,OSIntExit();中执行了任务调度。

5、OS_EventTaskWait(pevent)函数实现了事件没有发送的话,挂起该任务。

在任务控制块中存储挂起该任务的事件指针;在事件控制块中的任务信息中,置位该任务,也就是添加事件中挂起的任务ID(优先级);在运行任务的任务信息中,清楚该任务的信息,防止被调度;当该任务所在的优先级字节为0,表明整个优先级组没有任务,清空优先组代表的那个位,避免无效工作

6、执行任务调度,运行了其他任务,该任务的上下文被保存到堆栈中

7、当消息队列中收到消息,(post动作),则会将该任务的上下文切换到运行任务信息中,再进行任务调度,从而恢复了该任务的运行


你可能感兴趣的:(OSQPend的分析)