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