I have an ARM A5 Microprocessor with 2 major segments of memory. When it boots up, a hardware bootloader (see page 64) loads a 64k software bootloader that I wrote into sram. The software bootloader then reads an .elf file from a flash memory chip and loads it into ddram.
these are my mcu's most important memories:
sram from 0x0000_0000 - 0x0002_0000
ddram from 0x2000_0000 - 0x2100_0000
note: the datasheet I linked to says that on-mcu ROM containing a hardware bootloader is
mapped to 0x0000. This is true on startup, but I remap the memory as soon as my
bootloader starts up.
note: This 2 stage bootloading process is necessary because the Atmel hardware bootloader
can only load programs up to 64k, and it can only load programs to sram. My
firmware is over 64k and needs to be loaded to ddram, so the Atmel hardware
bootloader loads my own bootloader to sram, and my own bootloader loads my firmware
application code to ddram.
I want to compile and link my application code into an .elf file so that 2 program segments are created. One program segment should contain the vector table, placed at 0x0000_0000, and another should contain the .text, .data, and .bss sections and be placed at address 0x2000_0000.
It is important to emphasize the difference between program segments and sections. Read up here and here, page 1-1 (note the difference between "linking view" and "execution view".
With the linker script that I have right now, .vectors is mapped to an output section, but it does NOT appear in a program segment.
I thought that adding a PHDRS section like this:
PHDRS
{
vectors PT_LOAD; /* at 0x0000_0000 for the vectors*/
exec PT_LOAD; /* at 0x2000_0000 for the executable app code*/
}
to my linker script would fix this problem, but it only fixed it halfway: now I have a program segment at 0x0000_0000 like I want, but its length is 0.
How do I get my *(.vectors) section into a program segment at 0x0000_0000?
Thanks.
note: I will edit this question for more clarity when I get into my office and have my linker scripts in front of me.
crt0.S
.syntax unified
.section .vectors
.global reset_vector
.arm
reset_vector:
ldr pc, =reset_handler
undef_vector:
ldr pc, =undef_vector
svc_vector:
ldr pc, =svc_handler
prefetch_abort_vector:
ldr pc, =prefetch_handler
data_abort_vector:
ldr pc, =data_abort_handler
reserved_vector:
ldr pc, =reserved_vector
irq_vector:
ldr pc, =irq_handler
.section .text
prefetch_handler:
ldr sp, =__irq_stack_end__
mov r0, lr
ldr r1, =prefetch_handler_string
ldr r2, =printloop_fatal
blx r2
data_abort_handler:
ldr sp, =__irq_stack_end__
mov r0, lr
ldr r1, =data_abort_string
ldr r2, =printloop_fatal
blx r2
prefetch_handler_string:
.ascii "prefetch abort\0"
data_abort_string:
.ascii "data abort\0"
.align 4 // instructions must be aligned
// Note that we boot in SVC mode (cpsr & 0x1f == 0x12). We will
// switch to USER mode
reset_handler:
cpsie A // enable abort exceptions
// clear BSS
ldr r0, =__bss_start__
ldr r1, =__bss_end__
mov r2, #0
1:
cmp r0, r1
itt cc
strcc r2, [r0], #4
bcc 1b
// sign stack
ldr r0, =__irq_stack_start__
ldr r1, =__irq_stack_end__
ldr r2, =0x5718a9bf //magic number
1:
cmp r0, r1
it cc
strcc r2, [r0], #4
bcc 1b
//................................
//... lots more init code here ...
//................................
ldr sp, __sram_end__
blx main
msr CPSR, #0x1f // ARM_MODE_USER
svc #0 // invoke scheduler.
b .
//...................................................
//... other handlers are here. not worth showing ...
//...................................................
I am using the following linker script:
ddram.ld
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(reset_vector)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
/**
* The sram is actually 0x20000 long, but we use the top 0x4000 bytes for
* the page translation table.
*/
sram (W!RX) : ORIGIN = 0x000000, LENGTH = 0x1c000
ddr_ebi1 (W!RX) : ORIGIN = 0x20000000, LENGTH = 8M
dma_ddr (!RWX) : ORIGIN = 0x21000000, LENGTH = 8M
}
PHDRS
{
vectors PT_LOAD;
exec PT_LOAD;
}
/* Section Definitions */
SECTIONS
{
/* vectors go at start of sram.*/
.vect :
{
KEEP(*(.vectors));
_vector_end = .;
} > sram AT> sram :vectors
/***/
.text :
{
*(.text*);
*(.CP15*);
. = ALIGN(4);
*(.data*);
*(.rodata*);
_text_end = .;
} >ddr_ebi1 AT> ddr_ebi1 :exec
.bss :
{
. = ALIGN(4);
*(.bss*)
*(COMMON*)
. = ALIGN(4);
__irq_stack_start__ = .;
. = . + 4096;
__irq_stack_end__ = .;
} > ddr_ebi1 AT> ddr_ebi1
__page_translation_table__ = 0x1c000;
__sram_start__ = ORIGIN(sram);
__sram_end__ = ORIGIN(sram) + LENGTH(sram);
__bss_start__ = ADDR(.bss);
__bss_size__ = SIZEOF(.bss);
__bss_end__ = ADDR(.bss) + SIZEOF(.bss);
__heap_start__ = __bss_end__;
__heap_end__ = __sram_end__;
}
running arm-none-eabi-objdump -p ./main.out gives
0x70000001 off 0x0001481c vaddr 0x2000c81c paddr 0x2000c81c align 2**2
filesz 0x00000008 memsz 0x00000008 flags r--
LOAD off 0x00000094 vaddr 0x00000000 paddr 0x00000000 align 2**15
filesz 0x00000000 memsz 0x00000000 flags ---
LOAD off 0x00008000 vaddr 0x20000000 paddr 0x20000000 align 2**15
filesz 0x0000c824 memsz 0x0000de40 flags rwx
private flags = 5000000: [Version5 EABI]
When I search my .map file for "vect", I get the following
.vect 0x00000000 0x38
*(.vectors)
.vectors 0x00000000 0x38 build/crt0.o
0x00000000 reset_vector
0x00000038 _vector_end = .
.text 0x20000000 0xc81c
*(.text*)
.text 0x20000000 0xcb0 build/rtos.o
0x20000024 rtos_init
0x20000028 rtos_wait