目录
一、定义
互斥量。什么是互斥量?FreeRTOS中的互斥量是一种特殊的二值信号量,用于实现并发编程环境中对共享资源的互斥访问。它的名称“互斥”,意味着它可以互相排斥,防止资源被多个任务同时访问,从而避免数据竞争和不一致性问题。
例如我们定义一个变量Money,那么存在两笔消费,而两笔消费肯定不能同时操作这个变量Money,防止出现问题,这与数据库中的锁的概念类似。
二、实现步骤
在FreeRTOS中,互斥量的操作通常涉及以下几个函数:
创建互斥量:使用xSemaphoreCreateMutex函数创建一个互斥量,并返回一个句柄供后续操作使用。
获取互斥量:使用xSemaphoreTake函数尝试获取互斥量。如果互斥量已被其他任务获取,则当前任务将被阻塞,直到互斥量被释放或超时。
释放互斥量:使用xSemaphoreGive函数释放互斥量,使其他任务可以获取。对于递归锁定的互斥量,每次释放操作都会减少计数器的值,直到计数器降到0时,互斥量才真正被释放。
而在STM32CUBEMX提供的库中,已经分装了上述函数,比如创建函数,STM32CUBEMX配置生成后自动创建。我们只需要掌握获取互斥量的语句osMutexAcquire和释放互斥量的语句osMutexRelease即可。
首先,打开配置好的STM32CUBEMX工程文件。配置好串口,便于输出调试信息。
添加两个任务,模拟同时访问一个变量的过程。
随后完成printf重定向和勾选MicroLib这具体我就不多说了,不是本文主要内容。
点击Mutexes,点击Add添加互斥量。
提示我们输入互斥量名称,分配方式和控制块名称。按需修改即可,此处不做赘述,没有特殊需求的话,保持默认亦可。
右上角Generate Code生成代码并打开工程。
找到freertos.c,添加一个全局变量 money。
在两个Task中分别完成程序,操作变量money。
void StartTask01(void *argument)
{
/* USER CODE BEGIN StartTask01 */
/* Infinite loop */
for(;;)
{
printf("Task1请求获取互斥量\n");
if(osMutexAcquire(myMutex01Handle,osWaitForever)== osOK )
{
printf("Task1获取互斥量成功\n");
money+=2;
osDelay(2000);//拖延一会时间
printf("Task1释放互斥量\n");
osMutexRelease(myMutex01Handle);
}
else
printf("Task1获取互斥量失败\n");
osDelay(1000);
}
/* USER CODE END StartTask01 */
}
void StartTask02(void *argument)
{
/* USER CODE BEGIN StartTask02 */
/* Infinite loop */
for(;;)
{
osDelay(1000);
printf("Task2请求获取互斥量\n");
if(osMutexAcquire(myMutex01Handle,osWaitForever)== osOK )
{
printf("Task2获取互斥量成功\n");
money--;
osDelay(1000);//拖延一会时间
printf("Task2释放互斥量\n");
osMutexRelease(myMutex01Handle);
}
else
printf("Task2获取互斥量失败\n");
}
/* USER CODE END StartTask02 */
}
三、效果展示
我们不必在意money的值如何,只关注输出信息。
不难看出,当Task1没有释放互斥量的时候,Task2的获取互斥量语句是处于阻塞状态(本文获取函数的超时时间参数被设置为一直等待),或等超时时间到后返回超时状态。
基于此,本文提到的互斥量基本功能已经实现了。