zoukankan      html  css  js  c++  java
  • 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...
    ");
    /* 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!
    ");
          //获取二值信号量 xSemaphore,没获取到则一直等待
          if(osSemaphoreWait(myBinarySem01Handle, osWaitForever) == osOK)
          {
              printf("LowPriority_Task Runing
    
    ");
          }
    
          for (i=0; i<2000000; i++) { //模拟低优先级任务占用信号量
              osThreadYield();//发起任务调度
          }
          printf("LowPriority_Task Releasing semaphore!
    ");
          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
    ");
        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!
    ");
          //获取二值信号量 xSemaphore,没获取到则一直等待
          if(osSemaphoreWait(myBinarySem01Handle, osWaitForever) == osOK)
          {
              printf("HighPriority_Task Runing
    
    ");
          }
    
          printf("HighPriority_Task Releasing semaphore!
    ");
          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在正常执行,也就是程序设置的优先级被反转了。

  • 相关阅读:
    scala学习手记7
    scala学习手记6
    scala学习手记5
    scala学习手记4
    scala学习手记3
    scala学习手记2
    Scala学习手记1
    Java实现的一个小说采集程序
    Java的值传递和引用传递
    java 使用反射
  • 原文地址:https://www.cnblogs.com/tianxxl/p/12023102.html
Copyright © 2011-2022 走看看