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:

timerDebounce=5;

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

while(timerDebounce!=0);

+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
terry
Loading thread data ...

No, it's a bug in your code.

Ian

Reply to
Ian Bell

"terry" schreef in bericht news: snipped-for-privacy@posting.google.com...

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
jtp

Please show where the code is wrong.

Reply to
terry

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() { ... }

IS VERY DIFFERENT FROM

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

bye

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 (broeker@physik.rwth-aachen.de)
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.