lenguador lenguador - 2 years ago 119
C Question

Is volatile required for synchronous ISR access?

In the following code snippet, an interrupt routine uses one of many arrays for its execution. The array used is selected synchronously, not asynchronously (it will never change while the ISR is executing). On a single core microcontroller (this question assumes an STM32L496 if the architecture is important), is the

volatile
specifier required in the declaration of
foo
?

int a[] = {1, 2, 3};
int b[] = {4, 5, 6};
int * foo; //int * volatile foo? int volatile * volatile foo?

main(){
disable_interrupt();
foo = a;
enable_interrupt();
...
disable_interrupt();
foo = b;
enable_interrupt();
}

void interrupt(){
//Use foo
}


My assumption is that the
volatile
specifier is not required because any caching of the value of
foo
will be correct.

EDIT:

To clarify, the final answer is that
volatile
or some other synchronisation is required because otherwise writes to
foo
can be omitted or reordered. Caching is not the only concern.

Answer Source

volatile stops the compiler optimizing it, forcing the compiler

  • To always read the memory, not a cached value from a register
  • To not move things before, or after the register.

On a complex CPU (e.g. x86), it is possible for the CPU to re-order operations before, or after a volatile access.

It is typically for memory-mapped-io, where regions of memory, are actually devices, and can change (even on a single core CPU), without visible cause.

The mechanism for C++11 is to use std::atomic to change a value which may occur on different threads of execution.

With a single core, the code will safely modify the value, and store it. If you use volatile, then it will be written to the memory point, before the interrupts are enabled.

If you don't use volatile, then the code may still have the new value in a register before it is used in the interrupt.

int * volatile foo;

Describes that foo can change, but the values it points to, are stable.


int volatile * volatile foo

Describes foo can change, and the things it points to can also change. I think you want int * volatile foo;

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download