最近一直在调试SDRAM,花了一个多月才把sdram完全跑通。于是接下来的工作不是其他的,当然是写一个关于SDRAM调试的总结啦!话不多说,开始正题
开发板:SK-1788
CPU:cortex-M3 STM32 LPC1788FBD208
SDRAM:H57V2562GTR-75C (两片)
H57V2562GTR-75C简介:
16位数据总线(D0-D15),13位地址总线(A0-A12),两片,构成32位数据总线,26位地址总线,每片4个bank,由BA0,BA1两个管脚选择寻址,CS为片选管脚。
HY57V2562GTR挂到LPC1788的EMC_DYCS0,起始地址为0xA0000000,
片选管脚EMC_CS0 地址范围:0xA0000000-0xA3FFFFFF
存储器类型:动态
lpc1788 的封装是208PIN(所以ECC配置应该使用208的配置)
HY57V2562GTR大小:
2片32M组成的64MB的内存, 32*2=64MB
每一块SDRAM:8192行(2^13)*512列(2^9)*4个bank = 16M * 16位宽 = 256Mb = 32MB
原理:
研究过SDRAM的人都知道,我们的sdram是动态的,它要保存数据,依靠的是里面一个一个的微小电容排成的电容阵列(姑且这么认为),数据在每次的读写都会让电容的电荷流失,即使不对数据操作,间隔一定的时间,电容上的电荷也会流失。因此,sdram需要不断的刷新数据,为电容充电,以保证上面的数据不丢失。
不少sdram芯片datasheet上都会标出
等字样,(有的是4096)这就是说:每隔64ms刷新8192行。Sdram刷新是以“行”进行的,我们的sdram是8192行,因此刷新一次需要64ms。如果刷新的这个值比64ms大,那么我们的数据将得不到保存。64ms也是晶体存储容量的极限。因此在配置寄存器的时候,需要注意。
时钟配置:
为了使整个系统运行流畅,有必要说一下该开发板对于时钟的配置。
CPU上电复位,晶振稳定工作之后,通过配置CLKSRCSEL[0]=1,选择芯片的震荡源为外部12MHz晶振。
通过配置PLL0寄存器,将时钟倍频到108MHz输出,此时pll_clk为108MHz,sysclk为12MHz。(PLL1模块是单独一个给USB提供时钟的模块,占时不用管。)
通过配置CCLKSEL[8]=1,选择输入为108MHz,将108MHz送到CPU模块,EMC(SDRAM)模块和外设模块。
通过配置CPU Clock Divider 来选择时钟分频(不分频,108MHz),即cclk=108MHz,
通过配置EMC Clock Divider 来选择时钟(和CPU一致,108MHz),即emc_clk=108MHz,
通过配置Peripheral Clock Divider 来配置外设时钟分频,暂时不涉及到。
该系统的时钟部分工作原理如下图
下图是sdram模块的原理框图。
这里有两个比较重要的地方:
CMDDLY(EMCDLYCTL[4:0]),命令延迟模式下EMC 输出的可编程延迟值
FBCLKDLY(EMCDLYCTL[12:8]),控制输入数据采样的反馈时钟的可编程延迟值
这两个延时是非常重要的,1788芯片的SDRAM有一个很重要的寄存器, EMCDLYCTL 寄存器延时的设置,就算你和官方所使用芯片一样,只要电路板有差异,这个寄存器的设置将有可能导致SDRAM在使用过程中出现错误。
我在配置这两个寄存器的时候,花费了很长的时间才把延时配好。具体怎么配,下面再说。
初始化EMC模块和sdram
#define SDRAM_BASE 0xA0000000
#define EMC_BASE_ADDR 0x2009C000
#define EMC_RS_BASE_ADDR 0x400FC1DC
#define SDRAM_SIZE 0x4000000 // 512Mbit=64MB
#define EMCControl_ENABLE (1<<0)
#define EMCConfig_SMALL (0<<0)
#define EMCConfig_PERC_OF_CCLK (0<<8)
#define EMCDLYCTL_CMDDLY (0x0D<<0)
#define EMCDLYCTL_FBCLKDLY (0x10<<8)
#define EMCDLYCTL_CLKOUT0DLY (0<<16)
#define EMCDLYCTL_CLKOUT1DLY (0<<24)
#define EMC_DRC_CLKDELAY (1<<0)
#define EMC_Ras_late_3 (3<<0)
#define EMC_Cas_late_3 (3<<8)
#define EMCDCF0_BUF_EN (1<<19)
#define EMCDCF0_AM (1<<7)|(3<<9)|(1<<14)
#defin