Uboot 運行時內存的分配 -- 轉


u-boot鏈接分析
http://www.rritw.com/a/bianchengyuyan/C__/20130312/279763.html

一個典型的嵌入式系統中,bootloader代碼放在NOR Flash或NAND Flash里面,系統加電或復位后,首先運行這段代碼。通常把bootloader代碼放在NOR Flash里面,NAND Flash由於硬件原因不能隨機訪問,需要特殊的硬件支持機制。

bootloader代碼除了初始化以外就是搬運程序,即地址重定位(relocate)。我們為什么需要relocate?主要是經濟方面和速度方面的原因。經濟方面,NOR Flash和NAND Flash每兆價格相差懸殊,bootloader代碼一般在幾十到幾百K大小,而應用程序通常都很大,幾M到幾十M的大小,所以用價格低廉的NAND Flash存儲。速度方面,程序在NOR Flash里執行的速度遠遠小於在SDRAM中執行的速度,為了追求更高的速度,也需要relocate,讓程序在SDRAM里面執行。

relocate涉及到加載域(VMA)和運行域(LMA)兩個概念。加載域是程序代碼在ROM、FLASH中的排列次序及地址安排,運行域是程序運行時代碼在SRAM、SDRAM中地址安排。存儲代碼時按照加載域存放在FLASH中,運行時再從FLASH中取出代碼到RAM運行域運行,一段代碼的加載域和存儲域可以不同。(可以參考杜春雷的《arm體系結構與編程》一書的有關章節)。

以smdk2410為例,密切相關的就兩個文件夾/board/smdk2410和/cpu/arm920t,里面核心文件就u-boot.lds 、config.mk 、start.S。

/cpu/arm920t/u-boot.lds
        OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
        OUTPUT_ARCH(arm)
        ENTRY(_start)
        SECTIONS
        {
                . = 0x00000000; // 從0地址起始

        . = ALIGN(4);
                .text :
                {
                        cpu/arm920t/start.o (.text)
                        *(.text)
                }

        . = ALIGN(4);
                .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }

        . = ALIGN(4);
                .data : { *(.data) }

        . = ALIGN(4);
                .got : { *(.got) }

        . = .;
                __u_boot_cmd_start = .;
                .u_boot_cmd : { *(.u_boot_cmd) }
                __u_boot_cmd_end = .;

        . = ALIGN(4);
                __bss_start = .;
                .bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
                _end = .;
        }

連接腳本文件lds中沒有設置LMA,只是設置了VMA。VMA的設置是通過頂層目錄下的config.mk文件中的LDFLAGS實現的,TEXT_BASE在/board/smdk2410/config.mk中定義為0x33F80000(SDRAM地址)。

LDFLAGS += -Bstatic -T $(obj)u-boot.lds $(PLATFORM_LDFLAGS)
        ifneq ($(TEXT_BASE),)
        LDFLAGS += -Ttext $(TEXT_BASE)
        endif

查看u-boot.map文件,代碼的連接地址是從0x33F80000開始的。

167 .text         0x33f80000        0x232c8
        168        cpu/arm920t/start.o(.text)
        169        .text                0x33f80000                0x4a0 cpu/arm920t/start.o
        170                                0x33f80048                _bss_start
        171                                0x33f8004c                _bss_end
        172                                0x33f80044                _armboot_start
        173                                0x33f80000                _start
        174        board/samsung/fs2410/lowlevel_init.o(.text)
        175        .text                0x33f804a0         0x64 board/samsung/fs2410/lowlevel_init.o
        176                                0x33f804a4                lowlevel_init
        177        board/samsung/fs2410/nand_read.o(.text)
        178        .text                0x33f80504        0xe8 board/samsung/fs2410/nand_read.o
        179                                0x33f80504                wait_idle
        180                                0x33f80518                nand_read_ll

bootloader代碼上電之后之所以能夠正確執行,有個很重要的原因,就是最初執行的bootloader代碼是地址無關的,即這個映象文件可以被放在內存中的任何一個地址上運行。

對於地址無關的代碼, 尋址是基於pc值的, 在pc值上+/-一個偏移值得到運行地址,如跳轉指令B。當執行完代碼搬運,就需要跳到和地址相關的地方去執行,即RAM中。一般是跳轉到一個標號,這時地址相關代碼就開始運行了,如:ldr pc,_start_armboot。

因為在bin映象生成的時候,就已經把_start_armboot這個符號和實際地址綁定在一起,當執行ldr pc,_start_armboot 語句時,程序就從在ROM中執行跳入到RAM中了,前提是進行了代碼搬移。如果沒有代碼搬運就執行ldr pc,_start_armboot,因為RAM中沒有正確的可執行代碼,程序就馬上飛掉了,所有在搬運之前不能尋址絕對地址有關代碼,必須執行代碼地址無關.

下面的代碼是從NOR Flash向SDRAM搬運的代碼:

relocate:
                adr r0, _start
                ldr r1, _TEXT_BASE
                cmp r0, r1
                beq stack_setup
                ldr r2, _armboot_start
                ldr r3, _bss_start
                sub r2, r3, r2
                add r2, r0, r2
        copy_loop:
                ldmia r0!, {r3-r10}
                stmia r1!, {r3-r10}
                cmp r0, r2
                ble copy_loop

注意其中的 adr r0, _start,這是一條偽指令,一般被編譯器替換為sub r0, pc,#offset ,不要理解為讀取符合表中_start符號的地址(0x33F80000)。上電開始執行時,pc從0開始,所以現在r0值為0+offset,不等於_TEXT_BASE(0x33F80000)。接下來要用到鏈接時確定的符號地址_armboot_start(0x33F80044)了,把_start:0x0 (NOR Flash)里的.text、.data的代碼往SDRAM里_TEXT_BASE確定的地址: 0x33f80000搬運。s3c2410的SDRAM基地址是0x3000_0000,由於uboot支持的這個board SDRAM64M(0x3000_0000-0x3400_0000),所以把u-boot.bin搬運到內存的高端地址.然后跳到內存中執行,提高速度。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM