freeRTOS链接过程:`_start'的多重定义

时间:2016-11-20 14:35:09

标签: c makefile compilation embedded freertos

我正在尝试为raspberry pi 2编译freeRTOS。这些是我到目前为止尝试的命令:

  1. arm-none-eabi-gcc -march = armv7-a -mcpu = cortex-a7 -mfpu = neon-vfpv4 -mfloat-abi = hard test.c -o test.o

  2. arm-none-eabi-as -march = armv7-a -mcpu = cortex-a7 -mfpu = neon-vfpv4     -mfloat-abi = hard startup.s -o startup.o

  3. arm-none-eabi-ld test.o startup.o -static -Map kernel7.map -o     target.elf -T raspberrypi.ld

  4. 两个上层工作正常。然而,最后一个没有,它给了我以下错误:

    startup.o:在功能_start': (.init+0x0): multiple definition of _ start' test.o ::(。text + 0x6c):首先在这里定义 startup.o:在函数swi_handler': (.init+0x28): undefined reference to vPortYieldProcessor' startup.o:在函数irq_handler': (.init+0x38): undefined reference to vFreeRTOS_ISR' startup.o:在函数zero_loop': (.init+0xcc): undefined reference to rpi_cpu_irq_disable'

    这是相应的代码:

    test.c:

    #include <stdio.h>
    
    void exit(int code)
    {
        while(1)
            ;
    }
    
    int main(void)
    {
    
        return 0;
    }
    

    startup.s:

    .extern system_init
    .extern __bss_start
    .extern __bss_end
    .extern vFreeRTOS_ISR
    .extern vPortYieldProcessor
    .extern rpi_cpu_irq_disable
    .extern main
        .section .init
        .globl _start
    ;; 
    _start:
        ;@ All the following instruction should be read as:
        ;@ Load the address at symbol into the program counter.
    
        ldr pc,reset_handler        ;@  Processor Reset handler         -- we will have to force this on the raspi!
        ;@ Because this is the first instruction executed, of cause it causes an immediate branch into reset!
    
        ldr pc,undefined_handler    ;@  Undefined instruction handler   -- processors that don't have thumb can emulate thumb!
        ldr pc,swi_handler          ;@  Software interrupt / TRAP (SVC) -- system SVC handler for switching to kernel mode.
        ldr pc,prefetch_handler     ;@  Prefetch/abort handler.
        ldr pc,data_handler         ;@  Data abort handler/
        ldr pc,unused_handler       ;@  -- Historical from 26-bit addressing ARMs -- was invalid address handler.
        ldr pc,irq_handler          ;@  IRQ handler
        ldr pc,fiq_handler          ;@  Fast interrupt handler.
    
        ;@ Here we create an exception address table! This means that reset/hang/irq can be absolute addresses
    reset_handler:      .word reset
    undefined_handler:  .word undefined_instruction
    swi_handler:        .word vPortYieldProcessor
    prefetch_handler:   .word prefetch_abort
    data_handler:       .word data_abort
    unused_handler:     .word unused
    irq_handler:        .word vFreeRTOS_ISR
    fiq_handler:        .word fiq
    
    reset:
        /* Disable IRQ & FIQ */
        cpsid if
    
        /* Check for HYP mode */
        mrs r0, cpsr_all
        and r0, r0, #0x1F
        mov r8, #0x1A
        cmp r0, r8
        beq overHyped
        b continueBoot
    
    overHyped: /* Get out of HYP mode */
        ldr r1, =continueBoot
        msr ELR_hyp, r1
        mrs r1, cpsr_all
        and r1, r1, #0x1f   ;@ CPSR_MODE_MASK
        orr r1, r1, #0x13   ;@ CPSR_MODE_SUPERVISOR
        msr SPSR_hyp, r1
        eret
    
    continueBoot:
        ;@  In the reset handler, we need to copy our interrupt vector table to 0x0000, its currently at 0x8000
    
        mov r0,#0x8000                              ;@ Store the source pointer
        mov r1,#0x0000                              ;@ Store the destination pointer.
    
        ;@  Here we copy the branching instructions
        ldmia r0!,{r2,r3,r4,r5,r6,r7,r8,r9}         ;@ Load multiple values from indexed address.       ; Auto-increment R0
        stmia r1!,{r2,r3,r4,r5,r6,r7,r8,r9}         ;@ Store multiple values from the indexed address.  ; Auto-increment R1
    
        ;@  So the branches get the correct address we also need to copy our vector table!
        ldmia r0!,{r2,r3,r4,r5,r6,r7,r8,r9}         ;@ Load from 4*n of regs (8) as R0 is now incremented.
        stmia r1!,{r2,r3,r4,r5,r6,r7,r8,r9}         ;@ Store this extra set of data.
    
    
        ;@  Set up the various STACK pointers for different CPU modes
        ;@ (PSR_IRQ_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
        mov r0,#0xD2
        msr cpsr_c,r0
        mov sp,#0x8000
    
        ;@ (PSR_FIQ_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
        mov r0,#0xD1
        msr cpsr_c,r0
        mov sp,#0x4000
    
        ;@ (PSR_SVC_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
        mov r0,#0xD3
        msr cpsr_c,r0
        mov sp,#0x8000000
    
        ldr r0, =__bss_start
        ldr r1, =__bss_end
    
        mov r2, #0
    
    zero_loop:
        cmp     r0,r1
        it      lt
        strlt   r2,[r0], #4
        blt     zero_loop
    
        bl      rpi_cpu_irq_disable
    
    
        ;@  mov sp,#0x1000000
        b main                                  ;@ We're ready?? Lets start main execution!
        .section .text
    
    undefined_instruction:
        b undefined_instruction
    
    prefetch_abort:
        b prefetch_abort
    
    data_abort:
        b data_abort
    
    unused:
        b unused
    
    fiq:
        b fiq
    
    hang:
        b hang
    
    .globl PUT32
    PUT32:
        str r1,[r0]
        bx lr
    
    .globl GET32
    GET32:
        ldr r0,[r0]
        bx lr
    
    .globl dummy
    dummy:
        bx lr
    

    raspberrypi.ld:

    /**
     * BlueThunder Linker Script for the raspberry Pi!
     *
     *
     *
     **/
    MEMORY
    {
        RESERVED    (r) : ORIGIN = 0x00000000, LENGTH = 32K
        INIT_RAM    (rwx)   : ORIGIN = 0x00008000, LENGTH = 32K
        RAM     (rwx)   : ORIGIN = 0x00010000, LENGTH = 128M
    }
    
    ENTRY(_start)
    
    SECTIONS {
        /*
         * Our init section allows us to place the bootstrap code at address 0x8000
         *
         * This is where the Graphics processor forces the ARM to start execution.
         * However the interrupt vector code remains at 0x0000, and so we must copy the correct
         * branch instructions to 0x0000 - 0x001C in order to get the processor to handle interrupts.
         *
         */
        .init : {
            KEEP(*(.init))
        } > INIT_RAM = 0
    
        .module_entries : {
            __module_entries_start = .;
            KEEP(*(.module_entries))
            KEEP(*(.module_entries.*))
            __module_entries_end = .;
            __module_entries_size = SIZEOF(.module_entries);
        } > INIT_RAM
    
    
        /**
         *  This is the main code section, it is essentially of unlimited size. (128Mb).
         *
         **/
        .text : {
            *(.text)
        } > RAM
    
        /*
        * Next we put the data.
        */
        .data : {
            *(.data)
        } > RAM
    
        .bss :
        {
            __bss_start = .;
            *(.bss)
            *(.bss.*)
            __bss_end = .;
        } > RAM
    
    /*    
        __exidx_start = .;
        .ARM.exidx :
        {
            *(.ARM.exidx* .gnu.linkonce.armexidx.*)
        } > RAM
        __exidx_end = .;
    */
        /**
         *  Place HEAP here???
         **/
        PROVIDE(__HEAP_START = __bss_end );
        /**
         *  Stack starts at the top of the RAM, and moves down!
         **/
        _estack = ORIGIN(RAM) + LENGTH(RAM);
    }
    

    正如您所看到的,test.c不包含名为_start的入口点,它的汇编编译形式也没有。只有startup.s确实。

    关于如何解决当前问题的任何想法?

    编辑:如果需要,可以在此处找到所有代码:https://github.com/jameswalmsley/RaspberryPi-FreeRTOS

0 个答案:

没有答案