ucos在s3c2410上运行过程整体剖析--创建任务到多任务调度及运行(3)
- UID
- 1029342
- 性别
- 男
|
ucos在s3c2410上运行过程整体剖析--创建任务到多任务调度及运行(3)
我们前面提到过,ucos这个工程中为了统一,把所有的外部中断服务程序都写到不同的中断结构体里了。这些中断结构体在ucos初始化的时候有一些简单的初始化。
在系统级任务里调用了这样一个函数:
SetISR_Interrupt(IRQ_TIMER4, TimerTickHandle, NULL);
这个函数就实现了对定时器有关的中断服务程序的初始化操作,并且打开了定时器中断的掩码寄存器标志位。我们知道,一开始我们的arm的cpsr的中断是禁止的,这个是在系统级任务运行时就打开了的(还记得未雨绸缪时的堆栈cpsr的内容不)。现在又打开了定时器中断的掩码寄存器标志位,好了,原来的双层保护都打开了,从现在开始ucos就开始响应定时器中断了。那中断服务程序都干了些什么那?
看下面代码 ,
unsigned int irq=GetISROffsetClr(); //得到中断向量的偏移地址
irq=fixup_irq(irq);
if(irq>=NR_IRQS)
return;
if(InterruptFunc[irq].InterruptHandlers==NULL){
InterruptFunc[irq].ack_irq(irq); //clear pending
return;
}
OSIntEnter();
// Call interrupt service routine
InterruptFunc[irq].InterruptHandlers(irq, InterruptFunc[irq].data);
InterruptFunc[irq].ack_irq(irq); //clear pending
OSIntExit();
}
得到中断服务程序的偏移量,即确定是什么外部中断。然后执行响应的中断服务程序,然后进入ucos的中断OSIntEnter();,在这里没干什么,只是对OSIntNesting这个变量加一。然后OSIntExit();,在这里面干的就多了,如果有更高的优先级的任务就绪,那直接切换到高优先级任务去执行,即在这发生中断级任务切换。
最后推出中断。
那定时器中断服务程序(就是那个OSTimeTick()函数)具体都干什么那?
下面是部分代码:
ptcb = OSTCBList; /* Point at first TCB in TCB list */
while (ptcb->OSTCBPrio != OS_IDLE_PRIO) { /* Go through all TCBs in TCB list */
OS_ENTER_CRITICAL();
if (ptcb->OSTCBDly != 0) { /* No, Delayed or waiting for event with TO */
if (--ptcb->OSTCBDly == 0) { /* Decrement nbr of ticks to end of delay */
/* Check for timeout */
if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {
ptcb->OSTCBStat &= ~OS_STAT_PEND_ANY; /* Yes, Clear status flag */
ptcb->OSTCBPendTO = TRUE; /* Indicate PEND timeout */
} else {
ptcb->OSTCBPendTO = FALSE;
}
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) { /* Is task suspended? */
OSRdyGrp |= ptcb->OSTCBBitY; /* No, Make ready */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
}
}
}
ptcb = ptcb->OSTCBNext; /* Point at next TCB in TCB list */
OS_EXIT_CRITICAL();
通过阅读,简单分析你就可以知道这个定时器中断服务程序,就是对所有的通过调用延时函数的任务的TCB进行对OSTCBDly进行减一操作。延时函数OSTimeDly干的活就是把当前任务挂起,并给这个任务的TCB中的OSTCBDly赋值。当这个值减到一就说明这个任务的延时时间到了,把这个任务再置成就绪态,等待调度。
综上所述,我们知道了。我们现在创建的任务都是自己调用OSTimeDly();函数自动放弃cpu的使用权,然后通过定时器中断函数计时,当延时时间到时把任务置为就绪态,等待调度和切换。
在这个例子中,就有两种产生调度的原因,一:任务自愿调用OSTimeDly()产生了一次任务调度和切换,定时器中断服务程序负责对延时计时,当时间到时,置位就绪表,并产生任务调度和切换。
可以发现,其实程序一直都被定时器打断,还有计时cpu大部分时间都被空闲任务占有。因为我们的那三个任务都是执行一段代码后就延时。而空闲任务不延时。它都是在定时器中断服务程序里被迫的让出cpu使用权。请仔细分析这个多任务调度实例,在头脑中形成一个宏观现象,有利于对ucos的整体掌握。
下章,我们仔细分析一下这个任务级任务切换和中断级任务切换时怎么在arm9上实现的,因为这两个函数都是用汇编书写的,又和硬件有一些联系,可能比较难理解一些。我们做详细讲解。下章见。 |
|
|
|
|
|