Chinaunix首页 | 论坛 | 博客
  • 博客访问: 829004
  • 博文数量: 281
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2770
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-02 19:45
个人简介

邮箱:zhuimengcanyang@163.com 痴爱嵌入式技术的蜗牛

文章分类
文章存档

2020年(1)

2018年(1)

2017年(56)

2016年(72)

2015年(151)

分类: 嵌入式

2015-07-22 12:41:28

看了一下lowlevel_init.s里面的代码,发现最难懂的地方当属这里了:
ldr     r0, =SMRDATA
ldr    r1, _TEXT_BASE
sub    r0, r0, r1
ldr    r1, =BWSCON    /* Bus Width Status Controller */
add     r2, r0, #13*4

第一条语句是获取SMRDATA的地址,SMRDATA的定义在此文件的末尾。第二条语句是获取_TEXT_BASE的值,在start.s中,这个值被定义为CONFIG_SYS_TEXT_BASE。而CONFIG_SYS_TEXT_BASE在目标板目录的config.mk中定义,然后在根目录的config.mk中的以下语句中被包含进来。

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

然后查看u-boot.lds文件,就知道整个u-boot最后都被编译到CONFIG_SYS_TEXT_BASE这个地址之后,包括代码段、数据段等内容。
所以SMRDATA也必定是在这个地址之后。而第三句话就是计算SMRDATA相对于CONFIG_SYS_TEXT_BASE的偏移量。接下来的两句就是把控制寄存器的地址赋给r1,将SMRDATA的结束地址赋给r2。

计算好地址之后,后面的代码是一个循环,按照预先的设计设定每个BANK的属性。

刚开始看这个代码的时候不理解为什么要计算偏移量,后来在网上查了一些资料才逐渐明白。这个涉及到芯片的启动过程。现以上面的SDRDATA为例进行说明。

首先使用objdump –d lowlevel_init.o进行反汇编,查看这一部分代码被预编译为以下内容。
lowlevel_init.o:     file format elf32-littlearm

Disassembly of section .text:

00000000 <_text_base>:
   0:    33f80000     .word    0x33f80000

00000004 :
   4:    e59f0020     ldr    r0, [pc, #32]    ; 2c
   8:    e51f1010     ldr    r1, [pc, #-16]    ; 0 <_text_base>
   c:    e0400001     sub    r0, r0, r1
  10:    e3a01312     mov    r1, #1207959552    ; 0x48000000
  14:    e2802034     add    r2, r0, #52    ; 0x34
  18:    e4903004     ldr    r3, [r0], #4
  1c:    e4813004     str    r3, [r1], #4
  20:    e1520000     cmp    r2, r0
  24:    1afffffb     bne    18
  28:    e1a0f00e     mov    pc, lr
  2c:    00000030     .word    0x00000030

00000030 :
  30:    2211d120     .word    0x2211d120
  34:    00000700     .word    0x00000700
  38:    00000700     .word    0x00000700
  3c:    00000700     .word    0x00000700
  40:    00001f4c     .word    0x00001f4c
  44:    00000700     .word    0x00000700
  48:    00000700     .word    0x00000700
  4c:    00018005     .word    0x00018005
  50:    00018005     .word    0x00018005
  54:    008e0459     .word    0x008e0459
  58:    00000032     .word    0x00000032
  5c:    00000030     .word    0x00000030
  60:    00000030     .word    0x00000030

可知SMRDATA的地址就是当前PC值偏移32,在实际运行的时候就是lowlevel的入口地址加32。

再在根目录下使用objdump –d u-boot就可以查到最终的生成文件中lowlevel_init的入口地址了,由于在链接的时候指定了代码段的首地址为0x33f80000,所以lowlevel的入口地址是代码段的首址加上一个偏移量,这样就可以算出SMRDATA的地址就是0x33f80000+lowlevel_init入口的偏移量+SMRDATA本身的段内偏移量。查看uboot根目录底下的System.map文件可知lowlevel_init的地址是0x33f80bf0,SMRDATA的地址是0x33f80c1c。

弄清楚了这些地址之后再回到开头的问题,arm9在上电的时候如果硬件跳线选择的是从NAND FLASH启动的话,会将NAND FLASH开头的4K内容拷贝到一个叫“stepping stone”的空间中,其首地址是0x0。假设执行到了lowlevel_init里面,还是按照原来的地址去寻找SMRDATA的话,那肯定就找不到了,因为这个时候的代码是运行在0x0~0x00001000这个地址内的,应该去找0x00000c1c这个地址才是正确的。

也就是说:在跳转到SRAM内存中运行之前,都不能直接使用标号标记的全局变量地址,需要转换,算出以"启动地址为零"的时候的全局变量的偏移地址,因为启动的时候是从"零地址"开始的。

--------------------------------------------

问题:如果链接地址是0x00000000,又会有什么问题?



阅读(1435) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~