I use Eclipse and Yagarto toolchain (non-eabi, GCC 4.7.1) to program a ARM 7 chip (Atmel's AT91SAM7X256), Goal of this project is to place a bootloader in a defined range of ROM, which is copied to RAM later (see image below, ROM address 0x104000 for application code start is fixed). Works as expected ... until you debug the programm (SEGGER J-Link and GDB).
Memory structure image is shown here: http://i47.tinypic.com/2vb6f7o.jpg (sorry, cannot post images here).
The problems start with the .text section of the linked, mainly with the following method, which starts the whole .text section (correct): (disassembled C code by objdump -e -h common/exhandler.o > exhandler.lst)
00000000 <EXHANDLER_printHex>:
0: e92d4038 push {r3, r4, r5, lr}
4: e1a05000 mov r5, r0
8: e3a0401c mov r4, #28
c: e1a03435 lsr r3, r5, r4
10: e203000f and r0, r3, #15
14: e3500009 cmp r0, #9
18: c2800027 addgt r0, r0, #39 ; 0x27
1c: e2800030 add r0, r0, #48 ; 0x30
20: ebfffffe bl 0 <DBGUNIT_sendCharacter>
24: e2444004 sub r4, r4, #4
28: e3740004 cmn r4, #4
2c: 1afffff6 bne c <EXHANDLER_printHex+0xc>
30: e8bd4038 pop {r3, r4, r5, lr}
34: e12fff1e bx lr
When disassembling the linked ELF file, the code is outputted as: (wrong)
00104000 <EXHANDLER_printHex>:
104000: e92d4038 push {r3, r4, r5, lr}
104004: 5000 str r0, [r0, r0]
104006: 401ce1a0 andsmi lr, ip, r0, lsr #3
10400a: e3a0 b.n 10474e <ADCDAC_get16BitChannel+0x82>
10400c: e1a03435 .word 0xe1a03435
104010: e203000f and r0, r3, #15
104014: e3500009 cmp r0, #9
104018: 0027 movs r7, r4
10401a: 0030c280 eorseq ip, r0, r0, lsl #5
10401e: e280 b.n 104522 <CSTARTUP_lowLevelInit+0xfa>
104020: eb003367 bl 110dc4 <__DBGUNIT_sendCharacter_from_arm>
104024: 4004 ands r4, r0
104026: e244 .short 0xe244
104028: e3740004 cmn r4, #4
10402c: 1afffff6 .word 0x1afffff6
104030: e8bd4038 pop {r3, r4, r5, lr}
104034: e12fff1e .word 0xe12fff1e
While the byte sequences remain intact, the interpretation of those ASM commands differ. My assumption is that something went wrong with Thumb and ARM code in linking process.
My linker file:
/*
* Linker script for AT91SAM7X256 with internal bootloader.
*
* Bootloader is put into first 16 kB of Flash, then loaded to RAM and will connect by DBGU UART interface
* (115 kBaud, no parity bit).
*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
MEMORY
{
flash-boot (rx) : ORIGIN = 0x00100000, LENGTH = 16K /* read-only flash memory for boot-loader and startup sequence */
flash-app (rx) : ORIGIN = 0x00104000, LENGTH = 240K /* read-only flash memory for application */
ram (rwx) : ORIGIN = 0x00200000, LENGTH = 64K /* read/write S-RAM memory */
}
/* Stack is growing backwards, starting at end of RAM and is aligned at 4 byte. First entry in stack will
use RAM address 0x20fffc to 0x20ffff. */
_estack = 0x20fffc;
SECTIONS
{
. = 0;
/* Elements required during start-up sequence. Must be first elements in ROM. */
.startup : {
obj/sys/startup.o(.text .rodata)
. = ALIGN(4);
obj/sys/swi_handler.o(.text .rodata)
. = ALIGN(4);
_estartup = .; /* end of startup segment */
} >flash-boot
.ramvect : { /* used for vectors remapped to RAM */
__ram_start = .;
. = 0x40;
} >ram
/* Further elements for bootloader, which are placed into RAM for allowing chip flash. */
.bootloader : {
_bootloader = .; /* RAM */
obj/comm/dbgunit.o(.text .rodata)
. = ALIGN(4);
_ebootloader = .; /* RAM */
} >ram AT>flash-boot
/* Code starts at fixed address in flash (application start) and is kept there. */
.text : {
CREATE_OBJECT_SYMBOLS
*(.text .text.* .gnu.linkonce.t.*) /* remaining code */
*(.plt)
*(.gnu.warning)
*(.glue_7) *(.glue_7t) /* stub for code which glues together ARM7 and Thumb code */
. = ALIGN(4);
*(.rodata .rodata.* .gnu.linkonce.r.*) /* read-only data (constants) */
*(.ARM.extab* .gnu.linkonce.armextab.*)
*(.gcc_except_table)
*(.init)
*(.fini)
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);
} >flash-app
/* .ARM.exidx is sorted, so has to go in its own output section. */
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
__exidx_end = .;
} >flash-app
_etext = .;
/* Initialized .data sections go into RAM. */
.data :
{
_data = .; /* create a global symbol marking the start of the .data section (RAM) */
*(.ramsection .ramsection.*)
. = ALIGN(4);
*(.data .data.* .gnu.linkonce.d.*)
. = ALIGN(4);
_edata = .; /* define a global symbol marking the end of the .data section */
} >ram AT>flash-app /* put all the above into RAM */
/* Uninitialized .bss sections go into RAM. */
.bss (NOLOAD):
{
__bss_start__ = .; /* define a global symbol marking the start of the .bss section */
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
} > ram /* put all the above in RAM (it will be cleared in the startup code */
_bss_end = . ;
__bss_end__ = . ; /* define a global symbol marking the end of the .bss section */
. = ALIGN(4); /* advance location counter to the next 32-bit boundary */
_end = .; /* define a global symbol marking the end of application RAM */
PROVIDE (end = .);
/* DWARF debug sections.
* Symbols in the DWARF debugging sections are relative to the beginning
* of the section so we begin them at 0.
*/
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }
.ARM.attributes 0 : { KEEP (*(.ARM.attributes)) }
/DISCARD/ : { *(.note.GNU-stack) }
}
Can anyone spot an error in linker file or give me a hint, where to look next?
Thank you for reading, Paule
PS: Here's some output of the ELF file section headers, so that it's clear there are no overlapping sections.
Sections:
Idx Name Size VMA LMA File off Algn
0 .startup 0000033c 00100000 00100000 00008000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .ramvect 00000040 00200000 00200000 00030000 2**0
ALLOC
2 .bootloader 000001cc 00200040 0010033c 00010040 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
3 .text 0000ce08 00104000 00104000 00014000 2**3
CONTENTS, ALLOC, LOAD, READONLY, CODE
4 .ARM.exidx 000000f0 00110e08 00110e08 00020e08 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .data 0000129c 00200210 00110ef8 00028210 2**3
CONTENTS, ALLOC, LOAD, DATA
6 .bss 000008c8 002014ac 00112194 000294ac 2**2
ALLOC
7 .debug_aranges 000009b8 00000000 00000000 000294b0 2**3
CONTENTS, READONLY, DEBUGGING
8 .debug_info 0002166d 00000000 00000000 00029e68 2**0
CONTENTS, READONLY, DEBUGGING
9 .debug_abbrev 00006cb4 00000000 00000000 0004b4d5 2**0
CONTENTS, READONLY, DEBUGGING
10 .debug_line 00007db7 00000000 00000000 00052189 2**0
CONTENTS, READONLY, DEBUGGING
11 .debug_frame 0000232c 00000000 00000000 00059f40 2**2
CONTENTS, READONLY, DEBUGGING
12 .debug_str 0000682a 00000000 00000000 0005c26c 2**0
CONTENTS, READONLY, DEBUGGING
13 .debug_loc 00016421 00000000 00000000 00062a96 2**0
CONTENTS, READONLY, DEBUGGING
14 .comment 00000011 00000000 00000000 00078eb7 2**0
CONTENTS, READONLY
15 .ARM.attributes 0000002e 00000000 00000000 00078ec8 2**0
CONTENTS, READONLY
16 .debug_ranges 00000968 00000000 00000000 00078ef6 2**0
CONTENTS, READONLY, DEBUGGING