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.atpack
3 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 0x803E00
2 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.