Ucos源码分析
1.Ucos源码分析------任务控制块与任务调度
2.Ucos源码分析------事件控制块与事件控制
3.Ucos源码分析------信号量
4.Ucos源码分析------邮箱与队列
5.Ucos源码分析------事件标志组
6.Ucos源码分析------内存管理
7.Ucos源码分析------临界区与中断管理
8.Ucos源码分析------OS启动
9.Ucos总结
终于看完了源码!!!现在整合一下前面的(不断完善)。
1.几个控制块链表
2.任务调度的几个底层函数:
对任务控制主要和这几个有关:
1.当前任务的状态
2.任务就绪表
3.事件控制块的任务等待链表
当任务加入就绪表,从等待任务链表移除后,任务状态且就绪态,在OS_Sched ()后被调度,下面代码中的1 2 3 代表上面的三个环节。
任务从就绪表移除,添加到任务等待链表,等待事件置位是在Pend()中实现
加入任务就绪表 | 任务等待事件清除 | 从事件任务等待链表移除 | |
---|---|---|---|
不超时,不挂起的 | POST | POST | POST |
超时,不挂起的 | OSTimeTick | OS_EventTO | OS_EventTO |
不超时,不挂起的 | OSTaskResume | POST | POST |
任务加入就绪表三个方式:
1.滴答时钟将任务加入就绪表。
2.挂起任务恢复时加入
3.事件(信号量、邮箱等)释放时
最底层代码:
OS_EventTaskWait(pevent);
2.实现任务从就绪链表删除
3.实现任务添加到事件链表
OS_EventTaskRdy
3.实现移出事件链表
1.任务状态移除所等待事件
2.如果移除所等待事件后,任务变为就绪态(主要与手动挂起区分),任务加入就绪链表
在最底层代码进行封装,是外面可以直接用的API
OSSemPend()
1.当前任务等待事件置位
2.OS_EventTaskWait
任务超时:
任务超时是通过任务调度后,所等待的事件状态有没有清除判断的。
if (OSTCBCur->OSTCBStat & OS_STAT_SEM) { /* Must have timed out if still waiting for event*/
OS_EventTO(pevent);
OS_EXIT_CRITICAL();
*err = OS_TIMEOUT; /* Indicate that didn't get event within TO */
return;
}
超时不会调用OS_EventTaskRdy只会,OS_EventTO()
2.任务状态移除所等待事件
3.任务从等待事件列表移除
void OS_EventTO (OS_EVENT *pevent)
{
//从事件等待列表移除
if ((pevent->OSEventTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0x00) {
pevent->OSEventGrp &= ~OSTCBCur->OSTCBBitY;
}
//修改当前任务为就绪态
OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set status to ready */
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* No longer waiting for event */
}
任务加入就绪表是通过滴答时钟实现的
OSTimeTick()
1.任务加入就绪表
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) { /* Is task suspended? */
//任务不是被主动挂起的,需要将其加入到就绪表
OSRdyGrp |= ptcb->OSTCBBitY; /* No, Make task R-to-R (timed out)*/
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
} else { /* Yes, Leave 1 tick to prevent ... */
//判断任务是主动挂起的重新设置延时为1
ptcb->OSTCBDly = 1; /* ... loosing the task when the ... */
}
挂起任务的恢复
OSTaskResume()
实现任务加入就就绪表
if (((ptcb->OSTCBStat &= ~OS_STAT_SUSPEND) == OS_STAT_RDY) && /* Remove suspension */
(ptcb->OSTCBDly == 0)) { /* Must not be delayed */
//任务加入就绪表
OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OS_EXIT_CRITICAL();
//系统调度
OS_Sched();
} else {
OS_EXIT_CRITICAL();
}
3中段与任务调度
有些API是不能在中断中进行的:
任务的创建,信号量的创建:
涉及到对内存分配和其他需要较长时间完成的操作,会影响中断服务程序的执行时间
进程切换造成阻塞的:
中断前会关闭中断,滴答时钟无法进行正常工作,且任务调度的单位是任务控制块,没有中断控制块的原因是中断不能进行长时间的工作。
4其它
不管将消息发送给多少事件, 系统仅调度一次,运行最高优先级任务
INT8U OSQPostOpt (OS_EVENT *pevent, void *msg, INT8U opt)
遇到void *时
将传递过来的空地址首先进行强制类型转换成指向数据类型明确的指针后