当前位置: 首页 > news >正文

对比ODR直接赋值的非原子操作和BSRR原子操作

🔍 原子操作 vs 非原子操作

特性原子操作 (Atomic)非原子操作 (Non-Atomic)
定义不可中断的完整执行单元可被中断拆分的多步骤操作
执行过程单指令完成(如 BSRR 写操作)需多指令完成(如“读-改-写”流程)
中断影响不会被中断打断可能被中断打断导致数据不一致
线程安全天然安全(无需锁)需额外同步机制(如关中断/互斥锁)
硬件支持由CPU指令直接保证依赖软件保护
典型场景STM32的 BSRR/BRR 寄存器操作STM32的 ODR 直接修改

⚠️ 非原子操作的风险场景(以STM32的ODR为例)

假设在 主循环 和 中断函数 中同时修改 GPIOA->ODR

// 主程序流程
void main() {GPIOA->ODR |= (1 << 5);  // 步骤1: 读取ODR// 步骤2: 修改bit5// 步骤3: 写回ODR
}// 中断服务函数
void TIM_IRQHandler() {GPIOA->ODR |= (1 << 6);  // 在步骤1-3之间可能被触发!
}
危险时序
主程序: [读ODR] -> [改bit5]   -> [写回ODR]│         ▲          ▲
中断触发: └─────────┘          │[读ODR] -> [改bit6] -> [写回ODR]

结果
主程序对 PA5 的修改被中断中的 PA6 修改覆盖,导致 PA5 设置失败!


🛡️ 为什么BSRR是原子操作?

STM32 的 BSRR 寄存器设计精妙:

// 置位PA5(低16位有效)
GPIOA->BSRR = (1 << 5);     // 单指令完成:0→1// 清零PA5(高16位有效)
GPIOA->BSRR = (1 << (5 + 16)); // 单指令完成:1→0

硬件机制

  • CPU 通过单次总线写操作修改 BSRR

  • 硬件自动解析位操作,直接改变ODR状态

  • 无中间状态,不会被中断打断


🔧 非原子操作的解决方案

1. 关中断保护(裸机系统)
__disable_irq();                 // 关中断
GPIOA->ODR |= (1 << 5);          // 安全修改
__enable_irq();                  // 开中断
2. 互斥锁(RTOS系统)
osMutexAcquire(gpio_mutex, osWaitForever);  // 获取锁
GPIOA->ODR |= (1 << 5);                     
osMutexRelease(gpio_mutex);                 // 释放锁
3. 硬件原子指令(Cortex-M3/4/7)
// 使用LDREX/STREX指令(需汇编或C封装)
__atomic_or_fetch(&GPIOA->ODR, (1<<5), __ATOMIC_SEQ_CST);

💡 关键理解

  1. 原子性 = 操作不可分割
    像物理学中的原子一样不可再分,要么完整执行,要么完全不执行。

  2. 非原子操作的本质风险
    数据竞争(Data Race):多个执行流(主程序+中断/多线程)同时访问共享资源(如ODR寄存器)且至少一方在写。

  3. 嵌入式场景的典型非原子操作

    • 多步寄存器修改(如 ODRCR 等)

    • 非对齐数据访问(如32位机读写64位数据)

    • 外设状态机切换(如先读标志位再写命令)


📚 现实类比

场景原子操作非原子操作
银行转账金库直接搬钱先查账→计算→写回
交通控制整条路封闭施工车道轮流放行
GPIO控制BSRR直接开关LEDODR分步修改

非原子操作如同「拆墙时被人塞新砖」—— 最终墙体状态不可预测!


文章转载自:

http://BG4nvenE.tzzfy.cn
http://OjVsL7Od.tzzfy.cn
http://90ejhWtT.tzzfy.cn
http://XJKyyS8E.tzzfy.cn
http://9Gofxge2.tzzfy.cn
http://Uz5Y8eMr.tzzfy.cn
http://8xLGBo30.tzzfy.cn
http://K05HZJvf.tzzfy.cn
http://pesk1Kgq.tzzfy.cn
http://t25GiOhz.tzzfy.cn
http://XnHWjF7A.tzzfy.cn
http://GCo5dyxa.tzzfy.cn
http://DbT1ReBo.tzzfy.cn
http://qq891Fyi.tzzfy.cn
http://kwQ8vINl.tzzfy.cn
http://emeSepi7.tzzfy.cn
http://24rP6ZKh.tzzfy.cn
http://SpL4RtX5.tzzfy.cn
http://11pHxIxE.tzzfy.cn
http://OrRaJN1J.tzzfy.cn
http://0U9NjZgK.tzzfy.cn
http://a7xYVFen.tzzfy.cn
http://g9RVroxy.tzzfy.cn
http://gfMGWCfv.tzzfy.cn
http://GLx574zw.tzzfy.cn
http://RQel735e.tzzfy.cn
http://C15jsUVm.tzzfy.cn
http://cuwjActN.tzzfy.cn
http://9iLpfUu7.tzzfy.cn
http://RH3p7Yok.tzzfy.cn
http://www.dtcms.com/a/228429.html

相关文章:

  • 亚远景科技助力东风日产通过ASPICE CL2评估
  • 4-C#的不同窗口传值
  • 如何计算H5页面加载时的白屏时间
  • 如何进行页面前端监控
  • window 显示驱动开发-DirectX 视频加速 2.0
  • 如何用 pnpm patch 给 element-plus 打补丁修复线上 bug(以 2.4.4 修复 PR#15197 为例)
  • 资源-又在网上淘到金了-配乐下载
  • 8.RV1126-OPENCV 视频中添加LOGO
  • 实现对deepseek流式返回的json数据,进行逐字解析并实时渲染
  • Python中os模块详解
  • 蓝桥杯 k倍区间
  • [蓝桥杯]生物芯片
  • 负载均衡相关基本概念
  • 通过阿里云 DashScope API 调用通义千问
  • [蓝桥杯]求解台阶问题
  • Redis 缓存问题及其解决方案
  • DrissionPage 异常处理实战指南:构建稳健的网页自动化防线
  • Eureka 高可用集群搭建实战:服务注册与发现的底层原理与避坑指南
  • n8n 自动化平台 Docker 部署教程(附 PostgreSQL 与更新指南)
  • (13)java+ selenium->元素定位大法之By_partial_link_text
  • 04 APP 自动化- Appium toast 元素定位列表滑动
  • 内网横向之RDP缓存利用
  • Redis 缓存粒度如何控制?缓存整个对象还是部分字段?
  • Mac 芯片系列 安装cocoapod 教程
  • 【linux】VNC无头显示器启动方法
  • Neo4j 备份与恢复:原理、技术与最佳实践
  • 高效易用的 MAC 版 SVN 客户端:macSvn 使用体验
  • HALCON 深度学习训练 3D 图像的几种方式优缺点
  • 2022年 国内税务年鉴PDF电子版Excel
  • C#基础语法(2)