当前位置 博文首页 > cumtchw:S3C2440裸机------SDRAM
目录
1.配置内存控制器的寄存器
1.1BWSCON寄存器设置
1.2BANKCON6寄存器设置
1.3REFRESH寄存器配置
1.4 BANKSIZE寄存器配置
1.5MRSRB6寄存器配置
2.代码
2.1init.h
2.2init.c
2.3main.c
我们的S3C2440在访问SDRAM的时候,首先发出地址,然后内存控制器首先根据地址范围发出片选信号nGCS6,然后根据片选信号的类型得知是SDRAM,然后拆分地址为 bank地址,行地址和列地址,具体应该怎么把地址拆分成bank地址,行地址,列地址则由我们配置的SDRAM寄存器决定,然后开始读数据。
由于我们的SDRAM只连接到了片选6上面,所以我们只看该寄存器的与6相关的几项,由于我们使用了两篇SDRAM组成32位的,所以DW6我们设置成10,WS6表示是否使用wait信号,wait信号是指如果内存芯片的速度很慢,当cpu发出读写命令之后,内存控制器开始驱动相关引脚,在这些时间之内内存芯片还是没有把数据准备好,那么内存芯片可以向内存控制器发出一个wati信号,请求再宽限一点时间,在我们的原理图里面我们根本没用到这个wait信号,这里设置成0,ST6表示SRAM是否使用UB/LB引脚,我们是SDRAM不是SRAM,这个也用不到。
其中MT表示外部接的是ROM SRAM还是SDRAM,这里我们设置成11. SCAN用来设置列地址占据多少位,这个要看内存芯片的芯片手册得到列地址占据多少位,这里我们通过看芯片手册得到列地址占据9位。然后我们的内存控制器是先发出行地址,再发出列地址,然后行地址和列地址之间会有一个时间间隔,这个时间间隔也许要看内存芯片的芯片手册,这里通过看芯片手册得到是20ns,所以我们这里设置成是两个时钟周期。
动态内存是在使用过程中需要不断的刷新, 否则里面的数据会丢失, 首先REFEN位肯定要enable,TREFMD我们使用自动刷新模式,然后Refresh Counter里面的Refresh period这个值可以看SDRAM芯片手册, 然后发现64ms刷新8192次,那么刷新周期是64/8192=7.8ms. 然后我们的HCLK正好是100M,所以正好与寄存器配置表的里面例子重合,那么就是1269等于16进制的0x4F5.然后看一下Trp,这个是行地址信号的充电时间,我们直接在内存芯片手册里面搜索这个Trp发现是20ns,也就是两个时钟周期,然后看一下Tsrc,我们再内存芯片手册里面根本搜不到这个名字,但是我们在寄存器的注释里面发现一个公式,Trc = Tsrc + Trp,所以我们去内存芯片手册找一下Trc,发现是70ns,那么可以得到Tsrc是50ns。
先看BK76MAP,我们bank6接了两个SDRAM组成了64M的内存,然后BURST-EN是指突发访问,也就是可以一次访问多个字节。 然后SCKE_EN休眠模式使能,然后SCLK_EN使用推荐值。
我们看一下CL,内存控制器读的时候,发出bank地址,行地址,列地址,然后要等待一会才有数据,具体等待时间要看一下我们的SDRAM的芯片手册,SDRAM里面有个MR模式寄存器,里面有一项CL,我们的内存控制器设置了MRSR寄存器之后,它就会向SDRAM发出指定的信号来设置MR使得里面的CL等于某个值。
我们在之前uart代码的基础上增加两个文件,init.h和init.c。
#ifndef _INIT_H
#define _INIT_H
void sdram_init(void);
int sdram_test(void);
#endif
#include "s3c2440_soc.h"
void sdram_init(void)
{
BWSCON = 0x22000000;
BANKCON6 = 0x18001;
BANKCON7 = 0x18001;
REFRESH = 0x8404f5;
BANKSIZE = 0xb1;
MRSRB6 = 0x20;
MRSRB7 = 0x20;
}
int sdram_test(void)
{
volatile unsigned char *p = (volatile unsigned char *)0x30000000;
int i;
// write sdram
for (i = 0; i < 1000; i++)
p[i] = 0x55;
// read sdram
for (i = 0; i < 1000; i++)
if (p[i] != 0x55)
return -1;
return 0;
}
#include "s3c2440_soc.h"
#include "uart.h"
#include "init.h"
int main(void)
{
uart0_init();
sdram_init();
if (sdram_test() == 0)
led_test();
return 0;
}
?
cs