启动代码的分析之ADR,LDR辨析

来源:互联网 发布:软件使用手册标准 编辑:程序博客网 时间:2024/05/17 07:01

.equ sdram_base,   0x30000000

.equ mem_ctl_base,        0x48000000

.text

.global _start

_start:

         blclose_watch_dog

         blinit_mem

         blcopy_steppingstone2sdram

         ldrpc,=sdram

sdram:

         blinit_sp

         blmain

loop:

         bloop

        

close_watch_dog:

         ldrr0,=0x53000000

         ldrr1,=0;

         strr1,[r0]

         movpc,lr

        

init_sp:

         ldrsp,=0x34000000

         movpc,lr

 

init_mem:

         adrlr0,init_mem_data @不要写成ldr,否则就会进入0x3000000**,现在是初始化内存,还在片内SRAM中(0x000000**)

         addr1,r0,#52

         ldrr2,=mem_ctl_base

init_mem_loop:

         ldrr3,[r0],#4

         strr3,[r2],#4

         cmpr0,r1

         bneinit_mem_loop

         movpc,lr

        

copy_steppingstone2sdram:

         ldrr0,=0           @片内4K内存,也是SDRAM的前4K字节

         ldrr1,=sdram_base @sdram的起始地址

         ldrr3,=4096     @复制终止的标志

copy_loop:

         ldrr2,[r0],#4

         strr2,[r1],#4

         cmpr0,r3

         bnecopy_loop

         movpc,lr

        

.align 4

init_mem_data:

         .long0x22011110

         .long0x00000700

         .long0x00000700

         .long0x00000700

         .long0x00000700

         .long0x00000700

         .long0x00000700

         .long0x00018005

         .long0x00018005

         .long0x008c07a3

         .long0x000000b1

         .long0x00000030

         .long0x00000030   

         上面是2440的启动代码。看了韦东山老师的书发现。Ldr pc,=sdram紧接着下一跳语句就是sdram标号。开始的时候在想直接就把这里两句多余的删掉不就行了吗?仔细分析程序的过程才知道为什么要留下这个。

         实验的环境是在NANDFLASH下启动。

(1)      将NAND FLASH的前4K内存放入到2440的片内SRAM(steppingstone)中。

(2)      在2440片内的SRAM中执行。关闭看门狗,设置堆栈指针,设置内存。

(3)      然后将片内SRAM(steppingstone)也就是的内容拷贝到外接的内存SDRAM中。

(4)      这是,我们就想进入内存空间更大的外接内存SDRAM中去执行程序。

Arm-linux-ld –Ttext 0x30000000 **********

上面是Makefile里面的代码。因此实际上的地址空间都被映射到以0x30000000为基址的空间中了。但是前面进行的关闭看门狗初始化内存等必须在片内SRAM中和执行。因为,外部的SDRAM必须初始化才能工作。

事实上也正是这样的。初始化看门狗,内存等也正是在片内SRAM中执行的。因为ldr的寻址是32位数的,可以查询到任何位置。而bl的寻址是±32M。所以,刚上电在片内SRAM中执行。然后bl close_watch_dog。虽然close_watch_dog是0x300000**,但是bl指令的寻址范围只能保证它在跳转到0x000000**。而ldr的寻址范围就可以保证pc直接指向0x3000000**。这样就实现了跳转到片外SDRAM。这样也明白了为什么ARM汇编指令的分为ADR,ADRL,LDR等不同的范围的寻址指令。

对于init_mem汇编子程序,由于最开始的写法是ldr r0,init_mem_data。所以,就会将r0设置为0x3000000**。这时执行copy_steppingstone2sdram,也即是在0x300000**被拷入相应的数值,就会造成初始化mem失败。而copy_steppingstone2sdram必须在初始化mem之后。因此,我们就需要用adrl这条指令在相对小的范围寻址。进入片内SRAM的init_mem_data(0x000000**)而不是片外的SDRAM(0x300000**),这样就能得到正确的设置值了。

原创粉丝点击