STM32 FreeRTOS互斥量
介绍
在嵌入式系统中,多个任务可能会同时访问共享资源(如全局变量、外设等)。如果这些任务没有正确地协调对共享资源的访问,可能会导致数据不一致或系统崩溃。FreeRTOS提供了**互斥量(Mutex)**机制,用于确保同一时间只有一个任务可以访问共享资源。
互斥量是一种特殊的二进制信号量,用于实现互斥访问。当一个任务获取了互斥量后,其他任务必须等待该互斥量被释放后才能继续执行。
互斥量的基本概念
什么是互斥量?
互斥量是一种用于保护共享资源的同步机制。它确保同一时间只有一个任务可以访问共享资源,从而避免竞争条件(Race Condition)。
互斥量的工作原理
- 创建互斥量:在使用互斥量之前,需要先创建一个互斥量对象。
- 获取互斥量:任务在访问共享资源之前,必须先获取互斥量。如果互斥量已被其他任务占用,当前任务将进入阻塞状态,直到互斥量被释放。
- 释放互斥量:任务在完成对共享资源的访问后,必须释放互斥量,以便其他任务可以获取它。
互斥量的优先级继承
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 (;;);
}
代码解释
- 创建互斥量:在
main
函数中,使用xSemaphoreCreateMutex()
创建了一个互斥量。 - 获取互斥量:在任务1和任务2中,使用
xSemaphoreTake()
获取互斥量。如果互斥量已被占用,任务将进入阻塞状态。 - 释放互斥量:在任务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和任务2以不同的频率访问共享资源,观察互斥量的效果。
- 尝试在代码中移除互斥量的使用,观察共享资源的值是否会出现不一致的情况。
- 创建一个新的任务,该任务也访问共享资源,并观察互斥量如何协调多个任务的访问。
:::note
**注意**:在实际开发中,确保在访问共享资源时始终使用互斥量,以避免潜在的竞争条件。
:::
:::tip
**提示**:在使用互斥量时,尽量避免长时间持有互斥量,以减少其他任务的等待时间。
:::
:::caution
**警告**:如果任务在持有互斥量时发生死锁(Deadlock),系统将无法继续运行。因此,在设计任务时,务必小心处理互斥量的获取和释放顺序。
:::