Take the following example code:
static volatile bool pending = false;
void __attribute__((interrupt(TIMER0_A0_VECTOR))) TIMER0_A0_ISR (void)
{
pending = true;
}
int main(void)
{
while(true) {
if (!pending)
sleep();
pending = false;
// do stuff
}
}
Assume that the sleep function puts the hardware to sleep and that an interrupt wakes the hardware up, so that the sleep function will return immidiately after the interrupt.
There is a race condition here: if the interrupt happens after the if statement but before the sleep, we sleep until the next interrupt. This is a problem in my real-world counterpart of this code. How can I avoid this problem?
I am working with the msp430g2433.
To ensure that the check and the going-to-sleep are executed atomically, you have to disable interrupts around them. This also requires that you go to sleep and re-enable interrupts at the same time, but this is easy on the MSP430:
while (true) {
_disable_interrupts();
if (!pending)
_bis_SR_register(GIE + LPM1_bits);
else
_enable_interrupts();
pending = false;
// do stuff
}
Alternatively, write the interrupt bit accesses explicitly, which might make the logic clearer:
while (true) {
int status_bits = GIE;
_bic_SR_register(status_bits); // disable interrupts
if (!pending)
status_bits |= LPM1_bits;
_bis_SR_register(status_bits); // enable interrupts, go to sleep if needed
pending = false;
// do stuff
}