zoukankan      html  css  js  c++  java
  • 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搬运到内存的高端地址.然后跳到内存中执行,提高速度。

  • 相关阅读:
    《人类简史》八、融合统一(下)——宗教的法则、历史的混沌
    《今日简史》七、融合统一(中)——帝国的愿景
    《人类简史》六、融合统一(上)——历史的方向、金钱的味道
    《人类简史》五、监狱高墙——想象构建的秩序
    设计模式之职责链模式(Chain of Responsibility)
    设计模式之代理模式(Proxy)
    设计模式之享元模式(FlyWeight)
    设计模式之外观模式(Facade)
    设计模式之装饰模式(Decorator)
    设计模式之组合模式(Composite)
  • 原文地址:https://www.cnblogs.com/chenchenluo/p/3129383.html
Copyright © 2011-2022 走看看