μC/OS-II 的系统时钟

时间:2022-12-14 19:51:51

简介

μC/OS-II 与大多数计算机系统一样,用硬件定时器产生一个周期为 ms 级的周期性中断来实现系统时钟,最小的时钟单位就是两次中断之间相间隔的时间,这个最小时钟单位叫做时钟节拍(Time Tick)。
硬件定时器以时钟节拍为周期定时地产生中断,该中断的中断服务程序叫做 OSTickISR( )。中断服务程序通过调用函数 OSTimeTick( ) 来完成系统在每个时钟节拍时需要做的工作。

系统时钟中断服务程序

void OSTickISR(void)
{
    保存CPU寄存器;
    调用OSIntEnter( );                   
    if (OSIntNesting == 1;              
    {
        OSTCBCur->OSTCBStkPtr = SP; //保存堆栈指针
    }
    调用OSTimeTick( );                   
    清除中断;
    开中断;
    调用OSIntExit( );                
    恢复CPU寄存器;
    中断返回;
}

时钟节拍服务函数

void  OSTimeTick (void)
{
    ……
    OSTimeTickHook( );
    ……
    OSTime++;       //记录节拍数
    ……
    if (OSRunning == TRUE) {    
            ptcb = OSTCBList;
            while (ptcb->OSTCBPrio != OS_IDLE_PRIO) 
            {
                OS_ENTER_CRITICAL( );
                if (ptcb->OSTCBDly != 0) 
                {
                    if (--ptcb->OSTCBDly == 0) //任务的延时时间减一
                    {
                        if ((ptcb->OSTCBStat & OS_STAT_SUSPEND)
                                        == OS_STAT_RDY) 
                        { 
                            OSRdyGrp |= ptcb->OSTCBBitY;
                            OSRdyTbl[ptcb->OSTCBY]
                                                           |= ptcb->OSTCBBitX;
                        } else {
                            ptcb->OSTCBDly = 1;
                        }
                    }
                }
                ptcb = ptcb->OSTCBNext;
                OS_EXIT_CRITICAL( );
            }
    } 
}

函数 OSTimeTick( ) 的任务,就是在每个时钟节拍了解每个任务的延时状态,使其中已经到了延时时限的非挂起任务进入就绪状态。

任务的延时

由于嵌入式系统的任务是一个无限循环,并且 μC/OS-II 还是一个抢占式内核,所以为了使高优先级别的任务不至于独占 CPU,可以给其他任务优先级别较低的任务获得 CPU 使用权的机会,μC/OS-II 规定:除了空闲任务之外的所有任务必须在任务中合适的位置调用系统提供的函数 OSTimeDly( ),使当前任务的运行延时(暂停)一段时间并进行一次任务调度,以让出 CPU 的使用权。

系统提供的延时函数

void  OSTimeDly (INT16U ticks)
{
    INT8U      y;
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register */
    OS_CPU_SR  cpu_sr = 0;
#endif

    if (ticks > 0) {                             /* 0 means no delay! */
        OS_ENTER_CRITICAL();
        y            =  OSTCBCur->OSTCBY;        /* Delay current task */
        OSRdyTbl[y] &= ~OSTCBCur->OSTCBBitX;
        if (OSRdyTbl[y] == 0) {
            OSRdyGrp &= ~OSTCBCur->OSTCBBitY;
        }
        OSTCBCur->OSTCBDly = ticks;              /* Load ticks in TCB */
        OS_EXIT_CRITICAL();
        OS_Sched();                              /* Find next task to run! */
    }
}

取消任务延时函数

INT8U  OSTimeDlyResume (INT8U prio)

获得系统时间函数

INT32U  OSTimeGet (void)

设置系统时间函数

void  OSTimeSet (INT32U ticks)

参考自:《μC/OS-II 入门教程》