如何使用LD在程序段中放置ARM复位向量

时间:2015-06-09 00:09:02

标签: c linker arm linker-scripts

我有ARM A5 Microprocessor有两个主要内存段。当它启动时,hardware bootloader (see page 64)加载我写入sram的64k软件引导加载程序。然后,软件引导加载程序从闪存芯片中读取.elf文件并将其加载到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.

我想将我的应用程序代码编译并链接到.elf文件中,以便创建2个程序段。一个程序段应包含向量表,位于0x0000_0000,另一个应包含.text,.data和.bss段,并放在地址0x2000_0000处。

重要的是要强调程序段和节之间的区别。阅读herehere, page 1-1 (note the difference between "linking view" and "execution view"

使用我现在拥有的链接描述文件,.vectors将映射到输出部分,但它不会出现在程序段中。

我认为像这样添加一个PHDRS部分:

PHDRS
{
    vectors PT_LOAD; /* at 0x0000_0000 for the vectors*/
    exec PT_LOAD;    /* at 0x2000_0000 for the executable app code*/
}

到我的链接器脚本会解决这个问题,但它只修复了一半:现在我有一个程序段在0x0000_0000,就像我想要的那样,但它的长度是0。

如何将我的*(。vectors)部分放入0x0000_0000的程序段?

感谢。

注意:当我进入办公室并将链接器脚本放在我面前时,我会更清楚地编辑这个问题。

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 ... 
//...................................................

我使用以下链接描述文件:

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__;
}

运行arm-none-eabi-objdump -p ./main.out给出

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]

当我在我的.map文件中搜索" vect"时,我得到以下内容

.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 个答案:

没有答案