Accessing a shared volatile variable

Discussion in 'Embedded Systems and Microcontrollers' started by Vindhyachal Takniki, Aug 22, 2015.

  1. Vindhyachal Takniki

    Thread Starter Member

    Nov 3, 2014
    349
    6
    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 (Text):
    1.  
    2. volatile uint8_t vol_var,vol_var_copy;   /* took two variable & one as its copy */
    3.  
    4.  
    5. void main_code(void)
    6. {
    7.     main_read = 1;
    8.     data_read = vol_var;
    9.     main_read = 0;
    10.    
    11.     if(1 == main_interrupted)
    12.     {
    13.         data_read = vol_var_copy;
    14.         main_interrupted = 0;
    15.     }
    16. }
    17.  
    18.  
    19. void isr(void)
    20. {
    21.     if(0 == main_read)
    22.     {
    23.         vol_var = value;
    24.     }
    25.     else
    26.     {
    27.         main_interrupted = 1;
    28.         vol_var_copy = value;
    29.     }
    30. }
    31.  
     
  2. nsaspook

    AAC Fanatic!

    Aug 27, 2009
    2,910
    2,173
    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: Aug 22, 2015
  3. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,392
    1,606
    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.
     
Loading...