s3c2440裸机-内存控制器4-SDRAM编程实现
2024-07-08 来源:elecfans
配置内存控制器-SDRAM编程配置
2440内存控制器共有13个寄存器。
BANK0--BANK5只需要设置BWSCON和BANKCONx(x为0~5)两个寄存器; BANK6、BANK7外接SDRAM时,除BWSCON和BANKCONx(x为6、7)外,还要设置REFRESH、BANKSIZE、MRSRB6、MRSRB7等4个寄存器。
下面分别说明各个寄存起的设置:
1.位宽和等待控制寄存器BWSCON(BUSWIDTH&WAITCONTROLREGISTER)
我们SDRAM的位宽为32,DW6[25:24]设置成10, 没有使用等待信号,所以WS6[26]=0。 bank7跟随bank6的配置,
因此BWSCON寄存器的值为:0x22000000。
2.BANK控制寄存器BANKCON6(BANKCONTROLREGISTER)
在8个BANK中,只有BANK6和BANK7可以外接SRAM或SDRAM.
MT[16:15]:设置BANK是ROM/SRAM还是DRAM,我们用的SDRAM,属于DRAM。
Trcd[3:2]:行地址和列地址间隔多长时间,看SDRAM芯片手册时间间隔Trcd>18ns,我们HCLK=100MHZ,clocks为10ns,所以设置为2clocks即可。
SCAN[1:0]:SDRAM的列地址位数,上面的图片已经查看sdram手册分析过,列地址位数为9。
综上所述,本开发板中BANKCON6设为0x017001
3.刷新控制寄存器REFRESH(REFRESHCONTROLREGISTER)
REFEN[23]:设置开启SDRAM的刷新功能。
TREFMD[22]:SDRAM的刷新模式,0=CBR/AutoRefresh,选择自动刷新。
Trp[21:20]:根据sdram手册Trp>18ns, 设为0(2 clocks)即可。
Tsrc[19:18]: Tsrc = Trc - Trp = Trc-20, 根据sdram手册Trc>=60,我们取Trc =70, 则Tsrc= 50ns(5clocks)即可。
RefreshCounter[10:0]:Refresh period = (211-refresh_count+1)/HCLK,
RefreshCount = 211 + 1 - 100*Refresh period,看SDRAM手册“8192 refresh cycles/64ms”, Refresh period= 64000us/8192 = 7.8us,
RefreshCount取推荐值1269= 0x4f5.
综上,REFRESH寄存器设为0x8404F5。
4.BANKSIZE寄存器REFRESH(BANKSIZEREG ISTER)
BURST_EN[7]:0=ARM核禁上突发传输,1=ARM核支持突发传输(推荐);
SCKEEN[5]:0=不使用SCKE信号令SDRAM进入省电模式,1=使用SCKE信号令SDRAM进入省电模式(推荐);
SCLK-EN[4]:0=时刻发出SCLK信号,1=仅在访问SDRAM期间发出SCLK信号(推荐);
BK76MAP[2:0]:配置banksize成64M
因此,BANKSIZE寄存器设为0xB1。
5.SDRAM模式设置寄存器MRSRBx6(SDRAM MODE REGISTER SET REGISTER)
CL[6:4]:表示发出行、列地址后,等多久才返回收到数据, 看SDRAM手册发现Tcas >=18ns,所以配置成2 clocks即可。
MRSRB6寄存器设置为0x20。
代码如下:
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;//sdram base addr
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;
}
int main(void)
{
uart0_init();
sdram_init();
if (sdram_test() == 0)
led_test();
return 0;
}
测试结果: 当进行sdram_init后可已访问0x3000_0000地址的内容,led流水灯闪烁。 不初始化sdram_init,运行程序卡死。