加入收藏 | 设为首页 | 会员中心 | 我要投稿 济南站长网 (https://www.0531zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

U-Boot移植过程中的运行地址和装载地址的差异

发布时间:2021-11-22 13:41:04 所属栏目:教程 来源:互联网
导读:uboot移植涉及到底层硬件的设置,因此需要掌握UART、系统时钟频率、NOR FLASH、NAND FLASH、SDRAM、网卡、存储控制器等硬件的功能及配置,这些都可以参照相应开发板的芯片手册来完成,没有什么大的问题。在移植过程中,一直困扰我的是PIC(代码无关性)问题,

uboot移植涉及到底层硬件的设置,因此需要掌握UART、系统时钟频率、NOR FLASH、NAND FLASH、SDRAM、网卡、存储控制器等硬件的功能及配置,这些都可以参照相应开发板的芯片手册来完成,没有什么大的问题。在移植过程中,一直困扰我的是PIC(代码无关性)问题,即运行地址和加载地址的区别,看过网上很多关于这两者的介绍,感觉懂一点,却一直不知所然。在参考大量的文献下,算是得了一点心得。
    首先来了解下运行地址及加载地址的区别
    运行地址:也叫链接地址,是程序定位的绝对地址,即在编译连接时确定的地址。如果程序中有位置相关指令,程序在运行时,程序必须在运行地址上。
    加载地址:程序放置的位置。
    运行地址和加载地址的值有时相等,有时却不相等,所以这给初学者带来很大的困扰。为了弄清楚这个问题,还得从NOR FLASH,NAND FLASH,S3C2440内部4KB RAM的映射说起。
   
    左边表示从NOR FLASH启动时的映射,右边表示从NAND FLASH启动时的映射。
    这里只讨论从NOR FLASH启动的情况,从图中可以看出NOR FLASH映射到了0X00000000的起始位置,假如UBOOT的代码存放在NOR FLASH上,即装载地址为0X00000000。再来看看UBOOT的链接地址,代码在board/smdk2410/U-Boot.lds里。
 
    连接脚本文件lds中没有设置LMA,只是设置了VMA。VMA的设置是通过顶层目录下的config.mk文件中的LDFLAGS实现的
     
    在board/smdk2410/config.mk定义了TEXT_BASE = 0x33F80000(SDRAM),即程序的运行地址
查看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
 
    此时装载地址和运行地址明显不一样,为什么程序还能运行呢?这里就涉及到PIC----代码无关设计方面的知识了。在汇编语言中,像bl、b、adr(adr属于伪指令,一般被编译器解释成sub指令)指令属于位置无关指令,不管程序装载在哪个位置上,bl、b、adr指令都能正确的运行,其原因是bl、b、adr指令的地址域是基于PC的相对偏移寻址,相当于[pc+offset]。当ARM启动时,ARM自动取0x00000000位置上的指令,此时PC=0x00000000。
基于PC偏移量的指令都能正确的执行。所以uboot第一阶段指令都能执行的原因在于此。
    但我们回顾一下u-boot的启动过程中的第一阶段有将u-boot代码复制到SDRAM中,并跳到SDRAM中去运行,因为SDRAM映射到了BANK6,其地址为0x30000000,此时uboot代码的地址范围从 TEXT_BASE----TEXT_BASE+size(u-boot),程序是如何跳转的呢?跳转到SDRAM为何还能运行呢?这里就需要看下cpu/arm920t/start.S中的relocate标号。
 
    relocate: 把norflash中的代码复制到_TEXT_BASE处,在board/smdk2410/config.mk定义了TEXT_BASE = 0x33F80000,这个地址属于BANK6的范围。也就是把代码复制到从_TEXT_BASE地址开始的SDRAM中,当然在复制之前是要初始化SDRAM的,要不然SDRAM没法使用。至此,代码已复制到SDRAM中,那么就要跳到SDRAM中去运行,跳转之前要做stack设置,清BSS,这些就不说了。下面来说如何跳转的,请看下面这条指令。
    ldrpc, _start_armboot
    ldr伪指令中目的寄存器如果是pc,则ldr是与位置相关的指令,u-boot.map文件可以看出,_start_armboot=0x33f80044, 即pc=0x33f80004。这样uboot就跳到SDRAM上去运行了,且这条指令刚好处在其运行地址处,所以程序就能正确的运行。linux

(编辑:济南站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读