转载请注明原地址:http://blog.csdn.net/oyhb_1992/article/details/76836821
一、
ldr指令的两种用法:
1、 ldr pc,=label ;这里的ldr不是arm指令,而是伪指令。
这个时候与MOVE很相似,只不过MOV指令后的立即数是有限制的,并且MOV指令后的立即数是用#符号,而ldr是用=符号。
MOV这个立即数必须是0X00-OXFF范围内的数经过偶数次右移得到的数,所以MOV用起来比较麻烦,因为有些数不那么容易看出来是否合法。但是ldr伪指令就没有数值大小的限制。
关于LDR伪指令,可以装载一个32bit立即数的说法并不正确,
因为在实际中并不是这一条语句装载了32bit立即数.比如:
ldr r1,=0x70000000
其实真正的汇编代码是将某个地址的值传递给r1,就是说先把0x70000000立即数存放进一个地址,再把这个地址传给r1寄存器,而不是把立即数0x70000000传给r1,在反汇编中。
例如把label标号后的数据或者指令的32位运行地址赋值为pc。运行地址 = 链接地址 + 这些数据或指令相对于程序起始地址的偏移。
当用于跳转时mov pc,func是相对跳转,ldr PC,func是绝对跳转。要注意区别。
2、 ldr pc, label 这是arm里的装载指令,即把label后的数据或者指令内容赋值给pc。
例如:ldr R0,[R1];将存储器R1里的数据读入寄存器R0
1.2再举例子如:
ldr r2, _armboot_start [1]
ldr r2, =_armboot_start [2] 是不同的,
[1]可以理解为将变量_armboot_start的值即_start送入r2,是装载指令.
[2]则是将_armboot_start所在的地址送入r2. 相当于C中的 &_armboot_start(取地址操作).
二、
以u-boot中lowlevel_init初始化内存函数的一段代码说明ldr指令的用法。
代码功能:初始化sdram,将SDRDATA标号后的13个4字节的数据写入以BWSCON寄存器为起始地址的连续13个寄存器。
实现过程:
1、u-boot的链接地址为_TEXT_BASE,即0x33f80000。这是u-boot在sdram中执行的起始地址。
2、u-boot烧写完成后,实际的初始化数据是在sram当中,因为烧写是烧写到NandFlash的0地址,然后前面4k被拷贝到sram垫脚石中(后续需要把所有内容拷贝到sdram中)。要获得这些初始化数据在sram垫脚石中的地址,只要求取这些数据相对于链接地址的偏移后即可即是是相对于垫脚石0X0000 0000地址的地址。
之所以要求偏移是因为u-boot前4K拷贝到SRAM垫脚石中,而垫脚石的起始地址是0X0000 0000,然后代码从地址0X0000 0000绝对地址处开始执行,但是它的链接地址是_TEXT_BASE,而我们要获得SMRDATA地址的绝对地址,则要用链接地址相减SMRDATA-_TEXT_BASE再加上绝对起始地址0X0000 0000就是SMRDATA的绝对地址了,也就是SMRDATA在SRAM中的地址了。
链接地址只有在代码搬运到SDRAM内存后才有真正的物理作用。
3、 ldr r0, =SMRDATA 伪指令。这条指令获取SMRDATA 后数据的地址,即初始化数据在sdram中的地址(是绝对地址)。因为链接地址的设置,使得ldr这条指令指向了代码应该允许的地址。
4、 ldr r1, _TEXT_BASE 装载指令。获取标号_TEXT_BASE 后的数据内容,即0x33f80000。
5、r0 减去 r1就得到了初始化数据相对于链接地址的偏移了。
#include <config.h>
#include <version.h>
/* some parameters for the board*/
/*
*
* Taken fromlinux/arch/arm/boot/compressed/head-s3c2410.S
*
* Copyright (C) 2002 Samsung ElectronicsSW.LEE <hitchcar@sec.samsung.com>
*
*/
#define BWSCON 0x48000000
/* BWSCON */
#define DW8 (0x0)
#define DW16 (0x1)
#define DW32 (0x2)
#define WAIT (0x1<<2)
#define UBLB (0x1<<3)
#define B1_BWSCON (DW32)
#define B2_BWSCON (DW16)
#define B3_BWSCON (DW16+ WAIT + UBLB)
#define B4_BWSCON (DW16)
#define B5_BWSCON (DW16)
#define B6_BWSCON (DW32)
#define B7_BWSCON (DW32)
/* BANK0CON */
#define B0_Tacs 0x0 /* 0clk */
#define B0_Tcos 0x0 /* 0clk */
#define B0_Tacc 0x7 /* 14clk */
#define B0_Tcoh 0x0 /* 0clk */
#define B0_Tah 0x0 /* 0clk */
#define B0_Tacp 0x0
#define B0_PMC 0x0 /* normal */
/* BANK1CON */
#define B1_Tacs 0x0 /* 0clk */
#define B1_Tcos 0x0 /* 0clk */
#define B1_Tacc 0x7 /* 14clk */
#define B1_Tcoh 0x0 /* 0clk */
#define B1_Tah 0x0 /* 0clk */
#define B1_Tacp 0x0
#define B1_PMC 0x0
#define B2_Tacs 0x0
#define B2_Tcos 0x0
#define B2_Tacc 0x7
#define B2_Tcoh 0x0
#define B2_Tah 0x0
#define B2_Tacp 0x0
#define B2_PMC 0x0
#define B3_Tacs 0x0 /* 0clk */
#define B3_Tcos 0x3 /* 4clk */
#define B3_Tacc 0x7 /* 14clk */
#define B3_Tcoh 0x1 /* 1clk */
#define B3_Tah 0x0 /* 0clk */
#define B3_Tacp 0x3 /* 6clk */
#define B3_PMC 0x0 /* normal */
#define B4_Tacs 0x0 /* 0clk */
#define B4_Tcos 0x0 /* 0clk */
#define B4_Tacc 0x7 /* 14clk */
#define B4_Tcoh 0x0 /* 0clk */
#define B4_Tah 0x0 /* 0clk */
#define B4_Tacp 0x0
#define B4_PMC 0x0 /* normal */
#define B5_Tacs 0x0 /* 0clk */
#define B5_Tcos 0x0 /* 0clk */
#define B5_Tacc 0x7 /* 14clk */
#define B5_Tcoh 0x0 /* 0clk */
#define B5_Tah 0x0 /* 0clk */
#define B5_Tacp 0x0
#define B5_PMC 0x0 /* normal */
#define B6_MT 0x3 /* SDRAM */
#define B6_Trcd 0x1
#define B6_SCAN 0x1 /* 9bit */
#define B7_MT 0x3 /* SDRAM */
#define B7_Trcd 0x1 /* 3clk */
#define B7_SCAN 0x1 /* 9bit */
/* REFRESH parameter */
#define REFEN 0x1 /* Refresh enable */
#define TREFMD 0x0 /* CBR(CAS before RAS)/Auto refresh */
#define Trp 0x0 /* 2clk */
#define Trc 0x3 /* 7clk */
#define Tchr 0x2 /* 3clk */
#define REFCNT 1113 /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */
/**************************************/
_TEXT_BASE:
.word TEXT_BASE
.globl lowlevel_init
lowlevel_init:
/*memory control configuration */
/*make r0 relative the current location so that it */
/*reads SMRDATA out of FLASH rather than memory ! */
ldr r0, =SMRDATA
ldr r1, _TEXT_BASE
sub r0, r0, r1
ldr r1, =BWSCON /*Bus Width Status Controller */
add r2, r0, #13*4
0:
ldr r3, [r0], #4
str r3, [r1], #4
cmp r2, r0
bne 0b
/*everything is fine now */
mov pc, lr
.ltorg
/* the literal pools origin */
SMRDATA:
.word(0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
.word((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
.word((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
.word((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
.word((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
.word((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
.word((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
.word((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
.word((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
.word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
.word 0x32
.word 0x30
.word 0x30
本文详细解析了ARM汇编语言中的ldr指令两种用法及其应用场景。通过具体实例介绍了ldr伪指令与装载指令的区别,同时深入探讨了在u-boot初始化内存函数中ldr指令的具体实现过程。

7156

被折叠的 条评论
为什么被折叠?



