7-FreeRTOS时间片进行任务调度
注意:
①任务切换会存在时间片开销;
FreeRTOS 支持时间片,每个优先级可以支持无限多个任务,这些任务的调度就是时间片调度;
在 FreeRTOS 中允许一个任务运行一个时间片(一个时钟节拍的长度)后让出 CPU 的使用权,让拥有同优先级的下一个任务运行, 至于下一个要运行
哪个任务? 由时间片来调度,时间片调度发生在滴答定时器的中断服务函数中 。
下面三个任务优先级相同,为N
(1)任务 3 正在运行。
(2)这时一个时钟节拍中断(滴答定时器中断)发生,任务 3 的时间片用完,但是任务 3 还没有执行完。
(3)FreeRTOS 将任务切换到任务 1,任务 1 是优先级 N 下的下一个就绪任务。
(4) 任务 1 连续运行至时间片用完。
(5) 任务 3 再次获取到 CPU 使用权,接着运行。
(6) 任务 3 运行完成, 调用任务切换函数 portYIELD()强行进行任务切换放弃剩余的时间片,从而使优先级 N 下的下一个就绪的任务运行。
(7)FreeRTOS 切换到任务 1。
(8) 任务 1 执行完其时间片。
实验需求:
①使用时间片调度的话宏 configUSE_PREEMPTION(抢占式内核或协程) 和宏 configUSE_TIME_SLICING(时间片调度使能) 必须为 1;
②将task1_task 和 task2_task的任务优先级设置为相同,都为 2;
③时间片的长度由宏 configTICK_RATE_HZ 来确定,一个时间片的长度就是滴答定时器的中断周期,设置 configTICK_RATE_HZ 10 则时间片是1/10 =100ms,那么任务一和任务二运行的时候都是占用一个100ms的时间片;
④任务一和任务二中每25ms让串口打印一次,那么每个任务在自己时间片下执行的话,至少打印4次。
代码:
//----------------------------------------任务优先级 #define START_TASK_PRIO 1 #define KEY_TASK_PRIO 2 #define TASK1_PRIO 2 #define TASK2_PRIO 2 //优先级高 //----------------------------------------任务堆栈大小 #define START_STK_SIZE 128 #define TASK1_STK_SIZE 128 #define TASK2_STK_SIZE 128 #define KEY_STK_SIZE 128 //----------------------------------------任务句柄 TaskHandle_t Task1_Handler; TaskHandle_t Task2_Handler; TaskHandle_t StartTask_Handler; TaskHandle_t KeyTask_Handler; //任务句柄 //----------------------------------------任务函数 void start_task(void *pvParameters); void task1_task(void *pvParameters); void task2_task(void *pvParameters); void key_task(void *pvParameters); //任务函数 int main(void) { BaseType_t OS; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); User_GPIO_Init(); Delay_init(); USART_Config(); OS= xTaskCreate( (TaskFunction_t ) start_task, //任务函数 (const char * ) "start_task", //任务名 (configSTACK_DEPTH_TYPE) START_STK_SIZE, //堆栈大小 (void * )NULL, //传递给任务函数的参数 (UBaseType_t ) START_TASK_PRIO, //任务优先级 (TaskHandle_t * ) &StartTask_Handler //任务句柄 ); if(OS==pdPASS) GPIO_SetBits(GPIOA, GPIO_Pin_8); vTaskStartScheduler(); //开启任务调度 } void start_task(void *pvParameters) { taskENTER_CRITICAL(); //进入临界区 //创建任务Task1 xTaskCreate((TaskFunction_t )task1_task, //任务函数 (const char* )"task1_task", //任务名称 (uint16_t )TASK1_STK_SIZE, //任务堆栈大小 (void* )NULL, (UBaseType_t )TASK1_PRIO, //任务优先级 (TaskHandle_t* )&Task1_Handler); //任务句柄 xTaskCreate((TaskFunction_t )task2_task, //任务函数 (const char* )"task2_task", //任务名称 (uint16_t )TASK2_STK_SIZE, //任务堆栈大小 (void* )NULL, (UBaseType_t )TASK2_PRIO, //任务优先级 (TaskHandle_t* )&Task2_Handler); //任务句柄 vTaskDelete(StartTask_Handler); //vTaskDelete(NULL)也可以 删除开始任务 taskEXIT_CRITICAL(); //退出临界区 } //任务1 void task1_task(void *pvParameters) { uint8_t count_num=0; while(1) { count_num++; printf("任务1已经执行:%d次\r\n",count_num); delay_xms(25); //vTaskDelay delay_xms不发生任务切换 } } //任务2 void task2_task(void *pvParameters) { uint8_t count_num1=0; while(1) { count_num1++; printf("任务2已经执行:%d次\r\n",count_num1); delay_xms(25); //configTICK_RATE_HZ 10则时间片是100ms 这里延时25ms,则每个任务基本上执行4次会切换任务 } }
执行结果:
posted on 2020-12-28 17:34 Darren_pty 阅读(2991) 评论(0) 编辑 收藏 举报