Accessing a shared volatile variable

Thread Starter

Vindhyachal Takniki

Joined Nov 3, 2014
583
1. Need to access a volatile shared variable between main & interrupt. Trying to write code irrespective of 8,16 or 32 bit machine.

2. I have a code as below. But problem is even I have a lock varible i.e main_read, it is not atomic again.
For example, it will break into number of assembly instruction depending on 8,16 or 32.
Again if in between these instruction, interrupt comes, problem will arise.


3. Current I do like this:

Code:
volatile uint8_t vol_var,vol_var_copy;   /* took two variable & one as its copy */


void main_code(void)
{
    main_read = 1;
    data_read = vol_var;
    main_read = 0;
   
    if(1 == main_interrupted)
    {
        data_read = vol_var_copy;
        main_interrupted = 0;
    }
}


void isr(void)
{
    if(0 == main_read)
    {
        vol_var = value;
    }
    else
    {
        main_interrupted = 1;
        vol_var_copy = value;
    }
}
 

nsaspook

Joined Aug 27, 2009
8,384
Yes, making a variable volatile does not make it atomic, it's only a compiler hint not to optimize or cache value accesses. What you can do is to make a atomic_t type semaphore (using a type that is atomic in each machine type) in a header file that has a conditional define depending on the machine type and make main_read a variable of atomic_t.

volatile atomic_t main_read;

Then you must be sure the generated ASM code for manipulating this variable flag is atomic on all platforms or disable interrupts if not.
https://en.wikipedia.org/wiki/Test-and-set
 
Last edited:

ErnieM

Joined Apr 24, 2011
8,153
Typically the only problem is the ISR changing a variable while the main code is doing a read, so the main code gets a corrupted value.

There are two standard methods I use for this. Occasionally I will disable interrupts while doing the read (where I copy the shared value into another non-shared variable). Usually I just copy it and check again I really have the correct value:

while(shared_value != copy_value) copy_value = shared_value;

That little common code fragment screams out for a macro.
 
Top