uCOSIII real-time operating system 5 task API (time slice rotation API scheduling)

Time slice rotation scheduling

Time slice rotation method: mainly used for process scheduling in time-sharing systems. In order to implement round-robin scheduling, the system arranges all ready processes into the first process of a queue according to the first-in, first-out principle, and allows the CPU to run for a time slice. A time slice is a small unit of time, usually on the order of 5~10ms. When the process uses up the time slice allocated to it, the system’s timer issues a clock interrupt, and the scheduler stops the running of the process, puts it at the end of the ready queue, and allocates the CPU to the head process of the ready queue. Similarly Also let it run for a time slice, and so on.

If you want to use UCOSIII’s time slice round-robin scheduling, you must not only set the macro OS_CFG_SCHED_ROUND_ROBIN_EN to 1, but also call the function OSSchedRoundRobinCfg().

Location:

The function prototype is as follows:

void OSSchedRoundRobinCfg (CPU_BOOLEAN en,
                            OS_TICK dflt_time_quanta,
                            OS_ERR *p_err)

When using time slice rotation, enable the time slice rotation scheduling function, and the time slice length is 1 system clock beat, that is, 1*5=5ms

#if OS_CFG_SCHED_ROUND_ROBIN_EN //When using time slice rotation
//Enable time slice rotation scheduling function, the time slice length is 1 system clock beat, that is, 1*5=5ms
OSSchedRoundRobinCfg(DEF_ENABLED,1, & amp;err);
#endif

When the task wants to give up this time slice, it can call the OSSchedRoundRobinYield() function. The function prototype is as follows:

Task setting key points:

The following three factors should be considered at the beginning of task design:

  1. Interrupt service function
  2. Common tasks
  3. idle task

Interrupt service function:

Operations that suspend the current task cannot be used in the interrupt service function, and any calls that will block the running API function interface (delay) are not allowed. The interrupt service function is best to be concise and small, fast in and fast out. Generally, in the interrupt service function, we only mark the event and then notify the task to let the corresponding task area handle it. Because the priority of the interrupt service function is higher than any priority task, if the interrupt task processing time is too long, the entire task of the system will be unable to process. normal operation.

Common tasks:

Infinite loops are not allowed in tasks (the infinite loop here refers to the task loop body without blocking mechanism). If a task only has a ready state but no blocking state, it will inevitably affect the execution of other low-priority tasks. , so when designing tasks, you should ensure that when the task is inactive, the task can enter the blocking state to hand over the CPU usage rights. (OSTimeDlyHMSM() delay function)

Idle tasks:

Users can hook their own functions on idle tasks through idle task hooks. Usually this idle task hook can complete some additional special functions, such as indication of system running status, system power saving mode, etc. The idle task is the only task that is not allowed to block, because μC/OS needs to ensure that the system always has a runnable task.

Time slice rotation experiment:

Experimental requirements:

  1. The main function creates task 1 and is responsible for creating two tasks 2 and 3 with the same priority and then deletes itself after executing the task function.
  2. Task 2 is responsible for printing abcde every 1 s, and task 3 prints fghij every 1 s.
  3. Observe the time slice rotation by printing values through the serial port.

This experiment inherits the project from the previous blog http://t.csdnimg.cn/RRZqJ and modifies the previous project:

Task 1:

After the error code variable is declared, add the following code and execute it when the macro OS_CFG_SCHED_ROUND_ROBIN_EN is set to 1 and call the function OSSchedRoundRobinCfg() to implement time slice rotation scheduling.

#if OS_CFG_SCHED_ROUND_ROBIN_EN
OSSchedRoundRobinCfg(DEF_ENABLED,1, & err2_3);
#endif

Change the time slice length of the created task to an appropriate time. I changed it to 3. Time slice: 3*5=15ms.

Experimental phenomena:

Experiment source code:

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "includes.h"

//The following priority user programs cannot be used in UCOSIII, ALIENTEK
//Assign these priorities to the 5 system internal tasks of UCOSIII
//Priority 0: Interrupt service service management task OS_IntQTask()
//Priority 1: Clock task OS_TickTask()
//Priority 2: Scheduled task OS_TmrTask()
//Priority OS_CFG_PRIO_MAX-2: Statistics task OS_StatTask()
//Priority OS_CFG_PRIO_MAX-1: Idle task OS_IdleTask()

//Create task 1
//Define task priority
#define TASK_1_PRIO 3
//Define task control block
OS_TCB TASK_1_TCB;
//Define task stack size
#define TASK_1_STK_SIZE 128
//Define task stack
CPU_STK TASK_1_STK[TASK_1_STK_SIZE];
//Define task function
void TASK_1(void *arg);

//Create task 2
//Define task priority
#define TASK_2_PRIO 4
//Define task control block
OS_TCB TASK_2_TCB;
//Define task stack size
#define TASK_2_STK_SIZE 128
//Define task stack
CPU_STK TASK_2_STK[TASK_2_STK_SIZE];
//Define task function
void TASK_2(void *arg);

//Create task 3
//Define task priority
#define TASK_3_PRIO 4
//Define task control block
OS_TCB TASK_3_TCB;
//Define task stack size
#define TASK_3_STK_SIZE 128
//Define task stack
CPU_STK TASK_3_STK[TASK_3_STK_SIZE];
//Define task function
void TASK_3(void *arg);


int main(void)
{
OS_ERR err1;//Error code variable
CPU_SR_ALLOC();//Define the variables needed for the critical section
\t
//Hardware initialization
delay_init(); //Delay initialization
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //Interrupt group configuration
uart_init(115200); //Serial port baud rate setting
\t
OSInit( & amp;err1);//Initialize UCOSIII
OS_CRITICAL_ENTER();//Enter critical section code
\t
//Create start task 1
OSTaskCreate((OS_TCB * ) & TASK_1_TCB, //task control block
(CPU_CHAR * )"main TASK1", //task name
                 (OS_TASK_PTR )TASK_1, //task function
                 (void * )0, //Parameters passed to the task function
                 (OS_PRIO )TASK_1_PRIO, //Task priority
                 (CPU_STK * ) & amp;TASK_1_STK[0], //task stack base address
                 (CPU_STK_SIZE)TASK_1_STK_SIZE/10, //Task stack depth limit
                 (CPU_STK_SIZE)TASK_1_STK_SIZE, //task stack size
                 (OS_MSG_QTY )0, //The maximum number of messages that the task's internal message queue can receive. When it is 0, it is forbidden to receive messages.
                 (OS_TICK )0, //The length of the time slice when time slice rotation is enabled. When it is 0, it is the default length.
                 (void * )0, //User-supplemented storage area
                 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //task options
                 (OS_ERR * ) & amp;err1); //Storage the return value of this function when there is an error
\t
OS_CRITICAL_EXIT();//Exit critical section code
OSStart( & amp;err1);//Start UCOSIII

while(1);
}

void TASK_1(void *arg)
{
OS_ERR err2_3;//Error code variable
CPU_SR_ALLOC();//Define the variables needed for the critical section
#if OS_CFG_SCHED_ROUND_ROBIN_EN
OSSchedRoundRobinCfg(DEF_ENABLED,1, & err2_3);
#endif
\t
OS_CRITICAL_ENTER();//Enter critical section code
\t
//Create start task 2
OSTaskCreate((OS_TCB * ) & TASK_2_TCB, //task control block
(CPU_CHAR * )"main TASK2", //Task name
                 (OS_TASK_PTR )TASK_2, //task function
                 (void * )0, //Parameters passed to the task function
                 (OS_PRIO )TASK_2_PRIO, //Task priority
                 (CPU_STK * ) & amp;TASK_2_STK[0], //task stack base address
                 (CPU_STK_SIZE)TASK_2_STK_SIZE/10, //Task stack depth limit
                 (CPU_STK_SIZE)TASK_2_STK_SIZE, //task stack size
                 (OS_MSG_QTY )0, //The maximum number of messages that the task's internal message queue can receive. When it is 0, it is forbidden to receive messages.
                 (OS_TICK )3, //The time slice length when time slice rotation is enabled, when it is 0, it is the default length.
                 (void * )0, //User-supplemented storage area
                 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //task options
                 (OS_ERR * ) & amp;err2_3); //Storage the return value of this function when there is an error
//Create start task 3
OSTaskCreate((OS_TCB * ) & TASK_3_TCB, //task control block
(CPU_CHAR * )"main TASK3", //task name
                 (OS_TASK_PTR )TASK_3, //task function
                 (void * )0, //Parameters passed to the task function
                 (OS_PRIO )TASK_3_PRIO, //Task priority
                 (CPU_STK * ) & amp;TASK_3_STK[0], //task stack base address
                 (CPU_STK_SIZE)TASK_3_STK_SIZE/10, //Task stack depth limit
                 (CPU_STK_SIZE)TASK_3_STK_SIZE, //task stack size
                 (OS_MSG_QTY )0, //The maximum number of messages that the task's internal message queue can receive. When it is 0, it is forbidden to receive messages.
                 (OS_TICK )3, //The time slice length when time slice rotation is enabled, when it is 0, it is the default length.
                 (void * )0, //User-supplemented storage area
                 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //task options
                 (OS_ERR * ) & amp;err2_3); //Storage the return value of this function when there is an error
\t\t\t\t\t\t\t\t 
OS_CRITICAL_EXIT();//Exit critical section code
\t
//Task 1 deletes itself after executing the function
OSTaskDel((OS_TCB *)0, & err2_3);
}

//Task 2 body
void TASK_2(void *arg)
{
int num = 0; //Number of runs of task 2
OS_ERR err2;
while(1)
{
num + + ;
printf("Number of runs of task 2: %d\r\\
",num);
printf("abcde\r\\
");
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT, & err2);//Delay 1S
}
}

//Task 3 body
void TASK_3(void *arg)
{
int num = 0; //Number of runs of task 2
OS_ERR err3;
while(1)
{
num + + ;
printf("Number of runs of task 3: %d\r\\
",num);
printf("fghij\r\\
");
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT, & err3);//Delay 500ms
}
}