x210v3開發板u-boot-2012.10移植之八---DDR2初始化我也能搞定

                                                        瘋雨-版權所有,轉載請註明【http://blog.csdn.net/u010346967】

這麼久了代碼還沒進入內存怎麼行,接下來我們就來初始化DDR2。

1.DDR2的初始化流程

DDR2的初始化流程datasheet裏面已經寫得很清楚了,總共27步。直接看datasheet 598頁,DDR2初始化部分截圖如下:





2.硬件相關

首先,你得知道我們的板子用的是什麼內存芯片,然後用了幾塊,接在哪了?

好了查看原理圖x210cv3.pdf,搜索DDR2,你應該可以發現有4塊內存芯片,而且是FBGA封裝的。芯片型號是K4T1G164QQ,四塊一樣的芯片。三星產的,去下載這塊芯片的文檔,後面配置一些時序參數要用到。

然後,還得補充一些DDR2內存的知識,個人建議從DDR2的早起發展開始看,看產品是怎麼樣一代代升級的。但是這裏我們只談怎麼操作,不說原理,不然沒完沒了了。有興趣自己去了解吧。這裏推薦些資料信息:

3.初始化細節

那我我們對照着一步步來。

3.1 爲了向控制器和內存設備提供穩定的電源,控制器必須保持CKE爲低電平。然後才能運行穩定的時鐘。注意:XDDR2SEL引腳應爲高電平把CKE電平拉低。

先看核心板原理圖x210cv3.pdf(後面簡稱原理圖),確定XDDR2SEL和CKE是什麼?(DDR2位於核心板上面應該知道吧,如果不知道那你得好好反省了,每個硬件在哪還是得清楚)

先看XDDR2SEL,在原理圖中搜索一下,發現下圖:直接接到了VDD_IO,所以應該與編程無關,硬件上提供了高電平。所以第一步硬件做了。




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]







3.3 根據時鐘頻率和內存t_AC參數設置PhyControl1.ctrl_shiftcandPhyControl1.ctrl_offsetc爲正確的值

代碼如下:

	ldr r1, =0x2046
	str r1,[r0,#0x1C]





3.4 設置PhyControl0.ctrl_start爲1

這一步簡單 直接給出代碼:

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

3.5 設置ConControl關閉自動刷新


代碼如下:

	ldr r1, =0x0FFF13A8
	str r1,[r0,#0x0]




3.6 設置MemControl關閉所有的掉電模式

代碼如下:

	ldr r1, =0x00212400
	str r1,[r0,#0x4]




3.7 設置MemConfig0

因爲我們只使用了一個內存控制器,DMC0所以配置MemConfig0,如果使用了兩個DMC0和DMC1那麼要配置MemConfig1
這個寄存器的配置要看K4T1G164QE.pdf手冊:K4T1G164QE名字裏面的4就說明了是8個bank。地址數據線條數可以查看原理圖。

代碼如下:
	ldr r1, =0x20E00323
	str r1,[r0,#0x8]
	







3.8 設置PrechConfigandPwrdnConfig

代碼如下:

	ldr r1, =0xFF000000
	ldr r1,[r0,#0x14]
	
	ldr r1, =0xFFFF00FF
	str r1,[r0,#0x28]






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]
	




下圖(時序參數)來自於內存芯片手冊














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



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]



3.13 開機等待200us是時鐘平穩,這一步不用開機到內存初始化肯定時鐘平穩了


3.14 使用DirectCmd發送NOP命令,確保CKE保持爲高電平

代碼如下:

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




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]




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]



3.24 最少等200個時鐘週期


3.25使用DirectCmd發送EMRS命令,設置OCD校正

代碼如下:

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




3.26  無


3.27 設置ConControl啓動自動刷新計數器

代碼如下:

	ldr r1, =0x0FFF13B8
	str r1,[r0,#0x0]






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

最後燒寫,測試效果截圖如下:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章