avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-gcc-list] Re: Volatile bad compiled while


From: David Brown
Subject: [avr-gcc-list] Re: Volatile bad compiled while
Date: Fri, 27 Nov 2009 12:41:41 +0100
User-agent: Thunderbird 2.0.0.23 (Windows/20090812)

max2009tiny wrote:
OK
i can't drop register and i use on this code more register vars and all work
ok exept
while clause. That generate bad jump -4 .

My query is why not for removing register clause.
If memory store all code is +2 bytes for read and +2 any once write var and
this is over memory limit....


Here are some hints that might help you out:

You can't use "register volatile" variables - they don't work.

Using "register" variables will sometimes make code larger, since it hinders the compiler - do some testing here to be sure.

Using __attribute__((noinline)) will also often make the code larger - the compiler will spend more instructions putting data in the right registers for the function call than it would by inlining small functions.

Generally speaking, the compiler is better at optimising when you let it do its job than when you try and force it using hints like "register" and "noinline".

Make sure you use -combine and -fwhole-program to compile the code. -fno-split-wide-types is also often helpful.

You can force a "volatile" read of a register using the register's memory address:

__attribute__ ((noinline)) void waitACK(u08 cmack)
{
        while (cmack != *((volatile u08*)(0x0008))) ;
}

Address 0x0008 is the address of the r8 register. This will force a volatile read as (using an lds instruction), but you will at least spare the write.

If all else fails, it is sometimes best to use assembly.

mvh.,

David




David Brown-4 wrote:
max2009tiny wrote:
Hi everybody. I make project on Tiny2313 and use
volatile register unsigned char lastrec asm("r8")

and lastrec is modified on rs232 rx isr.

When compile little function
__attribute__ ((noinline)) void waitACK(u08 cmack)
{
while(cmack!=lastrec) ; //wait for reply request
}


Fixing a variable to a register in this way is almost never a good idea. It is /possible/, because there are rare occasions when you want to do so, but such cases are very rare. It is also very easy to break other parts of your program by using register variables like this, due to conflicts with register usage in the library or the compiler. See

<http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_regbind>

(Note that explicitly recommends /not/ using r8 for this use.)



On some versions of gcc, using a "volatile register" variable will give the warning "volatile register variables don't work as you might wish" if -Wall or -Wvolatile-register-var is enabled. For some reason, this warning does not seem to be triggered by avr-gcc while testing. However, the explanation from the manual remains relevant:

"""
-Wvolatile-register-var
Warn if a register variable is declared volatile. The volatile modifier does not inhibit all optimizations that may eliminate reads and/or writes to register variables. This warning is enabled by -Wall.
"""


Here are some other comments about global volatile register variables:

<http://gcc.gnu.org/ml/gcc-patches/2005-11/msg00657.html>
<http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34351>



In summary, you use "register" variables for data that is absolutely speed-critical and used widely throughout your code, and for which dedicating a register makes sense (i.e., almost never). You use "volatile" when you specifically want to limit the compiler's optimisation of the variable. "volatile register" is a conflict of interests, and it does not work as you think it should - the compiler cannot treat it as both a restricted volatile and a highly-optimised register at the same time.

Drop the "register", and your code will be fine.








reply via email to

[Prev in Thread] Current Thread [Next in Thread]