stm32中优先使用原子操作的具体实现方式

在STM32中,优先使用的原子操作主要包括‌位带操作 ‌、‌LDREX/STREX指令 ‌以及‌CMSIS提供的原子操作宏‌,以下是具体实现方式‌12:


1. ‌**位带操作(Bit-Banding)**‌

通过硬件直接对单个比特进行原子读写,适用于GPIO或寄存器位操作‌1:

cpp 复制代码
#define BITBAND(addr, bitnum) ((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5) + (bitnum << 2))
#define MEM_ADDR(addr)  *((volatile uint32_t *)(addr))

// 原子设置GPIOB的PIN5为高电平
MEM_ADDR(BITBAND(&GPIOB->ODR, 5)) = 1;

2. ‌LDREX/STREX指令‌

基于Cortex-M的独占访问指令,适用于共享变量修改‌23:

cpp 复制代码
volatile uint32_t shared_var = 0;

void atomic_increment(void) {
    uint32_t val;
    do {
        val = __LDREXW(&shared_var);  // 独占加载
        val += 1;
    } while (__STREXW(val, &shared_var));  // 独占存储,失败则重试
    __CLREX();  // 清除独占标记
}

3. ‌CMSIS原子操作宏‌

CMSIS库提供的封装宏,如ATOMIC_SET_BIT和ATOMIC_MODIFY_REG‌24:

cpp 复制代码
#include "core_cm4.h"

// 原子设置USART1的CR1寄存器第3位
ATOMIC_SET_BIT(USART1->CR1, USART_CR1_TXEIE);

// 原子修改TIM2的CCER寄存器
ATOMIC_MODIFY_REG(TIM2->CCER, TIM_CCER_CC1E, 0x1);
cpp 复制代码
#include "core_cm4.h"

// 原子设置USART1的CR1寄存器位
ATOMIC_SET_BIT(USART1->CR1, USART_CR1_TXEIE);

// 原子修改变量
uint32_t val = 0;
ATOMIC_MODIFY_REG(val, 0xFF, 0x55);  // 将低8位改为0x55

4. ‌GPIO的BSRR寄存器‌

通过置位/复位寄存器实现GPIO的原子操作‌1:

cpp 复制代码
// 原子设置PB5高电平、PB6低电平
GPIOB->BSRR = (1 << 5) | (1 << (6 + 16));

‌临界区保护

HAL库提供__disable_irq()和__enable_irq()函数,可临时禁用中断实现原子性‌

cpp 复制代码
volatile uint32_t counter = 0;

void atomic_increment(void) {
    __disable_irq();  // 进入临界区
    counter++;        // 原子操作
    __enable_irq();   // 退出临界区
}

代码实现示例

以下是一个综合示例,展示原子操作在多线程环境中的应用‌35:

atomic_ops.c

已完成

此代码演示了计数器原子递增和GPIO标志位原子设置,适用于中断与主程序共享数据的场景‌1

cpp 复制代码
#include "stm32f4xx.h"
#include "core_cm4.h"

volatile uint32_t counter = 0;

// 使用LDREX/STREX原子递增
void atomic_counter_inc(void) {
    uint32_t val;
    do {
        val = __LDREXW(&counter);
        val++;
    } while (__STREXW(val, &counter));
    __CLREX();
}

// 使用CMSIS宏原子设置标志位
void atomic_flag_set(volatile uint32_t *reg, uint32_t bit) {
    ATOMIC_SET_BIT(*reg, bit);
}

int main(void) {
    atomic_counter_inc();
    atomic_flag_set(&GPIOA->ODR, 5);
    return 0;
}
cpp 复制代码
#include "stm32f4xx.h"
#include "core_cm4.h"

volatile uint32_t global_var = 0;  // 待修改的全局变量

void atomic_write(uint32_t new_value) {
    uint32_t current_val;
    do {
        current_val = __LDREXW(&global_var);  // 独占加载当前值
    } while (__STREXW(new_value, &global_var));  // 尝试写入新值,失败则重试
    __CLREX();  // 清除独占标记(防止后续LDREX受影响)
}

int main(void) {
    atomic_write(0x12345678);  // 原子写入新值
    while(1);
}
相关推荐
szxinmai主板定制专家10 小时前
X86 工控机 vs RK3588 异构主控:AMR 控制器 BOM、散热、长期运维对比
运维·stm32·单片机·嵌入式硬件·fpga开发·am62x
HQB202612 小时前
屹晶微电子 EG1130|2‑24V 输入 / 最高 28V 输出 内置 MOS 异步升压 DC‑DC|SOT23‑6|摄像头 / 车充 / 电池充电电源
嵌入式硬件·硬件工程
泛凡(Linyongui)14 小时前
基于 CW32L010 的智能厨卫调温旋钮方案--低成本 EC21 编码旋钮全解析
单片机·嵌入式硬件·c#
十年磨一剑~14 小时前
Linux 内核中断处理机制与软硬件协同流程
linux·嵌入式硬件
糖糖单片机设计15 小时前
基于单片机的热水器节能控制系统
单片机·嵌入式硬件
数字新视界16 小时前
数字孪生技术赋能智能化转型与创新实践
嵌入式硬件·物联网·系统架构·机房管理·动力与环境监控系统
HQB202616 小时前
屹晶微电子 EG1195|10‑120V/10A+ 外置 MOS 异步降压控制器|ESOP‑8|电动车转换器 / 快充 / 工业电源
嵌入式硬件·硬件工程
不悔哥17 小时前
开源LineageOS:旧手机刷上开源系统
嵌入式硬件·智能手机·开源
服务器硬件项目经理18 小时前
《超节点修仙录》· 第一卷·炼气期【第04话】 超节点 vs 普通服务器——不就是多插了几张卡吗?
运维·服务器·人工智能·嵌入式硬件·深度学习·机器学习
一次调频AGCAVC18 小时前
一次调频系统控制柜的组成及一次调频装置主机功能详述
人工智能·嵌入式硬件