How can I use LD to place ARM reset vectors in a program segment

1.2k views Asked by At

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
0

There are 0 answers