实验目的:利用SDRAM存储代码,来执行流水灯实验
实验原理:s3c2440的启动方式中有 norflash和nandflash启动,对于norfalsh,CPU可以直接从它的0地址访处开始来进行读操作执行代码。但是从nandFlash启动,其访问方式就要复杂一点,其原因是因为是因为CPU是不能直接对nandflash进行读写操作的,CPU只需要进行负责发送指令(eg .STR 或者LDR来告诉储存控制器,具体访问工作由存储控制器来完成)。那么nandflash的启动方式到底是什么样的呢?其过程如下:首先由硬件将nandflash的前4K的内容复制到s3c2440内部存储器(这个4K存储器叫做steppingstong(垫脚石的意思))中,然后CPU从steppingstong进行执行代码。在本程序中,由于是从 nandflash中启动的,这4K代码要做的工作要做的工作,也就是nandflah的启动过程(外加:要坚持从SDRAM来执行代码)的具体描述有:(1)由硬件将nandflash的前4K的内容复制到steppingstong;(2)完成初始化工作:关闭看门狗,初始化存储控制器(即与存储控制器相关的13个寄存器);(3)将 nandflash的代码内容复制到SDRAM中;(4)跳到SDRAM中去执行代码。
实验步骤:首先编写启动代码,完成初始化工作,在CPU执行完初始化工作后,让其跳转到执行流水灯程序
实验代码:初始化代码:head.S 和流水灯源程序led_on_sdram.c
初始化代码:head.S:
.equ MEM_CTL_BASE, 0x48000000
.equ SDRAM_BASE, 0x30000000
.text @ 在GNU中,“@”代表的是注释
.global _start
_start:
bl disable_watch_dog @关闭看门狗
bl memsetup @完成存储器的初始化工作
bl copy_steppingstone_to_sdram @将垫脚石的4K代码内容复制到SDRAM中
ldr pc, =on_sdram @将PC指向SDRAM的首地址,来执行代码
on_sdram:
ldr sp, =0x34000000 @初始化堆栈
bl main @将CPU跳转到main,来执行流水灯实验
halt_loop:
b halt_loop
disable_watch_dog:
mov r1,#0x53000000
mov r2, #0x0
str r2, [r1]
mov pc, lr
memsetup:
mov r1, #MEM_CTL_BASE
adrl r2, mem_cfg_val
add r3, r1,#52
1: ldr r4, [r2],#4
str r4, [r1],#4
cmp r1, r3
bne 1b @这里的“1b”:1是标签,b代表的是backward.即1b代表的是向后跳转到1标签处
mov pc ,lr
copy_steppingstone_to_sdram:
mov r1, #0
ldr r2, =SDRAM_BASE
mov r3, #1024*4
1:
ldr r4, [r1],#4
str r4, [r2],#4
cmp r1, r3
bne 1b
mov pc, lr
.align 4
mem_cfg_val: @这里存储的13个值是用来初始化存储控器的
.long 0x22011110
.long 0x00000700
.long 0x00000700
.long 0x00000700
.long 0x00000700
.long 0x00000700
.long 0x00000700
.long 0x00018005
.long 0x00018005
.long 0x008C07A3
.long 0x000000B1
.long 0x00000030
.long 0x00000030
流水灯源程序led_on_sdram.c:
#define GPFCON (*(volatile unsigned long*)0x56000050)
#define GPFDAT (*(volatile unsigned long*)0x56000054)
void delay(int n)
{
int i,j;
for(i=0;i<n;++i)
for(j=0;j<50;j++) ;
}
int main()
{
int i=0;
while(1)
{
GPFCON=0x00000100;
for(i=0;i<3;i++)
{
delay(1000);
GPFCON=GPFCON<<2;
GPFDAT=0x00000000;
}
}
return 0;
}
实验总结:这里面初始化13个寄存器的值,要学会分析。