程序主要的任务是:初始化SDRAM,然后将nand flash的前4k代码拷贝到SDRAM的前4k. 根据S3C2440的手册,我们知道bank6,7是可以外接SDRAM的,那么sdram的起始地址是:0x30000000(参考芯片手册即可).
初始化SDRAM,往往需要配置如下的几个寄存器:
1:BWSCON
这个寄存器包括三部分:STx, WSx, DWx.
STx:启动/禁止 SDRAM的数据掩码引脚,对于SDRAM,此位为0; 对于SRAM,此位为1;
WSx:是否使用存储的WAIT信号, 通常我们设置为0;
DWx: 使用两位来设置响应的bank的位宽,对于我们的开发板, bank 6,7是32位宽的,而bank1~bank5是16位宽的
2:BANKCONx(x为0~5)
这个寄存器用来控制BANK0~BANK5外接设备的访问时序,使用默认的0x0700即可满足开发板所接个外设的要求.
3:BANKCONx(x为6,7)
在开发板8个bank中,只有BANK 6,7是可以外接SDRAM或SRAM的, 所以这个寄存器BANK 6,7与BANK0~5的配置是有所不同的.
MT: 用于设置是SDRAM还是SRAM,我们是SDRAM
Trcd: RAS to CAS delay, 设为推荐值:0b01
SCAN:SDRAM的列地址位数, 对于本开发板,我们的列数是9
4:REFRESH
REFEN: 禁止/开启 SDRAM刷新的功能
TREFMD: SDRAM的刷新模式
Trp:设为0即可
Tsrc: 设为默认值0b11即可
Refresh Counter: 这个计算有个公式:
R_CNT = 2 ^11 + 1 -SDRAM时钟频率(MHz) * SDRAM刷新周期(uS)
SDRAM的刷新周期可以在SDRAM的手册HY57V561620.pdf上可以看到:8192 refresh cycles / 64ms,所以刷新周期 = 64ms/8192 = 7.8125 us
SDRAM的始终频率等于晶振频率12MHz
现在可以计算出R_CNT = 2 ^11 + 1 -12 * 7.8125 = 1955
5:BANKSIZE
这个寄存器我们在乎的是BK76MAP,设置BANK 6,7的大小,我们开发板的大小事64MB的.
6:MRSRBx
这个寄存器能修改的只有位CL, 这个是SDRAM的一个时间参数,我们的板子支持的是2clocks 或者 3 clocks.
代码如下:
head.S
.equ MEM_CTL_BASE, 0X48000000 .equ SDRAM_BASE, 0x30000000 .text .global _start _start: bl disable_watch_dog bl memsetup bl copy_steppingstone_to_sdram ldr pc, =on_sdram on_sdram: ldr sp, =0x34000000 bl main halt_loop: b halt_loop disable_watch_dog: mov r1, #0x53000000 mov r2, #0 str r2, [r1] mov pc, lr copy_steppingstone_to_sdram: mov r1, #0 ldr r2, =SDRAM_BASE mov r3, #4*1024 l: ldr r4, [r1], #4 str r4, [r2], #4 cmp r1, r3 bne l mov pc, lr memsetup: mov r1, #MEM_CTL_BASE adrl r2, mem_cfg_val add r3, r1, #52 L: ldr r4, [r2], #4 str r4, [r1], #4 cmp r1, r3 bne L mov pc, lr .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 GPBCON (*(volatile unsigned long *)0x56000010) #define GPBDAT (*(volatile unsigned long *)0x56000014) #define GPB5_out (1<<(5*2)) #define GPB6_out (1<<(6*2)) #define GPB7_out (1<<(7*2)) #define GPB8_out (1<<(8*2)) void wait(volatile unsigned long dly) { for (; dly > 0; dly--); } int main(void) { unsigned long i = 1; GPBCON = GPB7_out|GPB5_out|GPB6_out|GPB8_out; while (1) { wait(30000); GPBDAT = ~(i << 5); if (++i == 8) i = 1; } }
Makefile
sdram.bin: head.S leds.c arm-elf-gcc -c leds.c -o leds.o arm-elf-gcc -c head.s -o head.o arm-elf-ld -Ttext=0x30000000 head.o leds.o -o sdram_elf arm-elf-objcopy -O binary -S sdram_elf sdram.bin arm-elf-objdump -D -m arm sdram_elf > sdram.dis clean: rm -f sdram.dis sdram.bin sdram_elf *.o
文章的脚注信息由WordPress的wp-posturl插件自动生成