美文网首页
UCOSIII_多任务创建(二)

UCOSIII_多任务创建(二)

作者: 飞向深空 | 来源:发表于2020-02-29 16:58 被阅读0次

    任务调度和切换就是让就绪表中优先级最高的任务获得CPU使用权,UCOSIII是抢占式的,高优先级任务可以抢了低优先级任务的CPU使用权,任务调度由任务调度器完成,任务调度器分为:任务级,中断级调度器

    1.任务级调度器:OSSched(),不能用于中断服务函数中
    函数里有一个函数OS_TASK_SW(),这个是真正执行任务切换的宏,它把当前任务的CPU寄存器值保存在任务堆栈中,保存完当前任务的现场后将新任务的OS_TCB中保存的任务堆栈指针的值加载到CPU的堆栈指针寄存器中,新任务结束后还要把CPU寄存器值变回旧任务的。

    2.中断级调度器:OSIntEnter(),OSIntExit(),调用此函数时中断应该是关闭的
    函数里有一个函数OSIntCtxSW(),这个是真正执行任务切换的宏,进入中断时硬件自动保存现场了,将新任务的OS_TCB中保存的任务堆栈指针的值加载到CPU的堆栈指针寄存器中,新中断结束后自动恢复现场。

    3.时间片轮转调度:UCOSIII支持一个优先级下有多个任务,不过允许一个任务运行一段时间(时间片)后让出CPU使用权,让同优先级下的洗一个任务运行,这种任务调度方法就是时间片轮转调度。如果同级下第一个任务设置的时间片用完则第一个任务排到链表尾,等待下一次调度。使用OSSchedRoundRobinYield()可以放弃剩余的时间片,在同级下其它任务运行。

    通常创建多个任务,可以先在main函数中设置一个任务,然后在这个任务里创建多个任务.
    每个任务都有自己的任务函数。

    #include "system.h"
    #include "led.h"
    #include "includes.h"
    
    //任务优先级
    #define START_TASK_PRIO     3
    //任务堆栈大小    
    #define START_STK_SIZE      512
    //任务控制块
    OS_TCB StartTaskTCB;
    //任务堆栈  
    CPU_STK START_TASK_STK[START_STK_SIZE];
    //任务函数
    void start_task(void *p_arg);
    
    #define LED1_TASK_PRIO      4   
    #define LED1_STK_SIZE       128
    OS_TCB Led1TaskTCB; 
    CPU_STK LED1_TASK_STK[LED1_STK_SIZE];
    void led1_task(void *p_arg);
    
    #define LED2_TASK_PRIO      5   
    #define LED2_STK_SIZE       128
    OS_TCB Led2TaskTCB; 
    CPU_STK LED2_TASK_STK[LED2_STK_SIZE];
    void led2_task(void *p_arg);
    
    int main()
    {   
        OS_ERR err;
        LED_Init();
        OSInit(&err);       //初始化UCOSIII
        //创建开始任务
        OSTaskCreate((OS_TCB    * )&StartTaskTCB,       //任务控制块
                     (CPU_CHAR  * )"start task",        //任务名字
                     (OS_TASK_PTR )start_task,          //任务函数
                     (void      * )0,                   //传递给任务函数的参数
                     (OS_PRIO     )START_TASK_PRIO,     //任务优先级
                     (CPU_STK   * )&START_TASK_STK[0],  //任务堆栈基地址
                     (CPU_STK_SIZE)START_STK_SIZE/10,   //任务堆栈深度限位
                     (CPU_STK_SIZE)START_STK_SIZE,      //任务堆栈大小
                     (OS_MSG_QTY  )0,                   //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
                     (OS_TICK     )0,                   //当使能时间片轮转时的时间片长度,为0时为默认长度,
                     (void      * )0,                   //用户补充的存储区
                     (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项
                     (OS_ERR    * )&err);               //存放该函数错误时的返回值 
        OSStart(&err);  //开启UCOSIII
    }
    
    //开始任务函数
    void start_task(void *p_arg)
    {
        OS_ERR err;
        
        CPU_INT32U  cpu_clk_freq;
        CPU_INT32U  cnts;
        
        CPU_SR_ALLOC();
        p_arg = p_arg; //防止报错
    
        CPU_Init();
        
        cpu_clk_freq = BSP_CPU_ClkFreq();                           /* Determine SysTick reference freq.                    */
        cnts = cpu_clk_freq / (CPU_INT32U)OSCfg_TickRate_Hz;        /* Determine nbr SysTick increments                     */
        OS_CPU_SysTickInit(cnts);                                   /* Init uC/OS periodic time src (SysTick).              */
    
        Mem_Init();   //初始化内存    
        
        
    #if OS_CFG_STAT_TASK_EN > 0u
       OSStatTaskCPUUsageInit(&err);    //统计任务                
    #endif
        
    #ifdef CPU_CFG_INT_DIS_MEAS_EN      //如果使能了测量中断关闭时间
        CPU_IntDisMeasMaxCurReset();    
    #endif
        
    #if OS_CFG_SCHED_ROUND_ROBIN_EN  //当使用时间片轮转的时候
         //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms
        OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);  
    #endif      
        
        OS_CRITICAL_ENTER();    //进入临界区
        //创建LED1任务
        OSTaskCreate((OS_TCB    * )&Led1TaskTCB,        
                     (CPU_CHAR  * )"led1 task",         
                     (OS_TASK_PTR )led1_task,           
                     (void      * )0,                   
                     (OS_PRIO     )LED1_TASK_PRIO,     
                     (CPU_STK   * )&LED1_TASK_STK[0],   
                     (CPU_STK_SIZE)LED1_STK_SIZE/10,    
                     (CPU_STK_SIZE)LED1_STK_SIZE,       
                     (OS_MSG_QTY  )0,                   
                     (OS_TICK     )0,                   
                     (void      * )0,                   
                     (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                     (OS_ERR    * )&err);
    
        //创建LED2任务
        OSTaskCreate((OS_TCB    * )&Led2TaskTCB,        
                     (CPU_CHAR  * )"led2 task",         
                     (OS_TASK_PTR )led2_task,           
                     (void      * )0,                   
                     (OS_PRIO     )LED2_TASK_PRIO,     
                     (CPU_STK   * )&LED2_TASK_STK[0],   
                     (CPU_STK_SIZE)LED2_STK_SIZE/10,    
                     (CPU_STK_SIZE)LED2_STK_SIZE,       
                     (OS_MSG_QTY  )0,                   
                     (OS_TICK     )0,                   
                     (void      * )0,                   
                     (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                     (OS_ERR    * )&err);
                     
        OS_TaskSuspend((OS_TCB*)&StartTaskTCB,&err);        //挂起开始任务             
        OS_CRITICAL_EXIT(); //退出临界区
    }
    
    //led1任务函数
    void led1_task(void *p_arg)
    {
        OS_ERR err;
        p_arg = p_arg;
        while(1)
        {
            led1=!led1;
            OSTimeDlyHMSM(0,0,0,200,OS_OPT_TIME_HMSM_STRICT,&err); //延时200ms
        }
    }
    
    //led2任务函数
    void led2_task(void *p_arg)
    {
        OS_ERR err;
        p_arg = p_arg;
        while(1)
        {
            led2=!led2;
            OSTimeDlyHMSM(0,0,0,400,OS_OPT_TIME_HMSM_STRICT,&err); //延时400ms
        }
    }
    

    相关文章

      网友评论

          本文标题:UCOSIII_多任务创建(二)

          本文链接:https://www.haomeiwen.com/subject/wyvphhtx.html