S3C2440从Nand Flash启动CPU时, CPU会通过硬件动作将Nand Flash开始的4KB数据复制到称为Setppingstone的4KB的内部RAM中,然后跳到地址0开始执行。
本实例先使用汇编语言设置好存储控制器,使外接的SDRAM可用,然后把程序本身从Steppingstone复制到SDRAM ,最后跳到SDRAM中执行。
head.S
@*********************************************************************
@File: head.S
@Function: 设置存储控制器使用SDRAM, 把程序拷到SDRAM里运行.
@*********************************************************************
.equ MEM_CTL_BASE, 0x48000000 @内存控制器的寄存器起始地址
.equ SDRAM_BASE, 0x30000000 @BANK6的起始地址,也就是SDRAM的起始地址
.text
.global _start
_start:
bl disable_watch_dog @关看门狗,否者cpu重启
bl memsetup @设置存储控制器
bl copy_steppingstone_to_sdram @拷贝程序到SDRAM
ldr pc, =on_sdram @跳到SDRAM执行程序
on_sdram:
ldr sp, =0x34000000 @SDRAM的内存范围为0x30000000 ~ 0x33FFFFFF
bl main @跳到c函数
halt_loop:
b halt_loop
disable_watch_dog:
mov r1, #0x53000000 @watch dog寄存器
mov r2, #0x0 @设0
str r2, [r1] @关watch dog
mov pc, lr @返回,往下跑memsetup
copy_steppingstone_to_sdram:
mov r1, #0 @ 源地址
ldr r2, =SDRAM_BASE @ 目的地址
mov r3, #4*1024 @ 拷贝长度
1:
ldr r4, [r1], #4 @ 从Setppingstone读取4字节数据,并让源地址加4
str r4, [r2], #4 @ 把此4字节数据复制到SDRAM中,并让目的地址加4
cmp r1, r3 @ 判断是否拷贝完4K数据
bne 1b @ 若没拷贝完成,继续
mov pc, lr @ 返回
memsetup:
mov r1, #MEM_CTL_BASE @ 寄存器起始地址
adrl r2, mem_cfg_val @ 把寄存器设定值放到r2里
add r3, r1, #52 @
1:
ldr r4, [r2], #4 @ 把设定值放到r4里,并让r2 加4
str r4, [r1], #4 @ 设定寄存器,并让寄存器地址加4
cmp r1, r3 @ 判断是否设定完成
bne 1b @ 没完成,继续
mov pc, lr @返回,往下跑copy_steppingstone_to_sdram
.align 4
mem_cfg_val:
.long 0x22011110 @BWSCON
.long 0x00000700 @BANKCON0
.long 0x00000700 @BANKCON1
.long 0x00000700 @BANKCON2
.long 0x00000700 @BANKCON3
.long 0x00000700 @BANKCON4
.long 0x00000700 @BANKCON5
.long 0x00018005 @BANKCON6
.long 0x00018005 @BANKCON7
.long 0x008c07a3 @REFRESH
.long 0x000000b1 @BANKSIZE
.long 0x00000030 @MRSRB6
.long 0x00000030 @MRSRB7
leds.c
#define GPFCON (*(volatile unsigned long *)0x56000050)
#define GPFDAT (*(volatile unsigned long *)0x56000054)
#define GPF4_out (1<<(4*2))
#define GPF5_out (1<<(5*2))
#define GPF6_out (1<<(6*2))
void wait(volatile unsigned long dly)
{
for(; dly > 0; dly--);
}
int main(void)
{
unsigned long i = 0;
GPFCON = GPF4_out|GPF5_out|GPF6_out; // 将LED1,2,4对应的GPF4/5/6三个引脚设为输出
while(1){
wait(30000);
GPFDAT = (~(i<<4)); // 根据i的值,点亮LED1,2,4
if(++i == 8)
i = 0;
}
return 0;
}
Makefile
sdram.bin : head.S leds.c
arm-linux-gcc -c -o head.o head.S
arm-linux-gcc -c -o leds.o leds.c
arm-linux-ld -Ttext 0x30000000 head.o leds.o -o sdram_elf
arm-linux-objcopy -O binary -S sdram_elf sdram.bin
arm-linux-objdump -D -m arm sdram_elf > sdram.dis
clean:
rm -f sdram.dis sdram.bin sdram_elf *.o