初始化好了sdram之后,下面就试一下把sram中的前4k搬到sdram中并跳转到链接地址处执行,这样就不用老是担心写的代码是不是位置无关(PIC)的了,下面是程序的所有文件。
-
root@ubuntu:~/myboot# tree
-
.
-
├── main.c
-
├── Makefile
-
├── sdram.c
-
├── start.S
-
└── u-boot.lds
-
0 directories, 5 files
1. start.S
-
.text
-
.global _start
-
_start:
-
/*关闭看门狗*/
-
ldr r0, =0x53000000
-
mov r1, #0x0
-
str r1, [r0]
-
-
/*初始化系统时钟: FCLK=400M HCLK=100M PCLK=50M */
-
#define COCKTIME 0x4C000000
-
#define MPLLCON 0x4C000004
-
#define UPLLCON 0x4C000008
-
#define CLKCON 0x4C00000C
-
#define CLKSLOW 0x4C000010
-
#define CLKDIVN 0x4C000014
-
#define CAMDIVN 0x4C000018
-
/*FCLK:HCLK:PCLK=1:4:8*/
-
ldr r0, =CLKDIVN
-
mov r1, #0x05
-
str r1, [r0]
-
-
mrc p15, 0, r0, c1, c0, 0
-
orr r0, r0, #0xc0000000
-
mcr p15, 0, r0, c1, c0,0
-
-
/*MPLL=(2*m*Fin)/(P*(1<
-
/*UPLL=(m*Fin)/(P*(1<
-
ldr r0, =0x10000
-
1:
-
sub r0, r0, #1
-
bne 1b
-
-
/*设置栈,因为下一步要调用c函数init_sdram*/
-
ldr sp, =1024*4
-
bl init_sdram
-
-
/*sdram初始化好之后,重新设置栈到内存 0x33d80000+128k*/
-
ldr sp, =0x33dA0000
-
-
/*复制 steppingstone 到内存: r0=src r1=dest r2=size=4k*/
-
mov r0, #0x0
-
ldr r1, =0x33d80000
-
ldr r2, =1024*4
-
-
copy_loop:
-
ldmia {r3-r10} /* copy from source address [r0] */
-
stmia {r3-r10} /* copy to target address [r1] */
-
cmp r0, r2 /* until source end addreee [r2] */
-
ble copy_loop
-
-
/*跳转到main中 此处bl与ldr跳转不一样*/
-
/*bl main*/
-
ldr pc, _main
-
loop:
-
b loop
-
_main: .word main
2. main.c
-
#define GPBCON (*(volatile unsigned int *) 0x56000010)
-
#define GPBDAT (*(volatile unsigned int *) 0x56000014)
-
-
static inline void delay (unsigned long loops)
-
{
-
__asm__ volatile ("1:\n"
-
"subs %0, %1, #1\n"
-
"bne 1b":"=r" (loops):"0" (loops));
-
}
-
/* 闪灯测试: sram快 sdram稍慢 */
-
void main(void)
-
{
-
int i = 1;
-
GPBCON = 0x15400;
-
while(1)
-
{
-
GPBDAT = 0x7FF&(~i<<5);
-
i *= 2;
-
if(16==i)
-
i = 1;
-
delay(400000);
-
}
-
return ;
-
}
3. sdram.c 与 u-boot.lds都无改动
4. Makefile 中 OBJS := start.o main.o sdram.o
5. 把start.S中的ldr pc, _main 改为 bl main, 编译后分别烧到板子中,可以发现程序运行在sram比sdram中灯闪烁的速度快一些。
把这两个程序反汇编进行比较:
-
root@ubuntu:~/myboot# diff u-boot.dis_sdram u-boot.dis_sram
-
44c44
-
< 33d80084: e59ff000 ldr pc, [pc, #0] ; 33d8008c <_main>
-
---
-
> 33d80084: eb000008 bl 33d800ac
ldr pc, [pc, #0]
把当前pc地址处的值赋给pc,当前pc=(0x33d80084+8)-0x33d80000=0x008C, 0x008C处的值为0x33d800ac,所以执行这条指令后pc指向了0x33d800ac,也就是内存中main函数的入口地址。
33d80084: eb000008 bl 33d800ac
以当前pc地址进行相对跳转,当前pc=(0x33d80084+8)-0x33d80000=0x008C,根据跳转的指令格式可知跳转到的地址为:0x8C+8<<2=0xAC,执行这条指令的后pc指向了0xAC, 还是在sram中的main函数的入口地址。
注意:1. 虽然反汇编文件中的地址都是0x33d80000,但是实现上程序并没有运行在0x33d80000,而是运行在0x0地址,所以在计算时要减去0x33d80000.同时虽然地址不吻合,但是地址里面的值却是正确的,可以放心用。
2. arm9五级流水,pc地址要加8,至于为什么可以看下面:
3. eb000008 转为二进制
1110 1011 0000 0000 0000 0000 1000
1110: always
101:
1: 说明这是一条bl指令
0000 0000 0000 0000 1000: word 对齐,最右边两位总是0,所以省略,计算时需要向左移两位,即乘以4。
出自《ARM7TDMI-S Data Sheet》chapter_4 “arm instruction set”
阅读(2797) | 评论(0) | 转发(1) |