This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430F5529: 关于暂时关闭中断的疑问

Part Number: MSP430F5529


由于软件模拟串口通信等种种原因,需要在一段代码的执行过程中暂时关闭中断,此前我使用如下代码

uint16_t x = _get_interrupt_state();
_disable_interrupts();

_set_interrupt_state(x);

在我的理解里,相当于如下指令

PUSH SR
BIC  #GIE, SR

POP  SR

但是我有了新的疑虑:

在入栈 SR 到复位 GIE 之间是否有可能触发中断?

如果可能触发中断,那么中断中对 SR 的修改将在执行完毕后对 SR 恢复而丢弃,但是此时中断已经被消耗,显然这个行为不符合预期。

我的疑虑存在吗,如果存在,应该如何正确地暂时关闭中断呢?

  • 在我的理解里,相当于如下指令

    我在CCS内使用反汇编看了一下

    在入栈 SR 到复位 GIE 之间是否有可能触发中断?

    您可以看一下下面链接的讨论

    https://e2echina.ti.com/support/microcontrollers/msp430/f/msp-low-power-microcontroller-forum/79006/msp430-dint-eint-msp430f169  

    以及

    https://www.ti.com/lit/ug/slau387f/slau387f.pdf 

  • 您提供的链接似乎讨论了DINT/EINT到后一个指令之间的状态,然而我的疑问应该归结为:是否有一个原子性的操作可以保存同时关闭中断位,这应该是DINT之前一个指令到其之间的状态,毫无疑问中断仍然是开着的,但是我不希望在保存之后触发中断。

    倘若解决不了这个问题,诸如

    _bic_SR_register_on_exit(GIE);

    的中断操作将可能失效。

    这是因为

    EINT
    ;GIE = 1
    
    PUSH SR
    ;<-----------------isr
    ;GIE = 0
    DINT
    NOP
    ;......
    POP SR
    NOP
    ;GIE = 1
    
    ------------------------------
    __interrupt void isr(void){
        _bic_SR_register_on_exit(GIE);
    }

    我希望得到一个正确放心的暂时性的关闭操作,我应该如何编写代码呢?
  • DINT和EINT分别指关和开所有中断。DINT就是关闭了所有的中断,您可以将需要保护的代码放置到DINT和EINT之间。

  • 但是这样做的话,原本关闭的中断就将会打开

    void txd(void){
        _disable_interrupts();
        // ...
        _enable_interrupts();
        // <---- 触发其他中断
    }
    
    __interrupt void isr(void){
        txd();
    }

    我知道这是一种不好的编码习惯,但是我确实觉得它有出现在中断中的必要性。

    因为我无法合适地(保存中断状态地)暂时关闭中断,我不得不为这些代码添加诸如此类的包装

    void do_some(void){
        // ...
    }
    
    void do_some_DINT(void){
        _disable_interrupts();
        do_some();
        _enable_interrupts();
    }

    然后让调用者思考应该调用哪个,这是在不是一个好消息,我不觉得这是一种合适的解决方法

  • 但是这样做的话,原本关闭的中断就将会打开

    我理解的是您需要有一段代码执行,而在执行该段代码时不能有中断,所以我认为将需要保护的代码放置到DINT和EINT之间是可以的

    我是没有正确理解您的意思吗?若是,请说明一下

  • 是的,我的需求是

    1. 执行一段代码时不能发生中断

    2. 执行完毕后全局中断开关与执行前一致

    您可以理解为这段代码还需要在中断里调用而不会发生中断嵌套

  • MSP430默认的是关闭中断嵌套的,进入中断服务程序时即关闭了总中断,除非你在一个中断程序中再次开总中断EINT。

    也就是说,当进入中断服务程序时,只要不在中断服务程序中再次开中断,则总中断是关闭的,此时后面到来的中断不管是比当前中断的优先级高还是低都不执行;

  • 只要不在中断服务程序中再次开中断

    因此

    将需要保护的代码放置到DINT和EINT之间

    如果在中断中调用这段代码最终将会开启中断而导致可能的中断嵌套

    我希望某一段代码在平时和中断中都可以被正常调用,然而现状是没有保护的代码只能正常工作于中断中,而拥有DINT/EINT保护的代码则只能正常工作在本就开启了全局中断的中断外,想要正确调用则需要分别给出有/无保护的函数,调用者需要“静态”地判断出调用时的状态来调用正确的函数