天天看點

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.初始化細節