Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15482795
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类:

2007-09-09 11:18:30

浅析μC/OS-II v2.85内核OSTimeDly()函数工作原理

文章来源:http://gliethttp.cublog.cn[转载请声明出处]

//----------------------------------------------------------------------
//1.OSTimeDly()函数
void OSTimeDly (INT16U ticks)
{
    INT8U y;
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR cpu_sr = 0;
#endif
    if (OSIntNesting > 0) {
        return;//在中断处理函数中调用了OSTimeDly(),那么直接退出
    }
    if (ticks > 0) {
        OS_ENTER_CRITICAL();
//调用OSTimeDly()的进程自己把自己从就绪控制矩阵中拿下来,
//即:去掉调度器(x,y)矩形阵列(OSRdyTbl,OSRdyGrp)中该task对应的bit位,使得调度器不考虑
//该task的调度
        y = OSTCBCur->OSTCBY;
        OSRdyTbl[y] &= ~OSTCBCur->OSTCBBitX;
        if (OSRdyTbl[y] == 0) {
            OSRdyGrp &= ~OSTCBCur->OSTCBBitY;
        }
//延时ticks值,放入OSTCBDly单元,在os时钟滴答处理函数OSTimeTick()中,会处理该单元[gliethttp]
        OSTCBCur->OSTCBDly = ticks;
        OS_EXIT_CRITICAL();
//因为本task正在运行,所以本task现在的优先级最高,现在本task已经将自己从就绪控制矩阵中--调度器(x,y)矩形阵列
//把自己摘掉,所以调度函数OS_Sched()一定会切换到另一个task中执行新task的代码[gliethttp]
        OS_Sched();//具体参见《浅析μC/OS-II v2.85内核调度函数》
    }//ticks==0,那么什么也不做
}
//----------------------------------------------------------------------
//2.OSTimeTick()--在定时中断里引用的系统滴答函数
void OSTimeTick (void)
{
    OS_TCB *ptcb;
#if OS_TICK_STEP_EN > 0
    BOOLEAN step;
#endif
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR cpu_sr = 0;//该3方式将使中断状态寄存器放入堆栈中

#endif

#if OS_TIME_TICK_HOOK_EN > 0
    OSTimeTickHook();
#endif
#if OS_TIME_GET_SET_EN > 0
    OS_ENTER_CRITICAL();
    OSTime++;
    OS_EXIT_CRITICAL();
#endif
    if (OSRunning == OS_TRUE) {
#if OS_TICK_STEP_EN > 0
//控制内核的tick
        switch (OSTickStepState) {
            case OS_TICK_STEP_DIS:
                 step = OS_TRUE;
                 break;
            case OS_TICK_STEP_WAIT:
                 step = OS_FALSE;
                 break;
            case OS_TICK_STEP_ONCE:
//本次tick将将影响到task的OSTCBDly域
//但以后的tick将一直被屏蔽,不会影响到OSTCBDly域
//直到外部将OSTickStepState改变为止[gliethttp]
                 step = OS_TRUE;
                 OSTickStepState = OS_TICK_STEP_WAIT;
                 break;
            default:
                 step = OS_TRUE;//本次tick将影响到task的OSTCBDly域
                 OSTickStepState = OS_TICK_STEP_DIS;
                 break;
        }
        if (step == OS_FALSE) {
            return;
        }
#endif
        ptcb = OSTCBList;
//2007-09-08 gliethttp
//OSTCBList是一个按进程创建的先后顺序链接成的task单向链表,最后创建的task在最前面,最先创建的
//task在单向链表的尾端,
//所以OS_TaskIdle空闲进程在链表的最后,因为它最先创建
        while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) {
            OS_ENTER_CRITICAL();
            if (ptcb->OSTCBDly != 0) {
                if (--ptcb->OSTCBDly == 0) {
//该task的延时时间已到,解析此次延时是OSTimeDly()引起的,还是OSQPend()之类超时引起的[gliethttp]
                    if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {
                        //2007-09-08 gliethttp
                        //如:由OSSemPend (pevent,timeout,perr);定义的timeout已经到了,对应task需要运行了
                        //超时时间到,所以不论当前进程是在做什么,只要时间一到
                        //该task就可以运行了,所以清除所有事件标志,之后状态标示为OS_STAT_PEND_TO(超时)
                        ptcb->OSTCBStat &= ~(INT8U)OS_STAT_PEND_ANY;
                        ptcb->OSTCBStatPend = OS_STAT_PEND_TO;//超时异常
                    } else {
                        //2007-09-08 gliethttp
                        //说明该task调用的是OSTimeDly()
                        ptcb->OSTCBStatPend = OS_STAT_PEND_OK;//正常结束
                    }
                    if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) {
                        //2007-09-08 gliethttp
                        //如果该task没有suspend,那么把当前就绪的task加入到运行调度器的就绪控制矩阵中
                        //等待被调度
                        OSRdyGrp |= ptcb->OSTCBBitY;
                        OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
                    }
                }
            }
            ptcb = ptcb->OSTCBNext;//继续运算下一个task的OSTCBDly时间域
            OS_EXIT_CRITICAL();
        }
    }
}

阅读(5638) | 评论(9) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2008-11-18 16:33:54

你可以查一下cpsr寄存器的数值,看看IRQ是否使能了 /* * Enable IRQs */ #define raw_local_irq_enable() \ ({ \ unsigned long temp; \ __asm__ __volatile__( \ "mrs %0, cpsr @ local_irq_enable\n" \ " bic %0, %0, #128\n" \ " msr cpsr_c, %0" \ : "=r" (temp) \ : \ : "memory", "cc"); \ }) /* * Disable IRQs */ #define raw_local_irq_disable() \ ({ \ unsigned long temp; \ __asm__ __volatile__( \ "mrs %0, cpsr @ local_irq_disable\n

chinaunix网友2008-11-18 16:00:41

我怀疑是定时中断的问题。 同样的设置 在一个小程序里都可以运行 为什么加到ucos就不行了呢? 程序就是进不去中断函数。

chinaunix网友2008-11-18 10:07:04

pll是cpu对应文件下的内容

chinaunix网友2008-11-18 09:41:15

请问PLL时钟是在哪个文件里配置的?谢谢!

chinaunix网友2008-11-14 16:00:13

如果同样的程序在2个板子上运行,一个板子上可以正常,一个不正常,如果没有控制外围硬件,只是使用了cpu内部资源,那么说明,程序配置pll时钟存在太大的问题,可以适当把频率降下来,因为有些板子可以跑到100MHZ,而有些板子则只能跑到80MHZ,高了就导致crash!