MCU编程中的临界资源及临界区

在MCU(微控制器)编程中,临界资源临界区是处理并发操作(如多任务、中断与主程序交互)时的核心概念,直接影响系统的稳定性和数据安全性。以下是更深入的解析:

一、临界资源(Critical Resource)

定义 :指被多个执行实体(如任务、中断服务程序ISR)共享,且其操作需要保持原子性(不可分割)的资源。

核心特点

  • 共享性:至少被两个及以上执行实体访问
  • 敏感性:非原子操作可能导致数据错误或系统异常

常见类型

  1. 软件资源:全局变量、静态变量、数据缓冲区、链表/队列等数据结构
  2. 硬件资源:外设寄存器(如UART数据寄存器)、I/O端口、定时器计数器
  3. 总线资源:I2C、SPI等共享总线,同一时间只能有一个设备占用

问题示例

两个任务同时操作全局变量count

  • 任务A读取count=5,准备执行count++(计划结果6)
  • 任务B在任务A写入前读取count=5,也执行count++
  • 最终count变为6(正确应为7),导致数据错误

二、临界区(Critical Section)

定义 :访问或操作临界资源的那段代码。需要保证互斥性------同一时间只能有一个执行实体进入并执行。

临界区的边界

  • 进入(Entry):获取资源访问权限的时刻
  • 退出(Exit):释放资源访问权限的时刻

示例

c 复制代码
// 临界资源:全局计数器
uint16_t system_counter = 0;

// 任务中的临界区
void task_update_counter(void) {
    while(1) {
        // 临界区开始
        system_counter += 1;  // 非原子操作(读-改-写)
        // 临界区结束
        vTaskDelay(10);
    }
}

// 中断中的临界区
void TIM2_IRQHandler(void) {
    if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
        // 临界区开始
        system_counter += 10;  // 同样需要保护
        // 临界区结束
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    }
}

三、临界区保护机制

根据应用场景(有无RTOS、中断参与等),常用以下保护方法:

1. 中断开关(最基础方法)

原理:通过禁用全局中断,防止ISR打断当前临界区操作。

STM32示例

c 复制代码
// 进入临界区
uint32_t primask = __get_PRIMASK();  // 保存中断状态
__disable_irq();                     // 禁用全局中断

// 临界区操作
system_counter += 1;

// 退出临界区
__set_PRIMASK(primask);              // 恢复中断状态

注意

  • 禁用时间必须尽可能短,避免影响中断响应
  • 适用于单任务+中断的简单系统
2. RTOS临界区API

在多任务系统中,RTOS提供专用接口保护临界区(如FreeRTOS):

c 复制代码
// 任务级临界区
taskENTER_CRITICAL();       // 进入临界区(禁用部分中断)
system_counter += 1;
taskEXIT_CRITICAL();        // 退出临界区(恢复中断)

// 中断级临界区
UBaseType_t uxSavedInterruptStatus;
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();  // 进入
system_counter += 10;
taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);       // 退出

优势

  • 仅禁用必要的中断(根据RTOS配置的中断优先级)
  • 平衡安全性和系统响应速度
3. 互斥锁(Mutex)

适用于多任务间的临界区保护(无中断参与):

c 复制代码
SemaphoreHandle_t xMutex;  // 定义互斥锁

// 任务1
void vTask1(void *pvParam) {
    while(1) {
        xSemaphoreTake(xMutex, portMAX_DELAY);  // 获取锁
        // 临界区操作
        system_counter += 1;
        xSemaphoreGive(xMutex);                 // 释放锁
        vTaskDelay(10);
    }
}

// 任务2(类似操作)

特点

  • 任务获取不到锁时会阻塞等待
  • 支持优先级继承(避免优先级反转)

四、最佳实践

  1. 最小化原则:临界区代码尽可能短,减少资源独占时间
  2. 避免嵌套:嵌套临界区可能导致死锁或中断长时间禁用
  3. 分层保护
    • 中断与任务共享:用中断开关或RTOS中断级API
    • 任务间共享:用互斥锁或任务级临界区API
  4. 原子操作优先:对简单变量(如32位以内),优先使用CPU原子指令

通过合理设计临界区保护机制,可以有效避免并发访问导致的数据不一致问题,确保MCU系统稳定运行。

相关推荐
周周记笔记3 分钟前
【元器件专题】用阻抗等效分析法来分析开关电路
单片机·嵌入式硬件
leoFY12315 分钟前
STM32H750配置LAN PHY芯片LAN8742
网络·stm32·嵌入式硬件
iCxhust16 分钟前
如何利用iret修改cs ip
汇编·单片机·嵌入式硬件·微机原理·8088单板机
m0_377108141 小时前
stm32平衡车
stm32·单片机·嵌入式硬件
小+不通文墨2 小时前
把树莓派外接的DHT11接收的温湿度发送到emqx上
经验分享·笔记·嵌入式硬件·学习·树莓派
Deitymoon3 小时前
FreeRTOS——列表与列表项
stm32·单片机·嵌入式硬件
总结所学3 小时前
电路定理 叠加定理 基尔霍夫定律
单片机·嵌入式硬件
雪度娃娃6 小时前
存储器层次结构——随机访问存储器
单片机·嵌入式硬件·计算机组成原理
少年潜行7 小时前
ESP01S使用笔记05--ESP01S 进行 MQTT 通信 发送 JSON 字符串遇到的问题
单片机
项目題供诗8 小时前
STM32-PWM驱动LED呼吸灯&PWM驱动直流电机(十三)
stm32·单片机·嵌入式硬件