[APM32F4] 原子操作

[复制链接]
160|3
幻影书记 发表于 2025-9-24 09:40 | 显示全部楼层 |阅读模式
, se, ic, bi,

在CMSIS模块中已经提供了原子操作宏,用于操作16位或32位变量,包括ATOMIC_SET_BIT、ATOMIC_CLEAR_BIT、ATOMIC_MODIFY_REG。

该功能是使用LDREX和STREX指令来实现的。可以通过对原子操作的封装实现互斥。LDREX和STREX指令是Thumb指令集提供的排他加载和排他访问指令,用以实现排他性访问。

我以APM32F407为例分享一下源代码:

  1.     /* Use of CMSIS compiler intrinsics for register exclusive access */  
  2.     /* Atomic 32-bit register access macro to set one or several bits */  
  3.     #define ATOMIC_SET_BIT(REG, BIT)                             \  
  4.       do {                                                       \  
  5.         uint32_t val;                                            \  
  6.         do {                                                     \  
  7.           val = __LDREXW((__IO uint32_t *)&(REG)) | (BIT);       \  
  8.         } while ((__STREXW(val,(__IO uint32_t *)&(REG))) != 0U); \  
  9.       } while(0)  
  10.       
  11.     /* Atomic 32-bit register access macro to clear one or several bits */  
  12.     #define ATOMIC_CLEAR_BIT(REG, BIT)                           \  
  13.       do {                                                       \  
  14.         uint32_t val;                                            \  
  15.         do {                                                     \  
  16.           val = __LDREXW((__IO uint32_t *)&(REG)) & ~(BIT);      \  
  17.         } while ((__STREXW(val,(__IO uint32_t *)&(REG))) != 0U); \  
  18.       } while(0)  
  19.       
  20.     /* Atomic 32-bit register access macro to clear and set one or several bits */  
  21.     #define ATOMIC_MODIFY_REG(REG, CLEARMSK, SETMASK)                          \  
  22.       do {                                                                     \  
  23.         uint32_t val;                                                          \  
  24.         do {                                                                   \  
  25.           val = (__LDREXW((__IO uint32_t *)&(REG)) & ~(CLEARMSK)) | (SETMASK); \  
  26.         } while ((__STREXW(val,(__IO uint32_t *)&(REG))) != 0U);               \  
  27.       } while(0)  




雾里闲逛 发表于 2025-9-24 20:08 | 显示全部楼层
很少使用原子操作。
都是在状态机里面完成。
原子操作太费神了
夜幕叙事曲 发表于 2025-10-4 10:09 | 显示全部楼层
以前使用原子操作是关闭全部中断来处理的
涡流远见者 发表于 2025-10-5 09:11 | 显示全部楼层
FreeRTOS里面中断临界区如何实现的啊
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

60

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部