Is it AVR-GCC bug?

I have written a simple program by GCC-AVR to detect key press. I found the debounce loop cannot be break.

In file main.c:

extern unsigned char timerDebounce=0;

: : c=pressKey(); if(c==-1) { } else { timerDebounce=5; while(timerDebounce!=0);//cannot break here col=pressKey(); : :

In file timer.c:

unsigned char timerDebounce=0;

void SIG_OVERFLOW0 (void) __attribute__ ((signal));

void SIG_OVERFLOW0 (void) { timerCounter25ms=(timerCounter25ms+1)%50; if(timerCounter25ms==0) { if(timerDebounce==0) { } else timerDebounce--;

: :

Then I disasmbler the program and found:


+0000006D: E085 LDI R24,0x05 Load immediate +0000006E: 93800071 STS 0x0071,R24 Store direct to data space


+00000070: 2388 TST R24 Logical AND +00000071: F7F1 BRNE -0x02 Branch if not equal

Obviously the "timerDebounce" is saved at SRAM location 0x71. I have traced the program and found the value at the location is 0 during looping , and the looping is caused by the program continues test the register R24 rather than the SRAM location 0x71 for branching if zero.

Is it a bug in GCC-AVR? Thanks!

Reply to
Loading thread data ...

No, it's a bug in your code.


Reply to
Ian Bell

"terry" schreef in bericht news:

Lookup the keyword volatile.

timerDebounce=5; while(timerDebounce!=0);//cannot break here

The compiler doesn't know that 'someone else' is going to change TimerDebounce, so it is perfectly okay to use a register for the time being. I guess that a few more lines down in your assembly, the compiler has created lines to store the TimerDebounce at locaction 0x71. Of course, that is not going to happen, as it keeps locked up in the loop.

BTW, please realize that your while loop is a great time waster. If you can afford that, no problem.

I'm not an GCC-AVR expert, but it doesn't look like a compiler bug.

Thanks, Frank.
(remove 'x' and 'invalid' when replying by email)
Reply to
Frank Bemelman

Lose the =0 here. It's not causing the bug, but initialization should really be with the definition, not the declaration. Right now, you have to places where timerDebounce is initialized. There should be only one.

What you need to do is to declare timerDebounce as "volatile". This will force the while loop to read the SRAM variable. Any variable that can change via an interrupt or via a change in hardware needs to be declared as volatile. You also should not have any sort of compiler optimization turned on when developing code. Get it working right, then turn optimization on and see the results.

Reply to
Gary Kato

Make that timerDebounce a volatile variable so the compiler will check the timerDebounce value from the SRAM in every loop rather than store the timerDebounce into the register before the loop.

Search from this newsgroup with the keyword "volatile" if you are not familiar its usage.

Reply to

Please show where the code is wrong.

Reply to

To avoid GCC optimization code you should declare timerDebounce variable as static.

Reply to
habib bouaziz-viallet

Declaring it static doesn't avoid optimization. Declaring it volatile will. It's what volatile is meant to do. Declaring something static means he can't export the name by using extern. When the compiler sees something declared as static, it doesn't generate an exportable symbol for the linker to use (it restricts visibility). If you try to to use:

extern static unsigned char timerDebounce;

you will get a compiler error like "declaration syntax error".

Reply to
Gary Kato

oops ! my apologies i didn't read timerDebounce variable is also declared in main as extern. So you're right, static modifier on variables makes them unvisible by other modules (*.c) static variables are remanent also I think that the prob is timerDebounce always 0 on main function but it depends on where located that inst

extern unsigned char timerDebounce = 0;

void main() { ... }


void main() { extern unsigned char timerDebounce = 0;

... }

I'm not sure that volatile modifier on that var would be the solution, locals vars are stored in regs AVR and be destroyed after exec functions. volatile modifier force GCC to read var in loops statements sensitive with asynchronous events (PORTS, INT's)

Tell me how the problem was fixed


Reply to
habib bouaziz-viallet

Indeed. Because the latter won't even compile as C code. "extern" inside blocks may only be used to code declarations, but not definitions. The presence of the "= 0" initializer, OTOH, turns this into a definition.

Actually, good C programming style effectively bans all use of the 'extern' qualifier outside header files. Whenever you think you want to use 'extern' in a source file, you should really #include a header file that holds the needed declaration, instead.

Then let me be one more person to ensure you that it is. This is

*exactly* the situation the 'volatile' modifier was originally created for. If making this variable 'volatile' doesn't suffice to fix the problem at hand, that would be a compiler bug.
Hans-Bernhard Broeker (
Even if all the snow were burnt, ashes would remain.
Reply to
Hans-Bernhard Broeker

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.