cancel
Showing results for 
Search instead for 
Did you mean: 

volatile variables and ''functions''

megahercas6
Senior
Posted on November 20, 2014 at 11:48

Hello,

i am running compile (IAR AMR) in highest optimization settting, but sometimes it does ignores my code, or even functions that does have purpose; as example, DataRx[] is loaded by DMA with data from computer, and it is used for triggering ( software based), 160 is free running mode, 168 is external trigger

if((DataRx[0])==168)
{
while((GPIOA->IDR&GPIO_Pin_3)==0)
{
if(DataRx[0]==160)
{
break;
} 
}
}

if i use uint8_t as my variable, this code is ignored, adding volatile uint8_t does solve problem, but then, compiler states that is problem in my other code ( but it works)

A_offset=DataRx[2]+(DataRx[3]<<8);
D_offset=(DataRx[4]+(DataRx[5]<<8))&1023;
integration=DataRx[6]+(DataRx[7]<<8);

error code says for all lines: Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement any idea how to tell compiler, that it must execute my trigger code, or should i move this code to outside main(), and create volatile function ? ( just tryed, it does work, but i should know what kind of programming error i am creating)
1 REPLY 1
ivani
Associate II
Posted on November 20, 2014 at 15:46

The compiler has no idea about the DMA (and ISR as well), so for it the data in DataRx never changes and it happily removes these operations as redundant.

Using of

volatile qualifier is the correct way to resolve this issue.

Resolving the warning could be done if you split the operation in two, so there will be only one

volatile operand per operation:

A_offset= DataRx[3];  A_offset=DataRx[2]+(A_offset<<8);

But

volatile alone may not be enough. You should take measures to ensure that the part of the array used in the calculations will not change unexpectedly in the middle of operations. May it is not an issue if the DMA doesn't overwrite the same locations unless you restart it.

And finally, it seems to me that:

A_offset=DataRx[2]+(DataRx[3]<<8);

...

should be:

A_offset=DataRx[2]+((unit16_t)DataRx[3]<<8);

...