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在正常执行,也就是程序设置的优先级被反转了。

 

posted @ 2019-12-11 15:59  飞起的小田  阅读(1488)  评论(0编辑  收藏  举报