1.管脚介绍
1)与SDRAM相关管脚:
2)以上接法都可由S3C2440数据手册里寻找到:
红圈里面表示我当前使用开发板外接SDRAM的情况:其中(4Mx8x4B)X2表示使用了2片32M的SDRAM组成64M的内存,其中4 banks/chip,4M/bank,
每一片的数据总线16-bit,但是通过使用两片扩展成x32总线宽度.bank的选择通过地址总线的A[25:24]来选择,以上的选择对应了以下的连线方式:

关于地址总线的连接,因为SDRAM使用了32-bit数据总线,也就是SDRAM的存储单元为4个字节,但是S3C2440的存储单元是1个字节,
所以通过A0管脚接到S3C2440的地址总线管脚A2上,以下依次接下去的方式来使S3C2440每次访问内存时都能对齐在4字节上。
2.相关寄存器(由以上开发板的原理图我们可以知道,我们的SDRAM是挂在Bank6上的):

1)BWSCON相关Pin:

注:
如果是SRAM的话就使用UB/LB,否则不使用.
是否选择WAIT功能:选择否
数据总线宽度:选择32-bit
我的最终配置是:BWSCON[27:24] = 0 0 10B
2)BANKCON6相关Pin:

注:其它Pin用于内存为ROM orSRAM.
MT选择SDRAM,Trcd选择2 clocks就可以了(在下面选择Trp和Tsrc时一起讨论),SCAN是9-bit
我的最终配置是:BANKCON6[16:15]=11B;BANKCON6[3:0]=0001B
3)REFRESH相关Pin:
注:
REFEN使能;
TREFMD选择全刷新,半刷新一般是用在系统休眠时;
Trcd,Trp和Trc都必须满足以下图示条件(图示来自相应SDRAM芯片手册):
其中的上限值没有定死,Trcd和Trp必须大于20ns,Trc最好要大于70ns。HCLK为12MHz表明了一个时钟周期为83ns/clock,
所以在没有使用PLL时,Trcd,Trp和Trc怎么选都是满足要求的。
所以Trp选择2 clocks,Tsrc选择4 clocks。
(需要注意的是:在使用了PLL之后要重新设置,因为条件可能不满足了)
Refresh Counter(刷新计数器)涉及到HCLK,可以看以下图示

从上图可以看出在没有设置PLL时,FCLK逻辑电平是直接由XTlpll(晶振频率12MHz)决定的;在默认情况下HCLK的时钟频率
是跟FCLK一样,而SDRAM使用的时钟频率正是由HCLK提供。
那么Refresh period =(2^11-refresh_count+1)/HCLK (从refresh_count开始计数到溢出时就刷新一次),从下面我对SDRAM对
应型号的datasheet里面的截图可以看出64ms内刷新8192次,这样Refreshperiod = (64ms/8192*1000)us;再由
Refresh count = 2^11+1-12*Refresh period = 0x7A3.
我的最终配置是:REFRESH[23:18]= 1 0 00 00B;REFRESH[10:0] = 0x7A3
4)BANKSIZE相关Pin:

注:
BUTST_EN:选择使能突发操作
SCKE_EN: 选择使能通过SCKE信号来使SDRAM进入省电模式
SCLK_EN: 选择推荐选项(在访问SDRAM期间SCLK才有效,没访问时为"L"电平)
DK76MAP: 选择64MB/64MB
我的最终配置为:BANKSIZE[7:0]= 1 0 1 1 0 001 B
5)MRSRB6相关Pin:

注:
这个寄存器里只有CL可以选择的,其它都是Fixed。
具体CL可选哪个,根据对应型号的SDRAM数据手册如下图:
可以看到我们使用的SDRAM的nCASLatency只支持2和3,而且各个版本都可以选择3.
我的最终配置为:MRSRB6[11:0]= 0 00 011 0 000 B
3.程序流程图设计:
4.程序设计:
1)Makefile
memory.bin : memory.S led_display.c
arm-linux-gcc -c -o memory.o memory.S
arm-linux-gcc -c -o led_display.o led_display.c
arm-linux-ld -Ttext 0x30000000 memory.o led_display.o -o memory_elf
arm-linux-objcopy -O binary -S memory_elf memory.bin
arm-linux-objdump -D -m arm memory_elf > memory.dis
clean:
rm -f memory.dis memory.bin memory_elf *.o
2)memory.S
#define WTCON 0x53000000
#define BWSCON 0x48000000
#define BANKCON6 0x4800001C
#define REFRESH 0x48000024
#define BANKSIZE 0x48000028
#define MRSRB6 0x4800002C
.Text
.global _start
_start:
/******关闭看门狗**********/
ldr r0 , =WTCON
mov r1 , #0x0
str r1 , [r0]
/*****END关闭看门狗********/
/***调用初始化内存子程序***/
bl memory_init
/**********END***********/
/*拷贝前4k内容到内存子程序*/
bl copy_bootsram_to_sdram
/************END**********/
/*PC跳转到内存后继指令开始处*/
ldr pc , =begin_sdram
begin_sdram:
@设置堆栈指针
ldr sp , =0x34000000
/**********让灯全亮************
#define GPBCON 0x56000010
#define GPBDAT 0x56000014
@把LED1-4管脚置为输出
ldr r0 , =GPBCON
ldr r1 , [r0] @把GPBCON里的内容加载到r1里
ldr r2 , =(0xFF<<10)
bic r1 , r1 ,r2 @操作数取反码或上r1,用于清零工作
ldr r2 , =(0x55<<10)
orr r1 , r1 , r2
str r1 , [r0]
@灯全亮
ldr r0 , =GPBDAT
ldr r1 , [r0]
ldr r2 , =(0x0F<<5)
bic r1 , r1 , r2
str r1 , [r0]
***********END***************/
@跳转到main函数
bl main
LOOP:
b LOOP
memory_init:
/*******内存初始化子程序*********/
@BWSCON[27:24] = 0 0 10B
ldr r0 , =BWSCON
ldr r1 , [r0]
ldr r2 , =(0x0F<<24)
bic r1 , r1 , r2
ldr r2 , =(0x02<<24)
orr r1 , r1 , r2
str r1 , [r0]
@BANKCON6[16:15]=11B;BANKCON6[3:0]=00 01B
ldr r0 , =BANKCON6
ldr r1 , [r0]
ldr r2 , =(0x03<<15)
bic r1 , r1 , r2
orr r1 , r1 , r2
ldr r2 , =0x0F
bic r1 , r1 , r2
ldr r2 , = 0x01
orr r1 , r1 , r2
str r1 , [r0]
@REFRESH[23:18] = 1 0 00 00B;REFRESH[10:0] = 0x7A3
ldr r0 , =REFRESH
ldr r1 , [r0]
ldr r2 , =(0x3F<<18)
bic r1 , r1 , r2
ldr r2 , =(0x20<<18)
orr r1 , r1 , r2
ldr r2 , =0x7FF
bic r1 , r1 , r2
ldr r2 , = 0x7A3
orr r1 , r1 , r2
str r1 , [r0]
@BANKSIZE[7:0] = 1 0 1 1 0 001 B
ldr r0 , =BANKSIZE
ldr r1 , [r0]
ldr r2 , =0xFF
bic r1 , r1 , r2
ldr r2 , =0xB1
orr r1 , r1 , r2
str r1 , [r0]
@MRSRB6[11:0] = 0 00 011 0 000 B
ldr r0 , =MRSRB6
ldr r1 , [r0]
ldr r2 , =0x3FF
bic r1 , r1 , r2
ldr r2 , =0x030
orr r1 , r1 , r2
str r1 , [r0]
mov pc , lr @函数返回
/******END内存初始化子程序*******/
copy_bootsram_to_sdram:
/******拷贝前4K代码到sdram*******/
mov r0 , #0x0
ldr r1 , =0x30000000
ldr r2 , =4*1024
copy:
ldr r3 , [r0] , #4
str r3 , [r1] , #4
cmp r0 , r2
bne copy
mov pc , lr
/*****END拷贝前4K代码到sdram*****/
3)led_display.c
#define GPBCON (*(volatile unsigned long *)0x56000010)
#define GPBDAT (*(volatile unsigned long *)0x56000014)
void delay(int dly)
{
for(; dly > 0; dly--);
}
int main()
{
GPBCON &= ~(0xFF<<10);
GPBCON |= (0x55<<10); //把GPB5~8都置为输出功能
while(1){
delay(50000);
GPBDAT |= (0x0F<<5); //LED灯灭
delay(50000);
GPBDAT &= ~(0x0F<<5); //LED灯亮
}
}