跳到主要内容

STM32 FreeRTOS互斥量

介绍

在嵌入式系统中,多个任务可能会同时访问共享资源(如全局变量、外设等)。如果这些任务没有正确地协调对共享资源的访问,可能会导致数据不一致或系统崩溃。FreeRTOS提供了**互斥量(Mutex)**机制,用于确保同一时间只有一个任务可以访问共享资源。

互斥量是一种特殊的二进制信号量,用于实现互斥访问。当一个任务获取了互斥量后,其他任务必须等待该互斥量被释放后才能继续执行。

互斥量的基本概念

什么是互斥量?

互斥量是一种用于保护共享资源的同步机制。它确保同一时间只有一个任务可以访问共享资源,从而避免竞争条件(Race Condition)。

互斥量的工作原理

  1. 创建互斥量:在使用互斥量之前,需要先创建一个互斥量对象。
  2. 获取互斥量:任务在访问共享资源之前,必须先获取互斥量。如果互斥量已被其他任务占用,当前任务将进入阻塞状态,直到互斥量被释放。
  3. 释放互斥量:任务在完成对共享资源的访问后,必须释放互斥量,以便其他任务可以获取它。

互斥量的优先级继承

FreeRTOS的互斥量支持优先级继承机制。当一个高优先级任务等待一个被低优先级任务占用的互斥量时,低优先级任务的优先级会被临时提升到与高优先级任务相同的级别,以减少高优先级任务的等待时间。

使用互斥量的代码示例

以下是一个简单的代码示例,展示了如何在STM32中使用FreeRTOS的互斥量来保护共享资源。

c
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

// 定义共享资源
int sharedResource = 0;

// 定义互斥量
SemaphoreHandle_t xMutex;

// 任务1:增加共享资源的值
void vTask1(void *pvParameters) {
while (1) {
// 获取互斥量
if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
// 访问共享资源
sharedResource++;
printf("Task 1: sharedResource = %d\n", sharedResource);

// 释放互斥量
xSemaphoreGive(xMutex);
}
vTaskDelay(pdMS_TO_TICKS(1000)); // 延迟1秒
}
}

// 任务2:减少共享资源的值
void vTask2(void *pvParameters) {
while (1) {
// 获取互斥量
if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
// 访问共享资源
sharedResource--;
printf("Task 2: sharedResource = %d\n", sharedResource);

// 释放互斥量
xSemaphoreGive(xMutex);
}
vTaskDelay(pdMS_TO_TICKS(1000)); // 延迟1秒
}
}

int main(void) {
// 创建互斥量
xMutex = xSemaphoreCreateMutex();

// 创建任务1
xTaskCreate(vTask1, "Task 1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);

// 创建任务2
xTaskCreate(vTask2, "Task 2", configMINIMAL_STACK_SIZE, NULL, 1, NULL);

// 启动调度器
vTaskStartScheduler();

// 程序不会执行到这里
for (;;);
}

代码解释

  1. 创建互斥量:在main函数中,使用xSemaphoreCreateMutex()创建了一个互斥量。
  2. 获取互斥量:在任务1和任务2中,使用xSemaphoreTake()获取互斥量。如果互斥量已被占用,任务将进入阻塞状态。
  3. 释放互斥量:在任务1和任务2中,使用xSemaphoreGive()释放互斥量,以便其他任务可以获取它。

输出示例

Task 1: sharedResource = 1
Task 2: sharedResource = 0
Task 1: sharedResource = 1
Task 2: sharedResource = 0
...

实际应用场景

场景1:共享外设访问

在嵌入式系统中,多个任务可能需要访问同一个外设(如UART、SPI等)。使用互斥量可以确保同一时间只有一个任务可以访问该外设,从而避免数据冲突。

场景2:共享内存访问

在多任务系统中,多个任务可能需要访问共享内存区域。使用互斥量可以确保同一时间只有一个任务可以访问该内存区域,从而避免数据不一致。

总结

互斥量是FreeRTOS中用于保护共享资源的重要机制。通过使用互斥量,可以避免任务间的竞争条件,确保系统的稳定性和可靠性。在实际应用中,互斥量常用于保护共享外设、共享内存等资源。

附加资源

练习

  1. 修改上述代码,使任务1和任务2以不同的频率访问共享资源,观察互斥量的效果。
  2. 尝试在代码中移除互斥量的使用,观察共享资源的值是否会出现不一致的情况。
  3. 创建一个新的任务,该任务也访问共享资源,并观察互斥量如何协调多个任务的访问。

:::note
**注意**:在实际开发中,确保在访问共享资源时始终使用互斥量,以避免潜在的竞争条件。
:::

:::tip
**提示**:在使用互斥量时,尽量避免长时间持有互斥量,以减少其他任务的等待时间。
:::

:::caution
**警告**:如果任务在持有互斥量时发生死锁(Deadlock),系统将无法继续运行。因此,在设计任务时,务必小心处理互斥量的获取和释放顺序。
:::