Tuesday, July 10, 2012

Atmel Studio bug caused by --Wl,--gc-sections

I have found a bug in Atmel Studio 6.0.1843 (with AVR Toolchain 8 Bit 3.4.663 - GCC 4.6.2) that results in RAM variables being placed starting at address 0x60 instead of 0x100 if the --Wl,--gc-sections flag is enabled and the .data section is empty. This makes the RAM variables overlap with memory-mapped SFRs, so they do not function properly.

You can follow these steps to reproduce the bug:
  1. Make a new project with the GCC C Executable Project template and select the ATmega328P. (I believe this bug affects other parts too.)
  2. In the project properties, check the "Garbage collect unused sections (-Wl,--gc-sections)" checkbox.
  3. Write the following in main.c:
    
    #include <avr/io.h>
    unsigned char foo = 0;
    int main(void)
    {
        while(1){ PORTC = foo++; }
    }
    
  4. Build the project.
Now look at the .map output file. You will see the following line, which indicates that foo is at address 0x60.
                0x00800060                foo
Unfortunately, address 0x60 is the location of WDTCSR, so putting a variable there does not work well.

The problem goes away if you ensure that the .data section is non-empty by making a static variable that is initialized to a non-zero value:
static void __attribute__((used)) workaround(void)
{
    static volatile unsigned char w = 1;
    w++;
}
I believe that Atmel Studio is affected by bug #13697 from GNU binutils.

I hope that the next version of Atmel Studio comes with a patched or updated binutils that does not suffer from this problem. I have reported the bug to Atmel.

Update 2012-07-18: A member of the Atmel AVR Toolchain Team has responded to my bug report. He said: "Thanks. We will have this fix available with our next release."