-2

我正在为 MSP430 编写 ISR。它读取 volatile PxIFG 寄存器并在第一条指令上将其复制到堆栈变量中。ISR 跳转是否有任何开销,或者我可以期待吗

__interrupt void SW_PRESSED_ISR(void)
{
  unsigned short currnet_ifg = P4IFG;
...
}

编译成类似的东西

... Register saving instructions
JSR ...       // jump into ISR
LD  P4IFG ... // load volatile register P4IFG value
...

我知道如果 ISR 跳转后的第一条指令是寄存器加载,我的 ISR 将按预期工作。我的理解是MSP430保证跳转后一条指令可以再次中断。如果加载不是跳转后的第一条指令,我会遇到一个问题,即在读取 P4IFG 寄存器之前我可能会再次被中断,并且它的值可能会更改为不同的值,这将是一个问题。

我期望编译器在跳转之后立即放置我的加载指令是否合理,从而确保我总是能在另一个中断可以更改它之前获得该寄存器的副本?

谢谢

4

1 回答 1

1

您使用的任何 MSP430 芯片的用户指南都回答了您的所有问题。

您的代码不会调用中断;当外部事件触发它们时,它们由 CPU 自动执行。将 PC 和 SR 寄存器保存到堆栈,清除 GIE 位,读取并跳转到中断向量,需要六个周期。但是,如果禁用中断,则可以将中断延迟任意时间。

在中断处理程序中,中断被禁用(除非您明确地重新启用它们)。

P4IFG 寄存器中的位不是由您的代码设置的,因此是否启用中断并不重要。每当配置的信号边沿发生在其中一个引脚(可能随时发生)时,都会设置新,但不会清除先前设置的位。

在您的中断处理程序中,您应该读取中断标志并清除您已读取的那些位。(如果在中断处理程序执行期间发生了新事件,则在返回后您将获得新的中断。)

__interrupt void SW_PRESSED_ISR(void)
{
    uint16_t ifg = P4IFG;
    P4IFG &= ~ifg;

    if (ifg & ...)
        ...
}

使用中断向量寄存器可能是一个更好的主意,它以原子方式返回端口的中断之一,并重置相应的标志位:

__interrupt void SW_PRESSED_ISR(void)
{
    switch (P4IV) {
    case P4IV_P4IFG0:
        // event at bit 0
        break;
    case P4IV_P4IFG1:
        // event at bit 1
        break;
    ...
    }
}
于 2016-02-15T08:21:06.007 回答