0

I am having the following problem when I try to compiler a simple test program for ATtiny424 with avr-gcc v8 (same with avr-gcc v13):

C program simple.c:

char x;

int main (void)
{
    x = 1;
    return 0;
}

avr-gcc does not support ATtiny424, so I downloaded the Atmel.ATtiny_DFP.2.0.368.atpack3 and unZIP'ed it to some folder <atpack>. Then I compile the C source above with4:

> avr-gcc simple.c -mmcu=attiny424 -B <atpack>/gcc/dev/attiny424 -isystem <atpack>/include -o simple.elf -Os -Wl,-Map,simple.map

which throws the following linker error at me:

.../avr/bin/ld: address 0x803e00 of simple.elf section `.data' is not within region `data'
.../avr/bin/ld: address 0x803e01 of simple.elf section `.bss' is not within region `data'
.../avr/bin/ld: address 0x803e00 of simple.elf section `.data' is not within region `data'
.../avr/bin/ld: address 0x803e01 of simple.elf section `.bss' is not within region `data'
collect2: error: ld returned 1 exit status

The RAM of ATtiny424 starts at 0x3e00, so the device-specs file1 adds -Tdata 0x803E002 to the linker command. I checked by means of -v that this option is actually passed to the linker. The generated map file simple.map reads as follows:

[...]
Memory Configuration

Name             Origin             Length             Attributes
text             0x0000000000000000 0x0000000000001000 xr
data             0x0000000000802000 0x0000000000000200 rw !x
[...]
Linker script and memory map

Address of section .data set to 0x803e00
[...]
.data           0x0000000000803e00        0x0 load address 0x000000000000006e
                [!provide]                        PROVIDE (__data_start = .)
 *(.data)
 .data          0x0000000000803e00        0x0 <atpack>/gcc/dev/attiny424/avrxmega3/short-calls/crtattiny424.o
 .data          0x0000000000803e00        0x0 simple.o
 .data          0x0000000000803e00        0x0 .../lib/gcc/avr/8.5.0/avrxmega3/short-calls/libgcc.a(_exit.o)
 .data          0x0000000000803e00        0x0 .../lib/gcc/avr/8.5.0/avrxmega3/short-calls/libgcc.a(_clear_bss.o)
 *(.data*)
 *(.gnu.linkonce.d*)
                0x0000000000803e00                . = ALIGN (0x2)
                0x0000000000803e00                _edata = .
                [!provide]                        PROVIDE (__data_end = .)

.bss            0x0000000000803e00        0x1
                0x0000000000803e00                PROVIDE (__bss_start = .)
 *(.bss)
 .bss           0x0000000000803e00        0x0 <atpack>/gcc/dev/attiny424/avrxmega3/short-calls/crtattiny424.o
 .bss           0x0000000000803e00        0x0 simple.o
 .bss           0x0000000000803e00        0x0 .../lib/gcc/avr/8.5.0/avrxmega3/short-calls/libgcc.a(_exit.o)
 .bss           0x0000000000803e00        0x0 .../lib/gcc/avr/8.5.0/avrxmega3/short-calls/libgcc.a(_clear_bss.o)
 *(.bss*)
 *(COMMON)
 COMMON         0x0000000000803e00        0x1 simple.o
                0x0000000000803e00                x
                0x0000000000803e01                PROVIDE (__bss_end = .)
                0x000000000000006e                __data_load_start = LOADADDR (.data)
                0x000000000000006e                __data_load_end = (__data_load_start + SIZEOF (.data))
[...]

So x is allocated to 0x3e00 as expected.

I can work around the error by means of -Wl,--defsym,__DATA_REGION_LENGTH__=0x1e02, so it appears as if .data start is still at 0x802000 where the default linker script puts it. The respective portion of the default linker script reads:

[...]
OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
OUTPUT_ARCH(avr:103)
__TEXT_REGION_LENGTH__ = DEFINED(__TEXT_REGION_LENGTH__) ? __TEXT_REGION_LENGTH__ : 1024K;
__DATA_REGION_LENGTH__ = DEFINED(__DATA_REGION_LENGTH__) ? __DATA_REGION_LENGTH__ : 0xffa0;
[...]
MEMORY
{
  text   (rx)   : ORIGIN = 0, LENGTH = __TEXT_REGION_LENGTH__
  data   (rw!x) : ORIGIN = 0x802000, LENGTH = __DATA_REGION_LENGTH__
[...]
}

All this doesn't fit together, and I am confused and do not understand what's going on:

  • The default for __DATA_REGION_LENGTH__ is 0xffa0, but the map file reports it as 0x200.

  • The map file reports .data start at 0x803e00, but the linker behaves as if it was still at 0x802000 because a __DATA_REGION_LENGTH__ of 0x1e02 does work, but a __DATA_REGION_LENGTH__ of 0x1e00 does not work as it throws errors like above.

So what's going wrong here? And how can I fix it? (without lying about the data region length, which is only 0x200 bytes for ATtiny424).


1Located at <atpack>/gcc/dev/attiny424/device-specs/specs-attiny424.

2In order to linearize RAM and Flash, RAM addresses are offset by a value of 0x800000 so that the linker can tell apart RAM and flash addresses.

3This is just a ZIP file in disguise. It can be downloaded from http://packs.download.atmel.com

4This is basically the process described in Supporting "unsupported" Devices in the avr-gcc wiki.


Edit 1

The statup-code of the crt<mcu>.o files in <atpack> contains additional weak symbols compared to the stock version of GNU tools. These extra symbols convey some properties of the memory layout of the device:

> avr-nm <atpack>/gcc/dev/attiny424/avrxmega3/short-calls/crtattiny424.o 
00000200 W __DATA_REGION_LENGTH__
00803e00 W __DATA_REGION_ORIGIN__
[...]

so this explains where __DATA_REGION_LENGTH__ of 0x200 comes from, but it does not explain why -Tdata 0x803e00 does not work as expected.

emacs drives me nuts
  • 2,785
  • 13
  • 23

0 Answers0