我正在为MSP430编写ISR。它读取易失性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寄存器之前再次中断,并且它的值可能会更改为不同的值,这将是一个问题。
我期望编译器在跳转后立即放置我的加载指令是否合理,从而确保在另一个中断可以改变之前我总是得到该寄存器的副本?
谢谢
答案 0 :(得分:1)
您在使用的任何MSP430芯片的用户指南中都会回答您的所有问题。
您的代码不会调用中断;当外部事件触发它们时,CPU会自动执行它们。 将PC和SR寄存器保存到堆栈,清零GIE位,以及读取和跳转到中断向量,需要六个周期。但是,如果禁止中断,则中断可以延迟任意时间。
在中断处理程序中,中断被禁用(除非您明确地重新启用它们)。
P4IFG寄存器中的位不是由您的代码设置的,因此无论是否启用中断都无关紧要。只要配置的信号边沿发生在其中一个引脚上(可能发生在任何时间),新位就会置1,但先前设置的位不会被清除。
在你的中断处理程序中,你应该读取中断标志并清除你读过的那些位。 (如果在执行中断处理程序时发生新事件,则在返回后会出现新的中断。)
__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;
...
}
}