Yahoo Groups archive

AVR-Chat

Index last updated: 2026-04-28 22:41 UTC

Message

Re: [AVR-Chat] gcc compiler bad behaviour

2012-04-13 by STEVEN HOLDER

Tim,
 
The AdcVals are being changed in a intterupt routine then ? The compiler needs to know that the values being stored or where they are being stored can changed or else it will optimise incorrectly, i.e it needs to have foresight of the fact that the values can change, if a value can be change from an interrupt routine and it is declared globally then it needs to be declared as volatile if it is the stored variable or the changed variable.
 
In the first instance of your code because there is no other code in the main routine the compiler will see this as one variable = another variable and sets it at compile time as it cannot see anything ever changing the variable, when you add the delay in or some other code it has to store them in the required variable because it may need the registers that it is using.
 
Generally if you do have variables that are global and can be changed outside the main routine then declare them as volatile (at the expense of variable optimisation) or cast it to volatile when required.
 
*(volatile) unsigned char *)&LedLevel0 = AdcVal[0];
 
Regards

 

________________________________
From: Tim Mitchell <tim@sabretechnology.co.uk>
To: AVR-Chat@yahoogroups.com 
Sent: Friday, 13 April 2012, 11:35
Subject: [AVR-Chat] gcc compiler bad behaviour


  

The GCC compiler optimiser seems to be doing a weird thing to me... I'd like to understand it. it seems to require a volatile qualifier when I am not expecting it.

I have the following variables defined
unsigned char LedLevel0=0;
unsigned char LedLevel1=0;
volatile unsigned char AdcVal[4];

AdcVal holds readings from the ADC and is loaded in an interrupt routine

main loop:

//the main loop
while(1)
{
LedLevel0=AdcVal[0];
LedLevel1=AdcVal[1];
}

compiler output:

//the main loop
while(1)
{
LedLevel0=AdcVal[0];
3ea: 80 91 86 01 lds r24, 0x0186
LedLevel1=AdcVal[1];
3ee: 80 91 87 01 lds r24, 0x0187
3f2: fb cf rjmp .-10 ; 0x3ea <main+0x8>

i.e. it's loading the AdcVal into r24, but never stores it into the other variable.

if I change the main loop to add a call to a delay routine then it works correctly. Also if I declare LedLevel0/1 as volatile.
But in my mind it shouldn't need to be declared volatile, nothing else is changing it.

//the main loop
while(1)
{
LedLevel0=AdcVal[0];
LedLevel1=AdcVal[1];
TimeWait(1);
}

compiler output:
//the main loop
while(1)
{
LedLevel0=AdcVal[0];
3ea: 80 91 86 01 lds r24, 0x0186
3ee: 80 93 06 01 sts 0x0106, r24
LedLevel1=AdcVal[1];
3f2: 80 91 87 01 lds r24, 0x0187
3f6: 80 93 07 01 sts 0x0107, r24
TimeWait(1);
3fa: 81 e0 ldi r24, 0x01 ; 1
3fc: 90 e0 ldi r25, 0x00 ; 0
3fe: f4 cf rjmp .-24 ; 0x3e8 <main+0x6>

-- 
Tim Mitchell 




[Non-text portions of this message have been removed]

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.