在CMSIS模块中已经提供了原子操作宏,用于操作16位或32位变量,包括ATOMIC_SET_BIT、ATOMIC_CLEAR_BIT、ATOMIC_MODIFY_REG。
该功能是使用LDREX和STREX指令来实现的。可以通过对原子操作的封装实现互斥。LDREX和STREX指令是Thumb指令集提供的排他加载和排他访问指令,用以实现排他性访问。
/* Use of CMSIS compiler intrinsics for register exclusive access */
/* Atomic 32-bit register access macro to set one or several bits */
#define ATOMIC_SET_BIT(REG, BIT) \
do { \
uint32_t val; \
do { \
val = __LDREXW((__IO uint32_t *)&(REG)) | (BIT); \
} while ((__STREXW(val,(__IO uint32_t *)&(REG))) != 0U); \
} while(0)
/* Atomic 32-bit register access macro to clear one or several bits */
#define ATOMIC_CLEAR_BIT(REG, BIT) \
do { \
uint32_t val; \
do { \
val = __LDREXW((__IO uint32_t *)&(REG)) & ~(BIT); \
} while ((__STREXW(val,(__IO uint32_t *)&(REG))) != 0U); \
} while(0)
/* Atomic 32-bit register access macro to clear and set one or several bits */
#define ATOMIC_MODIFY_REG(REG, CLEARMSK, SETMASK) \
do { \
uint32_t val; \
do { \
val = (__LDREXW((__IO uint32_t *)&(REG)) & ~(CLEARMSK)) | (SETMASK); \
} while ((__STREXW(val,(__IO uint32_t *)&(REG))) != 0U); \
} while(0)
|