Uboot 運行時記憶體的分配 — 轉

來源:互聯網
上載者:User
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搬運到記憶體的高端地址.然後跳到記憶體中執行,提高速度。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.