学习FreeRTOS(互斥量)
1. 互斥量
1.1 什么是互斥量?
在多数情况下,互斥型信号量和二值型信号量非常相似,但是从功能上二值型信号量用于同步,而互斥型信 号量用于资源保护。
互斥型信号量和二值型信号量还有一个最大的区别,互斥型信号量可以有效解决优先级反转现象。
1.2 什么是优先级翻转?

以上图为例,系统中有3个不同优先级的任务H/M/L,最高优先级任务H和最低优先级任务L通过信号量机 制,共享资源。目前任务L占有资源,锁定了信号量,Task H运行后将被阻塞,直到Task L释放信号量后, Task H才能够退出阻塞状态继续运行。但是Task H在等待Task L释放信号量的过程中,中等优先级任务M抢 占了任务L,从而延迟了信号量的释放时间,导致Task H阻塞了更长时间,这种现象称为优先级倒置或反 转。
优先级继承:当一个互斥信号量正在被一个低优先级的任务持有时, 如果此时有个高优先级的任务也尝试获 取这个互斥信号量,那么这个高优先级的任务就会被阻塞。 不过这个高优先级的任务会将低优先级任务的优 先级提升到与自己相同的优先级。
优先级继承并不能完全的消除优先级翻转的问题,它只是尽可能的降低优先级翻转带来的影响。
2. 互斥量相关 API 函数
互斥信号量不能用于中断服务函数中!

SemaphoreHandle_t xSemaphoreCreateMutex( void )参数:
无
返回值:
成功,返回对应互斥量的句柄;
失败,返回 NULL 。
3.实操
实验需求
1. 演示优先级翻转
2. 使用互斥量优化优先级翻转问题
演示优先级翻转
cubeMX配置




代码实现:
/* USER CODE BEGIN Header_StarTaskH */
/*** @brief  Function implementing the TaskH thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StarTaskH */
void StarTaskH(void const * argument)
{/* USER CODE BEGIN StarTaskH *//* Infinite loop */for(;;){xSemaphoreTake(myBinarySemHandle ,portMAX_DELAY); printf("TaskH:我开始占用CPU资源中....\r\n");HAL_Delay(1000);printf("TaskH:工作完毕...释放信号值\r\n");xSemaphoreGive(myBinarySemHandle );osDelay(1000);}/* USER CODE END StarTaskH */
}/* USER CODE BEGIN Header_StartTaskM */
/**
* @brief Function implementing the TaskM thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTaskM */
void StartTaskM(void const * argument)
{/* USER CODE BEGIN StartTaskM *//* Infinite loop */for(;;){printf("TaskM:占用CPU资源中....\r\n");osDelay(1000);}/* USER CODE END StartTaskM */
}/* USER CODE BEGIN Header_StartTaskL */
/**
* @brief Function implementing the TaskL thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTaskL */
void StartTaskL(void const * argument)
{/* USER CODE BEGIN StartTaskL *//* Infinite loop */for(;;){xSemaphoreTake(myBinarySemHandle ,portMAX_DELAY); printf("TaskL:我开始占用CPU资源中....\r\n");HAL_Delay(3000);printf("TaskL:工作完毕...释放信号值\r\n");xSemaphoreGive(myBinarySemHandle);osDelay(1000);}/* USER CODE END StartTaskL */
}实验现象:

在TaskL占用二值信号量的时候,TaskM可以占用CPU资源,TaskL释放二值信号量,TaskH才得以获取二值信号量占用CPU资源。
使用互斥量优化优先级翻转问题
cubeMX配置
任务优先级同上,将二值信号量删除,改为互斥量

代码实现:
/* USER CODE BEGIN Header_StarTaskH */
/*** @brief  Function implementing the TaskH thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StarTaskH */
void StarTaskH(void const * argument)
{/* USER CODE BEGIN StarTaskH *//* Infinite loop */for(;;){xSemaphoreTake(myMutexHandle ,portMAX_DELAY); printf("TaskH:我开始占用CPU资源中....\r\n");HAL_Delay(1000);printf("TaskH:工作完毕...释放信号值\r\n");xSemaphoreGive(myMutexHandle );osDelay(1000);}/* USER CODE END StarTaskH */
}/* USER CODE BEGIN Header_StartTaskM */
/**
* @brief Function implementing the TaskM thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTaskM */
void StartTaskM(void const * argument)
{/* USER CODE BEGIN StartTaskM *//* Infinite loop */for(;;){printf("TaskM:占用CPU资源中....\r\n");osDelay(1000);}/* USER CODE END StartTaskM */
}/* USER CODE BEGIN Header_StartTaskL */
/**
* @brief Function implementing the TaskL thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTaskL */
void StartTaskL(void const * argument)
{/* USER CODE BEGIN StartTaskL *//* Infinite loop */for(;;){xSemaphoreTake(myMutexHandle ,portMAX_DELAY); printf("TaskL:我开始占用CPU资源中....\r\n");HAL_Delay(3000);printf("TaskL:工作完毕...释放信号值\r\n");xSemaphoreGive(myMutexHandle );osDelay(1000);}/* USER CODE END StartTaskL */
}实验现象:

当TaskL获取到互斥值的时候,其他任务不能干预TaskL的执行,释放互斥值,才能执行其他任务。
