【13】从0到1教你写uC/OS-III————>阻塞延时与空闲任务

  1. 上章节系统所有延时,与前后台无差别,体现不出RTOS的优势;
  2. RTOS的优势就是榨干系统性能,永远不让CPU闲着; 因此任务需要延时就不能让CPU空等,至此加入阻塞延时概念; 
  3. 阻塞延时:即任务需要延时的时候,任务放弃CPU的使用 权,CPU可以去干其它事,当任务延时时间到,重新获取CPU使用权,任务继续运行,充分利用CPU的资源,而不是干等;
  4. 空闲任务:系统初始化时创建的优先级最低的任务,只是对空闲全局变量计数;实际应用中,可以利用这种特性在空闲任务中让CPU进入低功耗模式或者睡眠状态; 
  5. 例程:
    /*
    ************************************************************************************************************************
    *                                        空闲任务堆栈大小、起始地址
    ************************************************************************************************************************
    */
    
    CPU_STK     OSCfg_IdleTaskStk[OS_CFG_IDLE_TASK_STK_SIZE];
    
    //空闲任务堆栈起始地址
    CPU_STK     *const  OSCfg_IdleTaskStkBasePtr    =   (CPU_STK    *)&OSCfg_IdleTaskStk[0];
    //空闲任务堆栈大小
    CPU_STK     const   OSCfg_IdleTaskStkSize       =   (CPU_STK_SIZE)OS_CFG_IDLE_TASK_STK_SIZE;
    
    
     /*********************************************************
     * 函数名: void    OSSched(void);                       
     * 描述  :任务调度
     * 输入  :无
     * 输出  :无
     * 返回  :无 
     * 调用  :内部调用 
     **********************************************************/
    void    OSSched(void)
    {
        #if 0   //两个任务简单的交替运行
            if(OSTCBCurPtr == OSRdyList[0].HeadPtr)
            {
                OSTCBHighRdyPtr = OSRdyList[1].HeadPtr;
            }
            else
            {
                OSTCBHighRdyPtr = OSRdyList[0].HeadPtr;
            }
        #endif 
        
        //如果当前任务是空闲任务,那就尝试执行其它任务,看他们的延时时间是否结束
        //如果任务的延时时间均无到期,那就返回继续执行空闲任务
        if(OSTCBCurPtr  ==  &OSIdleTaskTCB)
        {
           if(OSRdyList[0].HeadPtr->TaskDelayTicks == 0)    //判断任务0延时是否到达
           {
                OSTCBHighRdyPtr = OSRdyList[0].HeadPtr;     //到达,下个任务指向任务0
           }           
           else if(OSRdyList[1].HeadPtr->TaskDelayTicks == 0)
           {
                OSTCBHighRdyPtr = OSRdyList[1].HeadPtr;     //同上
           }
           else
           {
                return ;    //任务延时都没有到达,返回继续执行空闲任务
           }
        }
        //如果当前任务非空闲任务,检查另外任务,如果不在延时中,就切换到该任务
        //否则,判断下当前任务是否进入延时状态,是的话切换到空闲任务,不是不做任何切换 
        else
        {
            if(OSTCBCurPtr == OSRdyList[0].HeadPtr)  //判断当前任务是否为任务0
            {
                if(OSRdyList[1].HeadPtr->TaskDelayTicks ==0)   //判断任务1延时是否到达
                {
                    OSTCBHighRdyPtr = OSRdyList[1].HeadPtr;     //到过,下一个任务切换任务1
                }
                else if(OSTCBCurPtr->TaskDelayTicks != 0)       //判断当前任务是否到达延时状态
                {                                                   
                    OSTCBHighRdyPtr = &OSIdleTaskTCB;           //是,切换回空闲任务
                }
                else
                {
                    return ;        //返回,保持当前运行状态
                }
            }
            else if(OSTCBCurPtr == OSRdyList[1].HeadPtr)  //判断当前任务是否为任务1
            {
                if(OSRdyList[0].HeadPtr->TaskDelayTicks ==0)   //判断任务0延时是否到达
                {
                    OSTCBHighRdyPtr = OSRdyList[0].HeadPtr;     //到过,下一个任务切换任务0
                }
                else if(OSTCBCurPtr->TaskDelayTicks != 0)       //判断当前任务是否到达延时状态
                {                                                   
                    OSTCBHighRdyPtr = &OSIdleTaskTCB;           //是,切换回空闲任务
                }
                else
                {
                    return ;        //返回,保持当前运行状态
                }
            }
        }
    
        OS_TASK_SW();   //触发PendSV异常
    }
    
     /*********************************************************
     * 函数名: OS_IdleTask(void *p_arg);                    
     * 描述  :空闲任务
     * 输入  :无
     * 输出  :无
     * 返回  :无 
     * 调用  :内部调用 
     **********************************************************/
    void    OS_IdleTask(void *p_arg)
    {
        p_arg = p_arg;
        
        //空闲任务什么都不做; 只是对全局变量OSIdleTaskCtr++操作
        for(;;)
        {
            OSIdleTaskCtr++;
        }
    }
    
     /*********************************************************
     * 函数名:OS_IdleTaskInit(OS_ERR  *p_err);                    
     * 描述  :空闲任务初始化,放在系统初始化中
     * 输入  :无
     * 输出  :无
     * 返回  :无 
     * 调用  :内部调用 
     **********************************************************/
    void    OS_IdleTaskInit(OS_ERR  *p_err)
    {
        //初始化空闲任务计数器,设置为0
        OSIdleTaskCtr = (OS_IDLE_CTR)0;
        
        //创建空闲任务
        OSTaskCreate(
                        (OS_TCB     *)&OSIdleTaskTCB,
                        (OS_TASK_PTR )OS_IdleTask,
                        (void       *)0,
                        (CPU_STK    *)OSCfg_IdleTaskStkBasePtr,
                        (CPU_STK_SIZE)OSCfg_IdleTaskStkSize,
                        (OS_ERR     *)p_err
                    );
        
    }
    

     

  6. 实验现象:
  7. 总结:阻塞任务与空闲任务配合,榨干系统性能,永远不让CPU闲着;达到实时;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值