Scheduling and switching of tasks in UCOIII

Publisher:SparklingStarLatest update time:2019-04-25 Source: eefocusKeywords:UCOIII  task  switch Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

1. UCOSIII Task Scheduling


1. Preemptive task scheduling


Definition: Task scheduling is to terminate the currently running task and execute other tasks instead (UCOSIII is a preemptive kernel, so when a high-priority task is ready and task scheduling occurs at this time, the high-priority task will obtain the right to use the CPU)


   Task scheduling in UCOSIII is done by a task scheduler. There are two types of task schedulers: task-level scheduler and interrupt-level scheduler.


    The task-level scheduler is the function OSSched().


//OSSched is a task-level scheduler. It cannot be used in an interrupt service function.

void  OSSched (void)

{

    CPU_SR_ALLOC();

    

    //Judge whether OSSched is used in the interrupt service function

    if (OSIntNestingCtr > (OS_NESTING_CTR)0) 

    {             

        return;                                             

    }

    

    //Is the scheduler locked?

    if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0)

     {       

        return;                                             

    }

 

    CPU_INT_DIS(); //Disable interrupt

    OSPrioHighRdy = OS_PrioGetHighest(); //Get the highest priority task in the task ready list

    //Get the task to be run next time the task is switched, OSTCBHighRdyPtr points to the OS_TCB of the task to be switched                

    OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;

    

    // Determine whether the task to be run is a running task, if it is, there is no need to switch

    if (OSTCBHighRdyPtr == OSTCBCurPtr) 

    {                   

        CPU_INT_EN();                                       

        return;

    }

 

#if OS_CFG_TASK_PROFILE_EN > 0u

    OSTCBHighRdyPtr->CtxSwCtr++;                        

#endif

    OSTaskCtxSwCtr++;                                      

 

#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)

    OS_TLS_TaskSw();

#endif

 

    OS_TASK_SW(); //Execute task switching                                     

    CPU_INT_EN(); //Enable interrupt

}

    The interrupt level scheduler is the function OSIntExit(), which uses interrupt level task scheduling when exiting the external interrupt service function.


void  OSIntExit (void)

{

    CPU_SR_ALLOC();

 

    if (OSRunning != OS_STATE_OS_RUNNING) //Judge UCOSIII, jump out if not running

    {                 

        return;                                             

    }

 

    CPU_INT_DIS();

    if (OSIntNestingCtr == (OS_NESTING_CTR)0) //OSIntNestingCtr interrupt nesting counter, check whether it is 0, and ensure that it will not be equal to a negative number after calling OSIntExit() when exiting

    {             

        CPU_INT_EN(); //Record interrupt nesting times

        return;

    }

    OSIntNestingCtr--;//3

    if (OSIntNestingCtr > (OS_NESTING_CTR)0)//>0 means there are other interrupts and no task switching is done

     {              

        CPU_INT_EN();                                       

        return;

    }

 

    if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) //Scheduler locked

    {        

        CPU_INT_EN();                                       

        return;

    }

 

    OSPrioHighRdy = OS_PrioGetHighest(); //Get the control block of the highest priority task              

    OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;     

    if (OSTCBHighRdyPtr == OSTCBCurPtr) 

    {                   

        CPU_INT_EN();                                      

        return;

    }

 

#if OS_CFG_TASK_PROFILE_EN > 0u

    OSTCBHighRdyPtr->CtxSwCtr++;                            

#endif

    OSTaskCtxSwCtr++;                                       

 

#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)

    OS_TLS_TaskSw();

#endif

 

    OSIntCtxSw(); //Call interrupt-level task switching function                                          

    CPU_INT_EN(); //Enable interrupt

}

2. Task scheduling point (emphasized in red)


(1) Release the semaphore or send a message, or configure the corresponding parameters to prevent task scheduling.


(2) Use the delay function OSTimeDly() or OSTimeDlyHMSM().


(3) The thing the task is waiting for has not happened yet (waiting for semaphore, message queue, etc.).


(4) Task cancellation waiting.


(5) Create a task.


(6) Delete the task.


(7) Delete a kernel object.


(8) A task changes its own priority or the priority of other tasks.


(9) The task suspends itself by calling OSTaskSuspend().


(10) Task: Unsuspend a suspended task.


(11) Exit all nested interrupts.


(12) Unlock the scheduler through OSSchedUnlock().


(13) The task calls OSSchedRoundRobinYield() to give up its execution time slice.


(14) The user calls OSSched().


3. Lock and unlock the scheduler:


Sometimes we don't want task scheduling to occur, because there are always some code execution processes that cannot be interrupted. In this case, we can use the function OSSchedLock() to lock the scheduler. When we want to resume task scheduling, we can use the function OSSchedUnlock() to unlock the locked task scheduler.


4. Time slice round-robin scheduling


UCOSIII allows multiple tasks under one priority level. Each task can execute for a specified time (time slice) and then it is the turn of the next task. This process is called time slice round-robin scheduling. When a task does not want to run, it can give up its time slice.


The time slice round-robin scheduler is: OS_SchedRoundRobin().


Time slice round-robin scheduling example:

2. UCOSIII Task Switching


1. What is task switching?


When UCOSIII needs to switch to another task, it will save the scene of the current task to the stack of the current task, mainly the CPU register value, and then restore the new scene and execute the new task. This process is called task switching.


There are two types of task switching: task-level switching and interrupt-level switching.


The task-level switching function is: OSCtxSw().


The interrupt level switching function is: OSIntCtxSw().


2. Task control block structure


The task control block is a data structure used to record task-related information. Each task must have its own task control block. The task control block is created by the user. The following code creates a task control block:


OS_TCB StartTaskTCB; //Create a task control block


OS_TCB is a structure that describes the task control block. Users cannot directly access the member variables in the task control block, let alone change them.


OS_TCB is a structure, some of its members are determined by conditional compilation.


Keywords:UCOIII  task  switch Reference address:Scheduling and switching of tasks in UCOIII

Previous article:UCOSIII task creation, deletion, suspension and resumption
Next article:UCOSIII system initialization and startup

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号