10 years, 1 month ago.

Sharing Variables with Interrupts

Hi everyone! If I have a variable that's being written to by an interrupt, and read from by the foreground code, do I need to make the read operation a critical section? Here's an example program that demonstrates what I'm talking about:

main.cpp

#include "mbed.h"

Ticker ticker;
int counter = 0;

void onTicker()
{
    //Increment the counter
    counter++;
}

int main()
{
    //Start the ticker at 1kHz
    ticker.attach_us(onTicker, 1000);

    while(1) {
        //Delay for 0.1s
        wait(0.1);

        //Get a copy of the current count value (should this be a critical section?)
        int currentCounter = counter;

        //Print the current counter value
        printf("The count is now %i!\n", currentCounter);
    }
}


In other words, is it possible for the foreground code to "half read" the variable, and then the interrupt update it before the rest of the variable is read causing currentCount to equal some bogus value? What if the scenario is reversed? Thanks!

1 Answer

10 years, 1 month ago.

For sure it will need to be volatile int.

But I don't see how it could half read it, since the critical parts should be atomic. Now if you modify the value in both main loop and the interrupt (for example if you have a buffer counter, which one increments and the other decrements), then you would need to protect it. Since then it would need to read memory, increment, write memory. And in between those operations the interrupt could occur, changing the memory after the main loop already copied that memory to a register.

Accepted Answer

Thanks for the reply Erik. Any particular reason it needs to be declared volatile though? My understanding is that volatile is only for situations where the variable might be modified without the compiler's knowledge (such as memory-mapped I/O). In this case, the compiler knows the variable is being modified by the callback and doesn't optimize it out.

posted by Neil Thiessen 04 Nov 2014

The compiler doesn't understand the Ticker and what the interrupt does. So it is very well possible that to optimize stuff in the while(1) loop it will only read counter once from the SRAM into a register, and then keeps using that register value, since there is no way it could be changed anyway. With volatile you force it to reread the SRAM with the new contents your interrupt routine wrote to it.

posted by Erik - 04 Nov 2014

Alright, thanks

posted by Neil Thiessen 04 Nov 2014