STM32CubeIDE+FreeRTOS模擬優先級反轉實驗


模擬優先級翻轉實驗是在 FreeRTOS 中創建了三個任務與一個二值信號量, 任務分別是高優先級任務,中優先級任務,低優先級任務, 用於模擬產生優先級翻轉。 低優先級任務在獲取信號量的時候,被中優先級打斷,中優先級的任務執行時間較長,因為低優先級還未釋放信號量,那么高優先級任務就無法取得信號量繼續運行,此時就發生了優先級翻轉。

創建工程RTOS_BinarySem,

配置HCLK,使用內部晶振,頻率為180MHZ(根據板子設置)

 

 

將SYS中時基源(Timebase Source)改為除SysTick之外的任意定時器即可,如:

 配置FreeRTOS,使用CMSIS_V1,先定義一個二值信號量。

 

定義3個任務,

 

    

 

 

 

Ctrl + S生成代碼

修改代碼,

1,在main.h中添加

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */

2,在mian.c中添加

/* USER CODE BEGIN PFP */
int _write(int file , char *ptr,int len)
{
    int i = 0;
    for(i = 0;i<len;i++)
        ITM_SendChar((*ptr++));
    return len;
}
/* USER CODE END PFP */

...
...
...

/* USER CODE BEGIN 2 */
printf("starting...\n");
/* USER CODE END 2 */

3,在main.c中修改3個任務入口函數的內容

 

 

/* USER CODE BEGIN Header_StartLowPriorityTask */
/**
  * @brief  Function implementing the LowPriority_Tas thread.
  * @param  argument: Not used 
  * @retval None
  */
/* USER CODE END Header_StartLowPriorityTask */
void StartLowPriorityTask(void const * argument)
{
  /* USER CODE BEGIN 5 */
    static uint32_t i;
  /* Infinite loop */
  for(;;)
  {
      printf("LowPriority_Task gets binarySem!\n");
      //獲取二值信號量 xSemaphore,沒獲取到則一直等待
      if(osSemaphoreWait(myBinarySem01Handle, osWaitForever) == osOK)
      {
          printf("LowPriority_Task Runing\n\n");
      }

      for (i=0; i<2000000; i++) { //模擬低優先級任務占用信號量
          osThreadYield();//發起任務調度
      }
      printf("LowPriority_Task Releasing semaphore!\r\n");
      osSemaphoreRelease( myBinarySem01Handle );//給出二值信號量
      osDelay(500);
  }
  /* USER CODE END 5 */ 
}
/* USER CODE BEGIN Header_StartMidPriorityTask */
/**
* @brief Function implementing the MidPriority_Tas thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartMidPriorityTask */
void StartMidPriorityTask(void const * argument)
{
  /* USER CODE BEGIN StartMidPriorityTask */
  /* Infinite loop */
  for(;;)
  {
    printf("MidPriority_Task Runing\n");
    osDelay(500);
  }
  /* USER CODE END StartMidPriorityTask */
}
/* USER CODE BEGIN Header_StartHighPriority_Task */
/**
* @brief Function implementing the HighPriority_Ta thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartHighPriority_Task */
void StartHighPriority_Task(void const * argument)
{
  /* USER CODE BEGIN StartHighPriority_Task */
  /* Infinite loop */
  for(;;)
  {
      printf("HighPriority_Task gets binarySem!\n");
      //獲取二值信號量 xSemaphore,沒獲取到則一直等待
      if(osSemaphoreWait(myBinarySem01Handle, osWaitForever) == osOK)
      {
          printf("HighPriority_Task Runing\n\n");
      }

      printf("HighPriority_Task Releasing semaphore!\r\n");
      osSemaphoreRelease( myBinarySem01Handle );//給出二值信號量
      osDelay(500);
  }
  /* USER CODE END StartHighPriority_Task */
}

修改完畢后點擊 小錘子 構建工程,然后點擊Debug,按如下步驟配置ITM調試

 

 

 

 全速運行之前一定要先點擊SWV ITM data Console 頁面中的紅色圓圈

 

現象:

 

 分析:

3個任務,LowPriority_Task,的優先級為 osPriorityLow ,任務先獲取二值信號量,獲取成功后先不釋放,進行任務調度2000000次,然后釋放二值信號量。

MidPriority_Task的優先級為 osPriorityNormal ,任務每個500ms輸出提示信息MidPriority_Task Runing。

HighPriority_Task的優先級為  osPriorityHigh,任務先獲取二值信號量,獲取成功后輸出提示信息,然后立即釋放二值信號量。

程序運行,先執行優先級最高的HighPriority_Task的,然后執行優先級第二高的MidPriority_Task,最后執行優先級最低的LowPriority_Task,在LowPriority_Task中,任務先獲取二值信號量,獲取成功后先不釋放,進行任務調度,調度到優先級最高的HighPriority_Task,HighPriority_Task任務獲取二值信號量,因為此時二值信號量被占用,所以會獲取失敗,進入阻塞態,執行MidPriority_Task,直到LowPriority_Task任務釋放二值信號量執行完畢。因此就出現了一個奇怪的現象,優先級最高的HighPriority_Task要等到LowPriority_Task執行完畢后才能執行,而此時優先級較低的MidPriority_Task和LowPriority_Task在正常執行,也就是程序設置的優先級被反轉了。

 


免責聲明!

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



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