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次會切換任務
     }
         
 }

 

執行結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM