-1

I know there are a lot of questions regarding volatile here but I haven't found anything specific to this case. I am working with a microcontroller. I know I have to use the volatile qualifier when I modify a global variable inside an ISR and read it inside my main function. I also feel quite fit with memory barriers, race conditions etc.

But what if I only write to a global variable in my main function(with interrupts being disabled to enforce an atomic write) and i am reading and writing it inside my ISR.

To give a clear example assume this code:

int state = 0;
ISR()
{
    switch(state)
    {
        case 0:
            //do something
            state=nextState; //go to another state
            break;
        case 1:
            //do something
            state=nextState; //go to another state
            break;
        case 2:
            //do something
            state=nextState; //go to another state
            break;
        //...some more states
        default:
            state=0;
            break;
    }
}

main(void)
{
     while(true)
     {
          //do lots of stuff
          if(someCondition)
          {
               EnterCriticalSection(); //Disable IRQs and memorybarrier
               //write to global shared variable state here!!!
               state=0;
               ExitCriticalSection(); //Enable IRQs again
          }
     }
}

So must state be volatile here?

And when, why? (I am never really using the value inside the main) Can the compiler optimize the write to state away or something. Or can the compiler keep the value of state cached in some Register across multiple callings of the ISR? For now I keep variables like state volatile but I am curious if this is actually necessary.

Edit: Well, yes I understand the answers now. I apologize, I should have thought about it some minutes more. When I think about it now it is quite similar to (write-only) hardware registers. Of course I need volatile here to ensure a write operation in the main method.

  • 1
    https://stackoverflow.com/questions/6995310/is-volatile-bool-for-thread-control-considered-wrong probably answers the question. Threads and ISRs are similar in this regard. – Lundin Mar 13 '18 at 14:51
  • As you stated you know about race-conditions, etc. I wonder you ask this questions. Expecially as `volatile` is not a sufficient guarantee. – too honest for this site Mar 17 '18 at 17:12

2 Answers2

5

The situation does not differ from the case where you "know" you need volatile, and the case in question.

It is not about ISRs and main() and which reads and which writes, but rather about different execution thread contexts. It does not matter what those thread contexts are - the language is not thread aware, so will not consider that for optimisation purposes - you have to tell it by way of volatile whenever and however data is shared directly between contexts.

Take a look at: Introduction to the volatile keyword on Embedded.com, and also When to use – and not use – the volatile keyword, which collates a number of articles on the subject including the first one.

Clifford
  • 88,407
  • 13
  • 85
  • 165
0

The fact that you never use the value of state inside of main actually makes it more likely to be optimized away.

Since state is only set to zero in main, the compiler could optimize by setting it to zero once and never writing to it again.

If you want to ensure that state is zeroed every time someCondition is true, you need to use volatile.

D Krueger
  • 2,446
  • 15
  • 12
  • Why would the compiler do that, when state is a global and so could be modified in a different file (not counting the fact that it is modified in ISR) – itj Mar 16 '18 at 13:11
  • @itj The point that it is global is valid, however that it occurs in the ISR is not necessarily. If you define an ISR as a static function, and the state variable was also static, the compiler could well optimize accesses away inferring that the variable is not used. It can not "see" that the interrupt actually runs asynchronously. – Jubatian Mar 26 '18 at 12:22