-2

I am writing an ISR for the MSP430. It reads the volatile PxIFG register and copies it into a stack variable on the first instruction. Is there any overhead to an ISR jump or can I expect

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

to compile to something like

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

I know that my ISR will work as intended if the first instruction after the ISR jump is the register load. My understanding is the MSP430 guarantees one instruction after the jump before it can be interrupted again. If the load isn't the first instruction after the jump I have the issue that I could be interrupted again before the P4IFG register is read and it's value may be changed to a different value which would be a problem.

Is it reasonable for me to expect the compiler to place my load instruction immediately after that jump thus ensuring I will always get a copy of that register before another interrupt can change it?

Thank you

Apcragg
  • 133
  • 1
  • 7
  • The C standard does not require using a stack for automatic variables. You should not assume it actually is. What do you want to accomplish? Your question is unclear. Reading & understanding the Users Guide is always a good start. – too honest for this site Feb 15 '16 at 04:13
  • You do NOT jump into ISRs. The execution path gets into the ISR in response to some event that triggers the associated interrupt. The linkage for an ISR is dramatically different (in most circumstances) than the linkage for a call to a function. – user3629249 Feb 15 '16 at 05:43
  • You could have the first instruction in the ISR be a disabling of the interrupts. Then have the ISR perform what ever you want to treat as 'critical' code, then re-enable the interrupts – user3629249 Feb 15 '16 at 05:44

1 Answers1

1

All your questions are answered in the User's Guide of whatever MSP430 chip it is that you're using.

Interrupts are not called by your code; they are automatically executed by the CPU when an external event triggers them. Saving the PC and SR registers to the stack, clearing the GIE bit, and reading and jumping to the interrupt vector, requires six cycles. If, however, interrupts are disabled, the interrupt can be delayed by an arbitrary amount of time.

Inside an interrupt handler, interrupts are disabled (unless you explicitly re-enable them).

Bits in the P4IFG register are not set by your code, so it does not matter whether interrupts are enabled or not. New bits get set whenever the configured signal edge happens at one of the pins (which can happen at any time), but previously set bits will not be cleared.

In your interrupt handler, you should read the interrupt flags and clear those bits that you've read. (If a new event happens while the interrupt handler is executing, you will get a new interrupt after is has returned.)

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

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

It might be a better idea to use the interrupt vector register, which atomically returns one of the port's interrupts, and resets the corresponding flag bit:

__interrupt void SW_PRESSED_ISR(void)
{
    switch (P4IV) {
    case P4IV_P4IFG0:
        // event at bit 0
        break;
    case P4IV_P4IFG1:
        // event at bit 1
        break;
    ...
    }
}
CL.
  • 173,858
  • 17
  • 217
  • 259