无Bitband的Cortex-M3外设寄存器RMW操作实现及LDREX/STREX疑问
微控制器外设寄存器Read/Modify/Write(RMW)操作实现方案
问题核心
在关闭UART中断使能的RMW操作中,读和修改步骤之间若中断状态标志被置位,会导致该标志被意外清除;无Bitband功能的Cortex-M3无法通过总线锁定实现安全RMW,需借助LDREX/STREX指令解决。
LDREX/STREX指令的行为
- 执行
LDREX后,内核会标记对应内存区域为“独占访问”状态。如果外设在LDREX和STREX之间主动更新了寄存器,AHB总线会检测到这个外部修改,此时执行STREX会返回1(失败),表示独占访问已被破坏,写入操作不会生效。 - 要实现外设通知总线寄存器更新的需求,需要外设硬件支持独占访问响应:当外设自身修改了被LDREX标记的寄存器时,要向AHB总线返回独占访问失败的信号,这样内核执行STREX时就能识别到冲突,返回失败状态。
安全RMW的代码实现示例
以UART中断使能寄存器(假设为UART_CR1,中断使能位为BIT5)为例,用LDREX/STREX实现安全的位清除操作:
void uart_disable_interrupt(void) { uint32_t temp; do { // 独占读取寄存器值 __LDREXW(&UART_CR1); // 清除中断使能位,保留其他位 temp = UART_CR1 & ~(1 << 5); // 尝试独占写入,返回0表示成功,1表示失败 } while (__STREXW(temp, &UART_CR1) != 0); }
这个循环会在STREX失败时重新执行RMW流程,直到成功完成,避免意外清除其他被外设更新的标志位。
注意事项
- 并非所有外设都支持独占访问响应,需要查看对应芯片的外设手册,确认目标寄存器是否能在自身修改时触发AHB总线的独占冲突信号。
- 如果外设不支持该硬件机制,LDREX/STREX可能无法检测到外设的寄存器更新,此时需要采用其他方案:比如拆分寄存器(将控制位和状态位分离到不同寄存器),或者在RMW前先保存状态位、修改后恢复,但这种软件方案存在一定风险,不如硬件支持的独占访问可靠。
内容的提问来源于stack exchange,提问作者pontakun
相关产品推荐
相关产品推荐

