1、互斥量
互斥量主要用于保护共享资源的访问,确保在同一时刻只有一个任务可以访问该资源。
互斥性:当一个任务获取了一个互斥量后,其他任务将无法再获取同一个互斥量,直到原始任务释放该互斥量。
优先级继承:为了防止优先级反转问题,FreeRTOS的互斥量支持优先级继承机制。当一个高优先级任务被低优先级任务阻塞时,低优先级任务会暂时提升自己的优先级,以尽快释放互斥量,让高优先级任务继续执行。
递归锁定:互斥量支持递归锁定,即获取互斥量的任务可以在未释放的情况下再次获取同一个互斥量,直到所有获取操作都被相应次数的释放操作所抵消。
操作需求:建立三个不同优先级的任务,演示一下优先级翻转,接着通过互斥量进行解决。
2、相关API函数
注意:互斥信号量不能用于中断服务函数。
xSemaphoreCreateMutex() //使用动态方法创建互斥信号量。
xSemaphoreCreateMutexStatic() //使用静态方法创建互斥信号量。
SemaphoreHandle_t xSemaphoreCreateMutex( void )
参数:
无
返回值:
成功,返回对应互斥量的句柄;
失败,返回 NULL 。
3、STM32CubeMX配置
新建三个任务分别为Task_H、Task_M、Task_L优先级分别设置为osPriorityAboveNormal、osPriorityNormal、osPriorityBelowNormal。
互斥量配置:Mutexes -> Add -> ok
此时生成文件会报错,内存不足,将内存变成5000
4、优先级翻转测试
4.1 Task_H
void StartTask_H(void *argument)
{
/* USER CODE BEGIN StartTask_H */
/* Infinite loop */
for(;;)
{
xSemaphoreTake(myBinarySem01Handle, portMAX_DELAY);
printf("TaskH:在房间睡觉!~~~\r\n");
HAL_Delay(1000);
printf("TaskH:睡醒了!~~~\r\n");
xSemaphoreGive(myBinarySem01Handle);
osDelay(1000);
}
/* USER CODE END StartTask_H */
}
4.2 Task_M
void StartTask_M(void *argument)
{
/* USER CODE BEGIN StartTask_M */
/* Infinite loop */
for(;;)
{
printf("TaskM:打王者呢!~~\r\n");
osDelay(1000);
}
/* USER CODE END StartTask_M */
}
4.3 Task_L
void StartTask_L(void *argument)
{
/* USER CODE BEGIN StartTask_L */
/* Infinite loop */
for(;;)
{
xSemaphoreTake(myBinarySem01Handle, portMAX_DELAY);
printf("TaskL:在房间睡觉呢!!!\r\n");
HAL_Delay(3000);
printf("TaskL:睡醒了,真舒服~~~\r\n");
xSemaphoreGive(myBinarySem01Handle);
osDelay(1000);
}
/* USER CODE END StartTask_L */
}
测试结果分析:
需要注意:HAL_Delay函数使用系统时钟来进行延时,并且在延时期间会阻塞整个处理器,也就是说,它会使处理器暂时停止执行其他任务和代码。
5、通过互斥量解决优先级翻转测试
将Task_H、Task_L二值信号量句柄通过互斥量句柄进行替换:
5.1 Task_H
void StartTask_H(void *argument)
{
/* USER CODE BEGIN StartTask_H */
/* Infinite loop */
for(;;)
{
xSemaphoreTake(myMutex01Handle, portMAX_DELAY);
printf("TaskH:在房间睡觉!~~~\r\n");
HAL_Delay(1000);
printf("TaskH:睡醒了!~~~\r\n");
xSemaphoreGive(myMutex01Handle);
osDelay(1000);
}
/* USER CODE END StartTask_H */
}
5.2 Task_L
void StartTask_L(void *argument)
{
/* USER CODE BEGIN StartTask_L */
/* Infinite loop */
for(;;)
{
xSemaphoreTake(myMutex01Handle, portMAX_DELAY);
printf("TaskL:在房间睡觉呢!!!\r\n");
HAL_Delay(3000);
printf("TaskL:睡醒了,真舒服~~~\r\n");
xSemaphoreGive(myMutex01Handle);
osDelay(1000);
}
/* USER CODE END StartTask_L */
}
5.3 测试
通过互斥量解决优先级翻转!
上文如有错误恳请各位大佬指正!