Topic : Issue when comparing a volatile variable

Forum : ST7/STM8

Original Post
Post Information Post
August 28, 2009 - 5:42pm
Guest

In the code below, the second part of the

if (TTS > STS)

statement produces no code. Removing 'volatile' from the definition of TTS resolves the issue. Am I missing something obvious here?

I think I can remove volatile from the definition in my code, as it was there only to ensure that the timer register would be read in the correct order (high byte first) when using optimization.

--
Blasio

***** BEGIN CODE *****

#include
#include

void Func1(void);

unsigned short STS;
unsigned short MAX_D, MIN_D=0xFFFF;

void main(void)
{
char i;
STS = T16ACR;

for (i=0; i<100; i++)
_nop_();

Func1();

while(1);

}

void Func1(void)
{

volatile unsigned short TTS = T16ACR;
unsigned short Duration;

if (TTS > STS)
{
Duration = TTS-STS;
}
else
{
Duration = ((TTS-STS) + 65536);
}

if (Duration > MAX_D) MAX_D=Duration;
if (Duration < MIN_D) MIN_D=Duration;

}

Replies
Post Information Post
+1
0
-1
August 28, 2009 - 6:39pm
Guest

That is similar to the problem I posted here: http://raisonance-forum.xsalto.com/viewtopic.php?id=2945

Do you have the automatic variable relocation enabled? My problem also concerned comparing volatiles.

+1
0
-1
August 31, 2009 - 10:21am
Raisonance Support Team

Hi Blasio,

We spent a bit of time trying to understand what happens in your code. The compiler is *right* when simplifying your code:

In the line: Duration = ((TTS-STS) + 65536); The 65536 is useless, as i + 65536 will always give back i as a result. Hence the compiler has been simplifying your code up to the point where the test vanishes.

A question can be "why does the non-volatile version of the code provide a fully functional code?". The answer here is that when simplifying the code, the optimizer is performing some factorization of assembly code statements. But at a given point it needs to factorize two "POP A", which is dangerous and is hence not performed. This is why the test remains in the non-volatile version; but if you look at the assembly code produce you will see that the statements are the same whatever the result of the comparison.

As a baseline, instead of:

if (TTS > STS)
    {
        Duration = TTS-STS;
    }
    else
    {
        Duration = ((TTS-STS) + 65536);
    }

You can just write:
Duration = TTS-STS;

The C will guarantee that the computation is correct.

I hope this helps,
Bruno

+1
0
-1
August 31, 2009 - 10:48am
Guest

Bruno wrote:

You can just write:
Duration = TTS-STS;

The C will guarantee that the computation is correct.

Yes, I forgot that with unsigned variables the result is valid even if an overflow occurs. Thanks for the response.

--
Blasio