Premise:
Time slice rotation method: mainly used for process scheduling in time-sharing system. In order to realize rotation scheduling, the system arranges all ready processes into a queue first process according to the principle of first in first out, and lets it run a time slice on the CPU. Time slice is a small time unit, usually in the order of 10~100ms. When the process runs out of the time slice allocated to it, the system timer sends a clock interrupt, and the scheduler stops the process and puts it at the end of the ready queue; Then, put it at the end of the ready queue; Then, the CPU is assigned to the queue head process of the ready queue, and it is also allowed to run a time slice, and so on.
Implementation idea: the basic idea of time slice rotation algorithm is that the system arranges all ready processes into a queue according to the principle of first come, first serve algorithm. Each time, the system allocates the processor to the first process in the queue and lets it execute a time slice. When the execution time slice is used up, the timer sends a clock interrupt request. According to this request, the scheduler stops the process, sends it to the end of the ready queue, and then assigns the processor to the new queue head process in the ready queue. At the same time, it also executes a time slice.
1. UCOIII time slice rotation scheduling
The time slice rotation scheduler is used for time slice rotation scheduling. It is a function OS_SchedRoundRobin(), which is controlled by OSTimeTick or OS_IntQTask() is called, and the function is in the file OS_ Defined in core. C.
2.1. Oschedroundrobincfg() function:
If we want to use ucosiiii time slice Round scheduling, we should not only use macro OS_ CFG_ SCHED_ ROUND_ ROBIN_ When en is set to 1, you also need to call the function oschedroundrobincfg(), and the function prototype is as follows
void OSSchedRoundRobinCfg (CPU_BOOLEAN en, OS_TICK dflt_time_quanta, OS_ERR *p_err)
When time slice rotation is used, the time slice rotation scheduling function is enabled. The length of time slice is 1 system clock beat, i.e. 1*5=5ms
#if OS_CFG_SCHED_ROUND_ROBIN_EN / / when using time slice rotation //Enable the time slice rotation scheduling function. The time slice length is 1 system clock beat, i.e. 1*5=5ms OSSchedRoundRobinCfg(DEF_ENABLED,1,&err); #endif
2.2. Oschedroundrobin yield() function:
When a task wants to give up this time slice, it can call this function. The function prototype is as follows:
void OSSchedRoundRobinYield (OS_ERR *p_err)
An example of the use of the function osshedroundrobin yield() is as follows:
void Task(void *p_arg) { OS_RR err; while(1) { ...... OSSchedRoundRobinYiled(&err); ... - } }
3. UCOSIII time slice rotation scheduling
In this experiment, three tasks are designed. Task A is used to create other tasks and delete itself after creation. Task B and task C have the same priority. These two tasks are scheduled by time slice rotation. Both tasks print some data through the serial port, and then display the running times of the task on the LCD. The operation of time slice rotation scheduling can be observed through the information output from the serial port.
Experimental steps:
- Set macro OS_CFG_SCHED_ROUND_ROBIN_EN = 1
- Call the function oschedroundrobin cfg() to start the time slice rotation scheduling function and set the time slice length
- Write task function
#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "lcd.h" #include "includes.h" /************************************************ ALIENTEK UCOS experiment of elite STM32 development board /Example 6-3 UCOSIII time slice rotation scheduling Technical support: www.openedv.com Taobao store: http://eboard.taobao.com Pay attention to wechat public platform wechat: "punctual atom", and obtain STM32 data for free. Guangzhou Xingyi Electronic Technology Co., Ltd Author: punctual atom @ ALIENTEK ************************************************/ //The following priority user programs in UCOSIII cannot be used. ALIENTEK //These priorities are assigned to five system internal tasks of UCOSIII //Priority 0: interrupt service management task OS_IntQTask() //Priority 1: clock beat 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() //Technical support: www.openedv.com //Taobao store: http://eboard.taobao.com //Guangzhou Xingyi Electronic Technology Co., Ltd //Author: punctual atom @ ALIENTEK //Task priority #define START_TASK_PRIO 3 //Task stack size #define START_STK_SIZE 128 //Task control block OS_TCB StartTaskTCB; //task stack CPU_STK START_TASK_STK[START_STK_SIZE]; //Task function void start_task(void *p_arg); //Task priority #define TASK1_TASK_PRIO 4 //Task stack size #define TASK1_STK_SIZE 128 //Task control block OS_TCB Task1_TaskTCB; //task stack CPU_STK TASK1_TASK_STK[TASK1_STK_SIZE]; void task1_task(void *p_arg); //Task priority #define TASK2_TASK_PRIO 4 //Task stack size #define TASK2_STK_SIZE 128 //Task control block OS_TCB Task2_TaskTCB; //task stack CPU_STK TASK2_TASK_STK[TASK2_STK_SIZE]; //Task function void task2_task(void *p_arg); //Main function int main(void) { OS_ERR err; CPU_SR_ALLOC(); delay_init(); //Clock initialization NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//Interrupt packet configuration uart_init(115200); //Serial port initialization LED_Init(); //LED initialization LCD_Init(); //LCD initialization POINT_COLOR = RED; LCD_ShowString(30,10,200,16,16,"ALIENTEK STM32F1"); LCD_ShowString(30,30,200,16,16,"UCOSIII Examp 6-3"); LCD_ShowString(30,50,200,16,16,"Task Round-robin"); LCD_ShowString(30,70,200,16,16,"ATOM@ALIENTEK"); LCD_ShowString(30,90,200,16,16,"2015/3/19"); OSInit(&err); //Initialize UCOSIII OS_CRITICAL_ENTER();//Enter critical zone //Create start task OSTaskCreate((OS_TCB * )&StartTaskTCB, //Task control block (CPU_CHAR * )"start task", //Task name (OS_TASK_PTR )start_task, //Task function (void * )0, //Parameters passed to the task function (OS_PRIO )START_TASK_PRIO, //Task priority (CPU_STK * )&START_TASK_STK[0], //Task stack base address (CPU_STK_SIZE)START_STK_SIZE/10, //Task stack depth limit (CPU_STK_SIZE)START_STK_SIZE, //Task stack size (OS_MSG_QTY )0, //The maximum number of messages that the task internal message queue can receive. When it is 0, it is prohibited to receive messages (OS_TICK )0, //When the time slice rotation is enabled, the time slice length is 0, which is the default length, (void * )0, //User supplementary storage (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //Task options (OS_ERR * )&err); //Store the return value when the function is wrong OS_CRITICAL_EXIT(); //Exit critical zone OSStart(&err); //Open UCOSIII } //Start task function void start_task(void *p_arg) { OS_ERR err; CPU_SR_ALLOC(); p_arg = p_arg; CPU_Init(); #if OS_CFG_STAT_TASK_EN > 0u OSStatTaskCPUUsageInit(&err); //Statistical tasks #endif #ifdef CPU_CFG_INT_DIS_MEAS_EN // If enabled, measure the interrupt off time CPU_IntDisMeasMaxCurReset(); #endif #if OS_CFG_SCHED_ROUND_ROBIN_EN / / when using time slice rotation //Enable the time slice rotation scheduling function. The time slice length is 1 system clock beat, i.e. 1*5=5ms OSSchedRoundRobinCfg(DEF_ENABLED,1,&err); #endif OS_CRITICAL_ENTER(); //Enter critical zone //Create TASK1 task OSTaskCreate((OS_TCB * )&Task1_TaskTCB, (CPU_CHAR * )"Task1 task", (OS_TASK_PTR )task1_task, (void * )0, (OS_PRIO )TASK1_TASK_PRIO, (CPU_STK * )&TASK1_TASK_STK[0], (CPU_STK_SIZE)TASK1_STK_SIZE/10, (CPU_STK_SIZE)TASK1_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )2, //2 time slices, i.e. 2*5=10ms (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); //Create TASK2 task OSTaskCreate((OS_TCB * )&Task2_TaskTCB, (CPU_CHAR * )"task2 task", (OS_TASK_PTR )task2_task, (void * )0, (OS_PRIO )TASK2_TASK_PRIO, (CPU_STK * )&TASK2_TASK_STK[0], (CPU_STK_SIZE)TASK2_STK_SIZE/10, (CPU_STK_SIZE)TASK2_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )2, //2 time slices, i.e. 2*5=10ms (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); OS_CRITICAL_EXIT(); //Exit critical zone OSTaskDel((OS_TCB*)0,&err); //Delete start_task task itself } //task1 task function void task1_task(void *p_arg) { u8 i,task1_num=0; OS_ERR err; p_arg = p_arg; POINT_COLOR = RED; LCD_ShowString(30,130,110,16,16,"Task1 Run:000"); POINT_COLOR = BLUE; while(1) { task1_num++; //Task 1 execution times plus 1 pay attention to Task1_ When num1 is added to 255, it will be cleared!! LCD_ShowxNum(110,130,task1_num,3,16,0x80); //Displays the number of task executions for(i=0;i<5;i++) printf("Task1:01234\r\n"); LED0 = ~LED0; OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //Delay 1s } } //task2 task function void task2_task(void *p_arg) { u8 i,task2_num=0; OS_ERR err; p_arg = p_arg; POINT_COLOR = RED; LCD_ShowString(30,150,110,16,16,"Task2 Run:000"); POINT_COLOR = BLUE; while(1) { task2_num++; //Task 2 execution times plus 1 pay attention to Task1_ When num2 is added to 255, it will be cleared!! LCD_ShowxNum(110,150,task2_num,3,16,0x80); //Displays the number of task executions for(i=0;i<5;i++) printf("Task2:56789\r\n"); LED1 = ~LED1; OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //Delay 1s } }