目录
3.2 配置SDRAM 控制寄存器 (EXMC_SDCTLx) (x=0, 1)
3.3 配置SDRAM 时序寄存器 (EXMC_SDTCFGx) (x=0, 1)
外部存储器控制器 EXMC功能与STM的FSMC类似。EXMC可以把AMBA协议转换为专用的片外 存储器通信协议,包括SRAM、ROM、NOR Flash、NAND Flash、PC Card 和SDRAM 。可以把EXMC理解为将外部设备映射到内部地址线上,这样不管外部设备的总线类型,用户都可以将这些设备当做变量读写(也可以理解成一个文件,类似Linux里面的设备管理方式),而实际的时序操作都交给EXMC处理。
EXMC中对应SDRAM的空间地址:
1 硬件接法
开发板上的SDRAM芯片型号MT48LC16M16A2P-6AIT,Micron的256Mbit(16Mx16位)的SDR SDRAM,时钟频率143/166MHz,存取时间6ns。
GD32F450 EXMC最大地址线是26位(最大只能找到EXMC_A25,不过EXMC SDRAM的寄存器中最大行地址只能设置为13位,列地址最大11位),最大数据线是32位(最大只能找到EXMC_D31)。
而MT48LC16M16A2P-6AIT的地址线是13位,数据线是16位的。
可以在datasheet中的2.6.4. GD32F450xx pin alternate function中以EXMC_*找到对应的IO。
注意GD32450i-EVAL板子上SDRAM的CKE脚(PC5)是与ETH的RXD1脚公用的,需要将JP17跳到SDRAM。
2 IO初始化
EXMC的IO口都是AF12。
地址线A0-A12都是唯一的IO(PF0-5, PF12-15, PG0-2),无复用。
数据线D0-D15都是唯一的IO(PD14-15, PD0-1, PE7-PE15, PD8-10),无复用。
DQM0和DQM1都是唯一的IO(PE0-1),无复用。
SDCKE0: GPIOC3、GPIOC5、GPIOH2
SDCKE1: GPIOB5、GPIOH7
BA0和BA1用的是地址线A14/A15,对应PG4-5,无复用。
SDCLK是唯一的IO(GPIOG8),无复用。
SDNCAS是唯一的IO(GPIOG15),无复用。
SDNRAS是唯一的IO(GPIOF11),无复用。
SDCKE0:GPIOC3、GPIOC5、GPIOH2
SDCKE1:GPIOB5、GPIOH7
SDNE0:GPIOC2、GPIOC4、GPIOH3
SDNE1:GPIOB6、GPIOH6
SDNWE:GPIOA7、GPIOC0、GPIOH5
注意这些IO不能用PULL UP,否则会导致写入0出错。
3 EXMC初始化
3.1 RCU时钟使能
RCU_AHB3EN |= 0x01;
AHB的最大时钟为200MHz。
3.2 配置SDRAM 控制寄存器 (EXMC_SDCTLx) (x=0, 1)
这个寄存器分2个,分别对应硬件上链接的是SDCKE0还是SDCKE1,而EXMC_SDCTL1的位10到位14是保留位,对应的设置是设置到EXMC_SDCTL0,也就是说如果选择SDCKE1,这2个寄存器都需要设置。
3.2.1 设置SDCLK[1:0]
由于GD32F450的最大时钟才100MHz(AHB / 2),比SDRAM的频率小的多,所以一般情况这个设置是0x10。
*REG_EXMC_SDRAM_SDCTL0 |= ((uint32_t)0x02 << 10);
更新一个调试碰到的问题,读写SDRAM不稳定,多个字节就出错,发现把这个参数改为0b11,即3个HCLK解决问题。
3.2.2 设置BRSTRD
这个参数一般是使能的。
*REG_EXMC_SDRAM_SDCTL0 |= ((uint32_t)0x2 << 10) | ((uint32_t)0x1 << 12)
3.2.3 设置PIPED[1:0]
3.2.4 设置CL[1:0]
SDRAM的Datasheet中有芯片的CL值。如上图CL为3。
3.2.4 设置NBK(Bank数量)

SDRAM的Datasheet中有芯片的Bank数,如上图。
3.2.4 设置SDW[1:0] (数据总线宽度)
SDRAM的Datasheet中有芯片的数据总线宽度,如上图。
3.2.5 设置RAW[1:0] (行地址位宽)
行地址位宽如上图红圈内,这里都是13位。
3.2.5 设置CAW[1:0] (列地址位宽)
3.3 配置SDRAM 时序寄存器 (EXMC_SDTCFGx) (x=0, 1)
时序寄存器和上一个的控制寄存器一样,分2个寄存器,也有部分位只有SDTCFG0有含义,如果用SDTCFG1的情况下也需要设置SDTCFG0的相应位(位12到位23)。
3.3.1 设置RPD[3:0] (仅SDTCFG0)
在SDRAM的Datasheet找RPD
最小值是12ns,而SDRAM的时钟为100MHz,即10ns,所以这个值应该最少设置成2。
3.3.2 设置WRD[3:0](仅SDTCFG0)
在SDRAM的Datasheet找WRD,位置应该和RPD接近
因为1CLK是10ns,所以参数选择1CLK + 6ns(大于12ns),这个参数应该设置为2.
3.3.3 设置ARFD[3:0](仅SDTCFG0)
60ns即6个Clock。
3.3.4 设置RCD[3:0]
18ns即2个Clock。
3.3.5 设置RASD[3:0]
42ns即5个Clock。
3.3.6 设置XSRD[3:0]
67ns即7个Clock。
3.3.7 设置LMRD[3:0]
3.3.8 等待SDRAM Ready
写完时序寄存器后需要通过判断SDRAM状态寄存器 (EXMC_SDSTAT)的位5 NRDY获知EXMC是否准备好。
3.5 SDRAM时钟使能
操作命令寄存器 (EXMC_SDCMD)以实现时钟使能。
3.5.1 选择SDRAM
3.5.2 设置时钟使能命令
即CMD[2:0] = 001
3.5.3 设置自动刷新个数
这个配置是指在发送自动刷新命令“011”后,EXMC会做几次自动刷新?不理解这个设定,应该都只需要做一次刷新吧?
这里设置为默认1个自动刷新周期。
3.5.4 设置MRC[12:0]
在SDRAM的Datasheet中查找mode register,可以找到这个寄存器的说明,这里不需要处理,设置MRC = 0
3.5.5 等待EXMC Ready
写完命令寄存器后先等待10ms,然后也需要判断SDRAM状态寄存器 (EXMC_SDSTAT)的位5 NRDY等待EXMC准备好。
3.6 配置自动刷新命令
与时钟使能类似,写入EXMC_SDCMD的参数如下:
//Auto Refresh Command(0b011)
//NARF = 7, 8 auto refresh cycle
//MRC = 0
这里有个问题,NARF设置为7,但是Datasheet上不是写了只有CMD=0b011时才意义,为什么这里还需要设置这个参数?
3.7 配置加载模式寄存器命令
这个命令需要对应到SDRAM的Datasheet中的Mode Register,即需要配置EXMC_SDCMD的MRC区域
主要是CASLatency需要设置为之前的CL配置值,之前CL配置为3,这里也需要设置为3.
还有第9位WB设置为1,意思如下图:
所以MRC = 0x230
3.8 设置自动刷新间隔寄存器 (EXMC_SDARI)
计算刷新每行需要的时间
下图中Row告知了SDRAM有8192行。
SDRAM的Datasheet中有说明,如下图
工规和商规是64ms,而车规是16ms。
这里用的是工规,所以取值64ms。
每行需要的时间 = 64 * 1000 / 8192 = 7.81us
SDRAM的时钟是100MHz,ARINTV = 7.81 * 100 - 20 = 761
3.9 确认初始化完成
可以通过读写一次SDRAM以确认SDRAM已经初始化OK。
4 SDRAM的访问
最简单直接的办法是使用指针,指针的地址指向SDRAM所在的地址即可。
if(SDRAMSetting.SDCKE == 0)
pRegAddr = (uint32_t *)EXMC_SDRAM_ADDR0;
else
pRegAddr = (uint32_t *)EXMC_SDRAM_ADDR1;
timeout = 10;
do
{
delayms(100);
*pRegAddr = 0xAA55A55A;
if(*pRegAddr == 0xAA55A55A)
break;
}while(--timeout > 0);
if(timeout == 0)
{
EXMCSD_INFO(Printf("SDRAM Initial Fail\n"));
}
EXMCSD_INFO(Printf("SDRAM Initial Done:0x%x\n", pRegAddr));