ucos II 任务切换 之 Delay()函数作用

原文:https://blog.csdn.net/passerbyyuan/article/details/51527697 

 

问题发现:当有一个任务没有进入延时的时候,这个任务就会一直执行不会挂起。就算有高优先级的任务已经准备好了,得等低优先级的任务执行完,或处于就绪态的时候,才能响应高优先级的的任务。所以任务里必须要有ucos ii系统里的延时函数,否则,没有延时函数的某优先级的任务会一直执行(当然也可以没有延时函数,只是必须要出现任务调度的代码)。

那么问题来了,为什么必须要使用系统里的延时函数呢?原因其实很简单:系统延时函数(OSTimeDly())调用了OS_Sched()函数,而OS_Sched()函数是根据任务就绪表找到当前就绪态的最高优先级任务。因此,本质上说我们需要在程序中的某个地方调用OS_Sched()函数来查找当前就绪任务并进行任务切换,释放当前任务对CPU的控制权。

void  OSTimeDly (INT32U ticks)
{
    INT8U      y;
#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr = 0u;
#endif
 
    if (OSIntNesting > 0u) {                     /* See if trying to call from an ISR                  */
        return;
    }
    if (OSLockNesting > 0u) {                    /* See if called with scheduler locked                */
        return;
    }
    if (ticks > 0u) {                            /* 0 means no delay!                                  */
        OS_ENTER_CRITICAL();
        y            =  OSTCBCur->OSTCBY;        /* Delay current task                                 */
        OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX;
        if (OSRdyTbl[y] == 0u) {
            OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY;
        }
        OSTCBCur->OSTCBDly = ticks;              /* Load ticks in TCB                                  */
        OS_EXIT_CRITICAL();
        OS_Sched();                              /* Find next task to run!                             */
    }
}
所以我们不可以在此处调用自定义延时函数(没有包含OS_Sched()函数),例如用:
x=1000;
while(x--);
这个,虽然有延时的效果,但系统默认为语句的执行而已,并不能使该任务在进入延时的时间里释放CPU的控制权。
大家都知道,进入延时的时候,该任务并没有对任何的外设进行控制,所以延时对于CPU来说是浪费资源,但在延时的时候能让CPU去执行其它的任务或做其它的操作,那就能达到高效利用CPU的资源。当该任务的延时时间到的时候,该任务就会处于就绪态,这样就由任务优先级的高低决定是否马上返回到该任务来。所以,想执行多个任务的时候,就必须利用系统里的延时函数,否则多个任务就变得无意义了。
附上部分程序源码:

//****************************************************************************

void led0_task(void *pdata)

      while(1)
      {
           //GPIO_SetBits(GPIOE,GPIO_Pin_5);
             LED0 = 1;
             delay_ms(1000);
           //GPIO_ResetBits(GPIOE,GPIO_Pin_5);
             LED0 = 0;
           //printf("¹ý·ÈË passerby!\r\n");
             delay_ms(1000);
}
}

void led1_task(void *pdata)
{  
   while(1)
   {
      //GPIO_ResetBits(GPIOE,GPIO_Pin_6);
        LED1 = 0;
        delay_ms(500);
      //GPIO_SetBits(GPIOE,GPIO_Pin_6);
        LED1 = 1;
        delay_ms(500);
   }
}
//***********************************************************

void delay_ms(u16 nms)

    if(OSRunning == TRUE)    
    { 
        if(nms>=fac_ms)
        {
            OSTimeDly(nms/fac_ms);
        }
        nms%=fac_ms; 
    }
    delay_us((u32)(nms*1000));
}

--------------------- 
作者:passerbyyuan 
来源:CSDN 
原文:https://blog.csdn.net/passerbyyuan/article/details/51527697 
版权声明:本文为博主原创文章,转载请附上博文链接!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值