新唐MCU技术
直播中

张丽

8年用户 1581经验值
私信 关注
[问答]

在 ISR 发生之前,当 SFRS 寄存器的值发生变化时,如何避免意外结果?

在 ISR 发生之前,当 SFRS 寄存器的值发生变化时,如何避免意外结果?

回帖(1)

chumowei

2025-8-27 17:57:14

在嵌入式系统中,特殊功能寄存器(SFR)的值在中断服务程序(ISR)发生前被修改时,可能会因非原子操作时序冲突导致意外结果。以下是系统化的解决方案:




核心原则:确保关键操作的原子性


当主程序修改SFR且可能被ISR访问时,需通过以下方法保证操作的不可中断性:


1. 临时禁用中断



  • 操作步骤

    • 关闭全局中断(如8051的EA=0)。

    • 修改SFR值。

    • 重新开启中断(EA=1)。


  • 代码示例
     EA = 0;          // 禁用全局中断
    SFR_REG = new_value;  // 安全修改SFR
    EA = 1;          // 启用全局中断

  • 优点:简单通用,适用于所有架构。

  • 注意:禁用中断时间应尽量短(通常小于10μs),避免影响实时性。


2. 利用硬件原子操作



  • 适用场景

    • 若SFR支持位寻址(如8051中的P0^1),直接使用位操作指令(如SETB/CLR)。

    • 现代MCU(如ARM Cortex-M)提供原子位操作指令(bit-band)。


  • 代码示例(8051)
     SETB SFR_BIT   ; 原子操作,无需禁用中断


3. 缓存副本法(Shadow Register)



  • 适用场景

    • SFR需多次修改(如配置序列)。

    • ISR需读取SFR的稳定值。


  • 操作步骤

    1. 主程序修改SFR的缓存副本(如全局变量shadow_SFR)。

    2. 安全时机(如空闲时)将副本值写入实际SFR。



  • 代码示例


     uint8_t shadow_SFR;  // SFR的缓存副本

    void main() {
         shadow_SFR = new_value;  // 先修改副本
         if (!in_isr) {           // 确认不在ISR中
             SFR_REG = shadow_SFR; // 安全写入SFR
         }
    }

    void ISR() {
         uint8_t safe_val = shadow_SFR;  // ISR使用副本值
    }



4. 状态标志同步



  • 适用场景

    • SFR的修改需与ISR状态同步(如通信协议)。


  • 操作步骤

    1. 主程序设置标志(如SFR_UPDATE_FLAG)。

    2. ISR检测标志,仅在标志未置位时使用SFR。



  • 代码示例


     volatile bool update_flag = false;

    void main() {
         SFR_REG = new_value;
         update_flag = true;     // 通知ISR值已更新
    }

    void ISR() {
         if (update_flag) {
             // 安全使用SFR_REG
             update_flag = false;  // 清除标志
         }
    }





架构特例优化



  • 8051系列

    • 优先使用位寻址操作(如TR0=1)避免禁用中断。

    • 关键字节操作(如TMOD)必须用CLR EA/SETB EA包裹。


  • ARM Cortex-M

    • 使用__disable_irq()__enable_irq()内核函数。

    • 利用硬件位带(Bit-Band)实现原子位修改。


  • AVR

    • cli()sei()控制全局中断。





设计要点总结



  1. 原子性优先:单指令操作 > 禁用中断 > 软件同步。

  2. 时序关键区最小化:禁用中断时间务必极短。

  3. 避免冗余操作:如ISR不读取的SFR无需保护。

  4. 测试验证:通过逻辑分析仪或调试器确认时序无冲突。



核心准则

任何可能被ISR访问的共享SFR资源,其修改操作必须通过原子化同步机制保护,确保主程序与ISR的视图一致性。



通过上述方法,可从根本上避免因SFR异步修改导致的寄存器损坏、信号毛刺或逻辑错误。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分