第九章 DRAM初始化配置
DRAM的初始化,其实就是对cpu内部的DRAM控制器进行初始化,因为对外部DRAM的数据访问,是通过DRAM控制器来进行访问的。
而对DRAM控制器的初始化,其实就是初始化DRAM控制器的寄存器。其实这部分代码,官方会提供参考的代码,只需要基于官方参考的修改即可。
代码,请查看我的github网站:https://github.com/weiqi7777/...
1、设置ASYNC_CONFIG寄存器
该寄存器
作用:
目前不知道配置这个寄存器有什么用,不过试了下,不用配置这个寄存器也可以。
2、设置驱动强度
设置GPIO的驱动强度。
MP1_0DRV_SR_OFFSET = 0x3CC
就是设置MP1_0组端口GPIO的驱动强度。
将驱动强度都设置为2x。
MP1_1DRV_SR_OFFSET = 0x3EC
设置MP1_1组端口GPIO的驱动强度为2x
设置驱动强度的意义
手册的92页,有说明,对于DRAM1使用的是MP1_0 – 8 端口。对于DRAM2使用的是MP2_0 – 8 端口。所以对于这些端口需要设置下驱动强度。
不过测试下,把驱动强度设置为1x,也是可以工作的。不过,官方既然是设置了驱动强度时2x,那么就设置为2x好了。
S5PV210,将GPIO,分为了三个类型,A类型,B类型,C类型,每组类型的IO,用于不同的目的。
对于type C,用于DRAM的。驱动能力由下图所示。猜测DS0和DS1就是配置驱动强度寄存器每一个port的低位和高位。
DS0 = 0, DS1 = 1 , 就表示驱动强度为2x。
设置驱动的目的,是为了和外部设备的兼容。比如外部的DRAM的芯片,驱动电流最小是6mA,那么连接DRAM芯片的端口的驱动电流,就不能低于6mA,因此DS0和DS1都不能设置为0,也就是驱动强度不能为1x。
设置MP1的其他组GPIO的驱动强度为2x。
以上的宏定义如下:
寄存器的作用和上面的一样。
不过经过测试,这些寄存器不用设置也是可以的,因为这些寄存器的复位默认值是0xAAAA。所以上诉代码是可以删掉的。
3、设置DLL
设置DLL的目的,是为了设置驱动给DRAM的时钟。
代码如下:
这里是210手册中规定的初始化顺序
PHY control0寄存器
◾需要操作PHY control0寄存器的ctrl_start_point和ctrl_inc这几位,而这几位要写入0x10。所以对这个寄存器的写入值是0x00101000
◾需要操作PHY control0寄存器的ctrl_dll_on这一位,要写入1,打开PHY DLL。所以对这个寄存器的写入值是0x00101002
◾操作PhyControl1寄存器的ctrl_shiftc和ctrl_offsetc位,这个和外部的DDR时序有关系,这里写入的值是0x00000086
◾设置PHY control0寄存器的ctrl_start位为1,这个是第0位。写入值是0x00101003。
以上的初始化时序和手册中的PHY DLL LOCK Procedure有关系(627页)
保持ctrl_dll_on一直为高,写入ctrl_start_point和ctrl_inc。等到DLL锁定后,ctrl_clock会为高,ctrl_flock也会为高,所以下一步就是判断锁定的时候就要判断ctrl_clock和ctrl_flock以及ctrl_lock信号是否都为1。
判断锁定后,就要将ctrl_lock_value读取,然后写入到ctrl_force中,就是之后的两步完成的事。
判断DLL是否锁定,通过读取PHY status寄存器判断。
判断PHY Status Register 寄存器的最低3位是否都为1。不是的话,就一直读取判断,直到DLL锁定
设置PHY control0寄存器的DLL force Delay
Ctrl_force的值是PHY Status Register寄存器的ctrl_lock_value[9:2],读取PHY Status Register寄存器的值赋值给r1,然后取ctrl_lock_value[9:2]的值,其他位都清零。在将ctrl_inc 和ctrl_start_point的值给设置为0x10,ctrl_dll_on 和ctrl_start都设置为1,赋值给 PHY control0寄存器。
4、设置寄存器
按照初始化步骤
代码
对于concontrol寄存器,这个寄存器比较复杂,目前不清楚功能。
对于memctrol寄存器,这个寄存器比较重要,根据外部存储器设置。
根据数据手册,得知,突发长度设置为4,1个chip,32位数据,存储器类型为DDR2。
对于memconfig0寄存器,设置chip0的信息。这个要根据所用的存储器来确定。
设置下来,chip_base为0x20,chip_mask为0xf0,表示对于DRAM0的有效地址空间是0x2000_0000 – 0x27ff_ffff。使用线性映射,row地址14位,col地址10位。
因为没有接chip1,因此用不到chip1,所以memconfig1不用设置。
对于preconfig寄存器
对于pwrdnconfig寄存器。设置若n个周期后没有对DRAM操作,就进入自刷新和预充电休眠状态。
5、设置时序
以下设置的时序信息,就和外部的DRAM芯片时序有关的。这里的时序参数,一定要设置正确,和外部的DRAM芯片的时序匹配,否则DRAM控制器是不能正常的驱动外部的DRAM芯片的。
手册上,有说明设置时序的步骤:
代码
设置刷新时间,我们设置的系统mclk时钟为200M,所以设置的值为7.8 us * 200 = 1560(0x618)。
对于timingRow寄存器,关于行地址的时序
对于TimingData,设置数据的时序
对于TimingPower,设置存储器的电源模式
6、判断锁定
时序设置完毕后,需要判断DLL是否锁定,并要设置PhyControl0.ctrl_force。但是这个在之前的DLL锁定已经做了,而且实验,在之前判断锁定和在这里判断锁定,都是可以工作的。
7、发送命令
DRAM控制器设置完毕后,下面就要利用DRAM控制器,对外部的DRAM芯片进行初始化。
手册提供了初始化顺序,需要发送各种命令。
发送命令,通过控制DirectCmd寄存器,[24:24]表示发送的命令,[20]表示对DRAM的哪个chip进行操作进行操作。
代码
对于EMRS命令。Cmd_type部分是0x9。但是怎么区分MRS,EMSR1,EMSR2,EMSR3了。就要靠cmd_bank来确定
根据外接的DDR2的数据手册,可以看出EMRS命令是可以带参数的,参数就是由cmd_addr来决定的。
对于DDR2芯片来说,EMRS的格式都是
前面3个BA2,BA1,BA0是去确定哪一个命令。因为该DDR2芯片没有用到BA2,所以BA2的值要为0。
后面的A13-A0就是该命令对应的参数,在不同的命令下,该参数对应的功能也不一样。
对于MRS命令
在代码中,是如下写的,通过上表对应,可知,设置CL为4,BL为4。Mode为normal,DLL Reset为YES,对DLL进行复位。
不过在随后的代码,将A8置为0,取消复位。
对于EMSR1命令
A10为1,——DQS功能取消。
A10-A7都是为1。——DQS功能取消。 OCD calibration default * 4
A10为1,A9-A7为0。 OCD calibration mode exit。
对于EMRS2
高温下自刷新功能关闭,自刷新的阵列是全阵列。
EMRS3命令,目前在DDR2芯片中没有使用。要使用的话,参数要设置为全0.
8、初始化最后两步
最后两部,设置两个寄存器:
代码
对于CONCONTROL寄存器
通过以上的操作,就将DRAM控制器和外部的DRAM芯片进行初始化了,此时CPU就可以访问外部的DRAM芯片了。
系列其他篇
原文首发于骏的世界博客
作者:卢骏.
更多Arm技术相关的文章请关注Arm技术博客极术专栏,每日更新。