天天看点

x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节

                                                        疯雨-版权所有,转载请注明【http://blog.csdn.net/u010346967】

这么久了代码还没进入内存怎么行,接下来我们就来初始化DDR2。

1.DDR2的初始化流程

DDR2的初始化流程datasheet里面已经写得很清楚了,总共27步。直接看datasheet 598页,DDR2初始化部分截图如下:

x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节

2.硬件相关

首先,你得知道我们的板子用的是什么内存芯片,然后用了几块,接在哪了?

好了查看原理图x210cv3.pdf,搜索DDR2,你应该可以发现有4块内存芯片,而且是FBGA封装的。芯片型号是K4T1G164QQ,四块一样的芯片。三星产的,去下载这块芯片的文档,后面配置一些时序参数要用到。

然后,还得补充一些DDR2内存的知识,个人建议从DDR2的早起发展开始看,看产品是怎么样一代代升级的。但是这里我们只谈怎么操作,不说原理,不然没完没了了。有兴趣自己去了解吧。这里推荐些资料信息:

3.初始化细节

那我我们对照着一步步来。

3.1 为了向控制器和内存设备提供稳定的电源,控制器必须保持CKE为低电平。然后才能运行稳定的时钟。注意:XDDR2SEL引脚应为高电平把CKE电平拉低。

先看核心板原理图x210cv3.pdf(后面简称原理图),确定XDDR2SEL和CKE是什么?(DDR2位于核心板上面应该知道吧,如果不知道那你得好好反省了,每个硬件在哪还是得清楚)

先看XDDR2SEL,在原理图中搜索一下,发现下图:直接接到了VDD_IO,所以应该与编程无关,硬件上提供了高电平。所以第一步硬件做了。

x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节

3.2  根据时钟频率设置PhyControl0.ctrl_start_pointandPhyControl0.ctrl_inc为正确的值,设置PhyControl0.ctrl_dll_on为1打开PHY DLL

代码如下:

ldr r0, =0xF0000000
	ldr r1, =0x00101002
	str r1,[r0,#0x18]
           
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节

3.3 根据时钟频率和内存t_AC参数设置PhyControl1.ctrl_shiftcandPhyControl1.ctrl_offsetc为正确的值

代码如下:

ldr r1, =0x2046
	str r1,[r0,#0x1C]
           
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节

3.4 设置PhyControl0.ctrl_start为1

这一步简单 直接给出代码:

ldr r1, =0x00101003
	str r1,[r0,#0x18]
           

3.5 设置ConControl关闭自动刷新

代码如下:

ldr r1, =0x0FFF13A8
	str r1,[r0,#0x0]
           
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节

3.6 设置MemControl关闭所有的掉电模式

代码如下:

ldr r1, =0x00212400
	str r1,[r0,#0x4]
           
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节

3.7 设置MemConfig0

因为我们只使用了一个内存控制器,DMC0所以配置MemConfig0,如果使用了两个DMC0和DMC1那么要配置MemConfig1

这个寄存器的配置要看K4T1G164QE.pdf手册:K4T1G164QE名字里面的4就说明了是8个bank。地址数据线条数可以查看原理图。

代码如下:

ldr r1, =0x20E00323
	str r1,[r0,#0x8]
	
           
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节

3.8 设置PrechConfigandPwrdnConfig

代码如下:

ldr r1, =0xFF000000
	ldr r1,[r0,#0x14]
	
	ldr r1, =0xFFFF00FF
	str r1,[r0,#0x28]
           
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节

3.9 设置TimingAref,TimingRow,TimingDataandTimingPower

这几个寄存器的值要根据K4T1G164QQ内存芯片手册配置,手册上有详细的时序参数 代码如下:

ldr r1, =0x618
	str r1,[r0,#0x30]
	
	ldr r1, =0x1C24434A
	str r1,[r0,#0x34]
	
	ldr r1, =0x24240000
	str r1,[r0,#0x38]
	
	ldr r1, =0x08C90343
	str r1,[r0,#0x3C]
	
           
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节

下图(时序参数)来自于内存芯片手册

x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节

3.10 QoS没用到,这一步跳过

3.11 通过读PhyStatus0.ctrl_locked 是否为1检测PHY DLL是否锁定

代码如下:

1:
	ldr r1,[r0,#0x40]
	and r2,r1,#0x2
	cmp r2,#0
	beq 1b
           
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节

3.12 强制延时

代码如下:

and r1,r1,#0x3fc0
	mov r2,r1,LSL #18
	orr r2,r2,#0x00100000
	orr r2,r2,#0x1000
	orr r2,r2,#0x3
	str r2,[r0,#0x18]
           
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节

3.13 开机等待200us是时钟平稳,这一步不用开机到内存初始化肯定时钟平稳了

3.14 使用DirectCmd发送NOP命令,确保CKE保持为高电平

代码如下:

ldr r1, =0x07000000
	str r1,[r0,#0x10]
           
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节

3.15 等待最少400ns

3.16 使用DirectCmd发送PALL命令

代码如下:

ldr r1, =0x01000000
	str r1,[r0,#0x10]
           

3.17 使用 DirectCmd发送EMRS2命令去写入运行参数

这个部分就要去看DDR2规范文档了,自己去下载吧。

代码如下:

ldr r1, =0x00020000
	str r1,[r0,#0x10]
           
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节

3.18 使用DirectCmd发送EMRS3命令去写入运行参数

代码如下:

ldr r1, =0x00030000
	str r1,[r0,#0x10]
           

3.19 使用 DirectCmd发送EMRS命令,使能内存DLLs

代码如下:

ldr r1, =0x00010000
	str r1,[r0,#0x10]
           

3.20 使用 DirectCmd发送MRS命令,复位内存DLLs

代码如下:

ldr r1, =0x542
	str r1,[r0,#0x10]
           

3.21 使用 DirectCmd发送PALL命令

3.22  使用DirectCmd发送两次auto refresh命令

代码如下:

ldr r1, =0x05000000
	str r1,[r0,#0x10]
	str r1,[r0,#0x10]
           

3.23 使用DirectCmd发送MRS命令,运行无复位的内存DLL

代码如下:

ldr r1, =0x442
	str r1,[r0,#0x10]
           
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节

3.24 最少等200个时钟周期

3.25使用DirectCmd发送EMRS命令,设置OCD校正

代码如下:

ldr r1, =0x00010780
	str r1,[r0,#0x10]
           
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节

3.26  无

3.27 设置ConControl启动自动刷新计数器

代码如下:

ldr r1, =0x0FFF13B8
	str r1,[r0,#0x0]
           
x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节

3.28 如果有必要的话设置MemControl开启掉电模式

这里我们就不设置了

完整的初始化代码如下:

mem_init:
	//2.设置PhyControl0.ctrl_start_pointandPhyControl0.ctrl_inc
	ldr r0, =0xF0000000
	ldr r1, =0x00101002
	str r1,[r0,#0x18]
	
	//3.设置PhyControl1.ctrl_shiftcandPhyControl1.ctrl_offsetc
	ldr r1, =0x2046
	str r1,[r0,#0x1C]
	
	//4.设置PhyControl0.ctrl_start为1
	ldr r1, =0x00101003
	str r1,[r0,0x18]
	
	//5.设置ConControl关闭自动刷新
	ldr r1, =0x0FFF13A8
	str r1,[r0,#0x0]
	
	//6.设置MemControl关闭所有的掉电模式
	ldr r1, =0x00212400
	str r1,[r0,#0x4]
	
	//7.设置MemConfig0
	ldr r1, =0x20E00323
	str r1,[r0,#0x8]
	
	//8.设置PrechConfigandPwrdnConfig
	ldr r1, =0xFF000000
	ldr r1,[r0,#0x14]
	
	ldr r1, =0xFFFF00FF
	str r1,[r0,#0x28]
	
	//9.设置TimingAref,TimingRow,TimingDataandTimingPower
	ldr r1, =0x618
	str r1,[r0,#0x30]
	
	ldr r1, =0x1C24434A
	str r1,[r0,#0x34]
	
	ldr r1, =0x24240000
	str r1,[r0,#0x38]
	
	ldr r1, =0x08C90343
	str r1,[r0,#0x3C]
	
	
	//10.QoS没用到,这一步跳过
	
	//11.通过读PhyStatus0.ctrl_locked 是否为1检测PHY DLL是否锁定
1:
	ldr r1,[r0,#0x40]
	and r2,r1,0x2
	cmp r2,#0
	beq 1b
	
	//12.强制延时
	and r1,r1,#0x3fc0
	mov r2,r1,LSL #18
	orr r2,r2,#0x100000
	orr r2,r2,#0x1000
	orr r2,r2,#0x3
	str r2,[r0,#0x18]
	
	//13.开机等待200us是时钟平稳,这一步不用开机到内存初始化肯定时钟平稳了
	//14.使用DirectCmd发送NOP命令,确保CKE保持为高电平
	ldr r1, =0x07000000
	str r1,[r0,#0x10]
	
	//15.等待最少400ns
	//16.使用DirectCmd发送PALL命令
	ldr r1, =0x01000000
	str r1,[r0,#0x10]
	
	//17.使用DirectCmd发送EMRS2命令去写入运行参数
	ldr r1, =0x00020000
	str r1,[r0,#0x10]
	
	//18.使用DirectCmd发送EMRS3命令去写入运行参数
	ldr r1, =0x00030000
	str r1,[r0,#0x10]
	
	//19. 使用DirectCmd发送EMRS命令,使能内存DLLs
	ldr r1, =0x00010000
	str r1,[r0,#0x10]
	
	//20.使用DirectCmd发送MRS命令,复位内存DLLs
	ldr r1, =0x542
	str r1,[r0,#0x10]
	
	//21.使用DirectCmd发送PALL命令
	ldr r1, =0x01000000
	str r1,[r0,#0x10]
	
	//22.使用DirectCmd发送两次auto refresh命令
	ldr r1, =0x05000000
	str r1,[r0,#0x10]
	str r1,[r0,#0x10]
	
	//23.使用DirectCmd发送MRS命令,运行无复位的内存DLL
	ldr r1, =0x442
	str r1,[r0,#0x10]
	
	//24.最少等200个时钟周期
	//25.使用DirectCmd发送EMRS命令,设置OCD校正
	ldr r1, =0x00010780
	str r1,[r0,#0x10]
	
	//26.不用设置
	//27.设置ConControl启动自动刷新计数器
	ldr r1, =0x0FFF13B8
	str r1,[r0,#0x0]
	
	//28如果有必要的话设置MemControl开启掉电模式
	
	mov pc,lr
           

在串口初始化代码后添加调用DDR2初始化代码,修改代码如下:

bl system_clock_init
	
	/* for UART */
	bl	uart_init

	bl ddr2mem_init
	
           

最后是测试工作:

代码测试始终伴随程序开发而存在,如何测试内存能不能用呢?我们可以这么做,往内存单元里面写入数据,然后读出来,比较写入的数据与读出的数据。

最简单的方式是利用led来调试。你可以自己想想怎么做?这里我们采用串口把指定的地址内容打印出来。

测试的函数如下(这个函数是从别人视频那里偷学过来的):用法:把要打印的地址赋给r0,就是打印相应地址内容。

display_mem:
    ldr r0,[r0]

    ldr r1, =0xE2900020

    ldr r2, =0x30
    str r2,[r1]

    ldr r2,=0x78
    str r2,[r1]

    ldr r3, =28

display_loop_cnt:
    lsr r2,r0,r3
    and r2,r2,#0xF
    cmp r2,#10
    addmi r2,r2,#0x30
    addpl r2,r2,#0x37
    str r2,[r1]

    sub r3,r3,#4
    cmp r3,#0
    bpl display_loop_cnt

    ldr r2, =0xA
    str r2,[r1]        @UTH0='\r'

    ldr r2,=0xD
    str r2,[r1]

    mov pc,lr
           

将测试代码(往0x20000000内容单元写入0x1234ABCD并通过串口打印出来)添加到lowlevel_init.S文件,修改如下:

bl ddr2mem_init
	
	ldr r1, =0x1234abcd
	ldr r0, =0x20000000
	str r1,[r0]
	bl display_mem
	
	bl	internal_ram_init
           

最后烧写,测试效果截图如下:

x210v3开发板u-boot-2012.10移植之八---DDR2初始化我也能搞定1.DDR2的初始化流程2.硬件相关3.初始化细节