DDR初始化 - 0
推荐链接:
- https://blog.csdn.net/m0_59161987/article/details/136760838
- https://www.cnblogs.com/biaohc/p/6346949.html
- https://f.daixianiu.cn/csdn/8588266265617235.html
程序目录结构
程序源码文件包含:
start.S:程序主函数
sdram_init.S:初始化SDRAM的函数
led_blink.c:led闪烁函数
Makefile和link.lds
概要
这段代码是三星出的demo程序,其中有些缺陷,要先看懂这块代码,然后按照前面文章的理解,手册上也给出了相关初始化的序列描述,在这些基础上我们对这个程序做修改,比如支持512M,1G的ddr配置等。
ddr初始化
DDR的初始化过程
S5PV210的用户手册里有对DDR初始化序列的描述:
S5PV210有两个独立的DRAM控制器,一个最大支持512MB,一个最大支持1024MB,但两个控制器必须支持相同类型的内存。
根据三星S5PV210文档可知,DDR2类型内存的初始化流程如下:
1、提供稳压电源给内存控制器和内存芯片,内存控制器必须保持CLE在低电平,此时就会提供稳压电源。注:当CKE引脚为低电平时,XDDR2SEL应该处于高电平(PCB上用上拉电阻实现)
2、根据时钟频率正确配置PhyControl0.ctrl_start_point和PhyControl0.ctrl_inc的值。配置的PhyControl0.ctrl_dll_on值为’1’以打开PHY DLL。
3、数据选取脉DQS清除:依照时钟频率和内存的tAC参数正确设置PhyControl1.ctrl_shiftc和PhyControl1.ctrl_offsetcbit位的值。
4、设置PhyControl0.ctrl_start位的值为’1’
5、设置ConControl,同时关闭auto refresh自动刷新计数器
6、设置MemControl,同时关闭所有的power down(休眠模式)。
7、设置MemConfig0寄存器。如果有两组内存芯片(比如有8片DDR,这8片DDR是分别挂在Memory Port1和Memory Port2上),再配置MemConfig1寄存器。
8、设置PrechConfig和PwrdnConfig寄存器
9、根据内存的tAC参数设置TimingAref,TimingRow, TimingData和TimingPower寄存器
10、如果需要QoS标准,配置QosControl0—15和QosConfig0-15寄存器
11、等待PhyStatus0.ctrl_locked位变为’1’。检查是否PHY DLL是否已锁
12、PHY DLL补偿在内存操作时由PVT(Process, Voltage and Temperature,处理器、电压和温度)变化引起的延迟量。但是,PHY DLL不能因某些可靠的内存操作而切断,除非是工作在低频率下。如果关闭PHY DLL,依照PhyStatus0.ctrl_lock_value[9:2]位的值正确配置PhyControl0.ctrl_force位的值来弥补延迟量(fix delay amount)。清除PhyControl0.ctrl_dll_on位的值来关闭PHY DLL。
13、上电后,确定最小值为200us的稳定时钟是否发出
14、使用DirectCmd寄存器发出一个NOP命令,保证CKE引脚为高电平
15、等最小400ns
16、使用DirectCmd寄存器发出一个PALL命令
17、使用DirectCmd寄存器发出一个EMRS2命令,program操作参数
18、使用DirectCmd寄存器发出一个EMRS3命令,program操作参数
19、使用DirectCmd寄存器发出一个EMRS命令来使能内存DLLs
20、使用DirectCmd寄存器发出一个MRS命令,重启内存DLL
21、使用DirectCmd寄存器发出一个PALL命令
22、使用DirectCmd寄存器发出两个Auto Refresh(自动刷新)命令
23、使用DirectCmd寄存器发出一个MRS命令,program操作参数,不要重启内存DLL
24、等待最小200时钟周期
25、使用DirectCmd寄存器发出一个EMRS命令给程序的运行参数。如果OCD校正(Off-Chip Driver,片外驱动调校)没有使用,改善一个EMRS命令去设置OCD校准的默认值。在此之后,发送一个EMRS指令去退出OCD校准模式,继续program操作参数
26、如果有两组DDR芯片,重复14-25步配置chip1的内存,刚刚配置的是chip0,也就是第一组内存芯片
27、配置ConControlto来打开自动刷新计数器
28、如果需要power down(休眠)模式,配置MemControl寄存器。
初始化过程需要28个小步骤,下面的代码,将28个小步骤划分为4个大部分:
- IO端口驱动强度设置
- 初始化PHY DLL
- 初始化DMC0
- 初始化DDR2 DRAM
初始化PHY DLL
下图是控制器内部结构的topview,可以从中窥探一下DLL的位置和作用:
上图解析:
64bit的AXI Channel的左边是CPU,右边就是DMC内部结构。控制命令和数据都是通过AXI总线来与DMC交互,可以看到数据和命令都有相应的缓存和fifo,这是因为CPU的速率非常高,控制器需要buffer将他们存起来。
Queue Arbiter是队列仲裁器,对已缓存的bank访问命令进行重排优化
AREF Cmd负责自刷新,每隔64MS发送自刷新命令。
CPU需要直接对DMC发布命令如MRS/EMRS,上下电命令,DMC还有一条APB总线从CPU连接到Functional Register,将命令送入direct cmd
经过final arbiter对所有命令和数据进行仲裁
latency control是一个很重要的部件,用来控制前面章节解释的所有t延时参数,如CL,AL延时。输入来自timing & configuration information
命令和时间延迟都有了,那么进入phy interface的都是理想波形,需要在经过DLL的处理才能送到PCB上去。
对于低速总线来说,不需要DLL。高速总线上的时序经过PCB以及device自身的部件处理,会有较大的延迟,一般都需要对PCB上信号再经过一定的“变形”才能送到PHY
DLL就是负责对返回信号做“变形”(一般用在read场景)
对physic部分的配置,也就是DLL配置,非常重要,决定了通信成败。DMC和Device都有DLL,但是功能和原理大相径庭。Device下的DLL比较简单,而DMC的DLL更加复杂所以需要详细配置。
device端DLL
上图是不带DLL的时序模型,图中DQ是数据线,而DQS是数据锁存信号。可以看到CLK上升沿和DQS上升沿之间(理论上要在DQS上升沿发送,下降沿接收)有一个D参数,这是由于信号在PCB上传输,经过device处理,所造成的延时。
图中还有一个AL延迟,这是由于数据线一共有很多根,在DQS采集时并不是所有数据线都已经稳定有效了,所以还需要一个AL延迟去做等待。
实际总的时延是ideally, “these two edges would be aligned”那块的延迟。为了尽量消除这里的时延,需要用到DLL来做调整:
上图是加入DLL之后的时序,DQS被向后延迟,一个full时钟周期,直到与CLK同步,这样DQ可以大致地与CLK对齐。
device的DLL比较简单,硬件自动帮我们做好了。我们只需要知道有这么个原理。
DMC端DLL
read情况下的DLL如何工作?
我们要在DQ的1/4处对数据进行采集,所以原来的DQS必须要经过90°的相位偏移。
接收读取命令的存储设备在读取延迟(即CAS延迟)后将数据发送到控制器。清除DQS后,PHY使用PHY DLL将DQS相移90度。使用移位的DQS,PHY对读取数据进行采样,并将数据保存到位于PHY内部的读取数据输入FIFO中。然后,控制器在考虑读延迟和读取延迟的情况下,从PHY获取数据,然后将其发送到AXI读通道。
一种RL之后的额外时序:
图中红框中的delay来自phy以及board级别的输入延迟。
rd_fetch 必须设置为2,兼容慢速device
存在一个内部DLL,它允许它在读取延迟的确切数量之后发送数据。如果我们假设有最小的或没有板级/PHY的输入延迟,如果采样负极性(Q1, Q3采样),由于数据被保存到PHY读取数据输入FIFO中,控制器以“读取延迟+1(读取)”周期将读取数据发送到AXI读取通道。读取周期是使用ConControl设置的。rd_fetch位域。
write情况下的DLL如何工作?
DQS的输出应该延迟90°的相位偏移,由于device的内部模拟电路复杂度不能做很高,所以只能由DMC来设置DLL。
如何配置DLL?
根据手册由:
“
根据时钟频率正确配置PhyControl0.ctrl_start_point和PhyControl0.ctrl_inc的值。配置的PhyControl0.ctrl_dll_on值为’1’以打开PHY DLL。
数据选取脉DQS清除:依照时钟频率和内存的tAC参数正确设置PhyControl1.ctrl_shiftc和PhyControl1.ctrl_offsetcbit位的值。
”
实际是配置如下三个寄存器,以及其位域:
PhyControl0:
ctrl_start是激活
ctrl_dll_on值为是总开关
ctrl_start_point是相位偏移起始点,手册建议0x10
ctrl_inc是每次相位偏移的size,手册建议0x10
因为DLL是模拟电路,不能像数字电路那样立即配置即生效。要经过反馈电路慢慢调节,所以需要配置inc和start_point.
PhyControl1:
ctrl_shiftc:粗调,DQS Cleaing,手册建议配置0x110,即T/2
ctrl_offsetc:细调,一般配置为0,不需要细调。
由于在DMC发送命令或数据,到memory device,再到memory device给出DMC反馈,这一路上是有各种延迟的,如I/O延迟,Bonding延迟,PKG延迟,Board延迟。为了知晓这一路延迟花了多少时间,需要有一个DQS Cleaning电路。
存在一个经验值,认为CK和DQS/DQ之间,有一个T/2的延迟,手册推荐也是配置T/2。
代码以及注释:
1 |
|