S5PV210內存一般會使用SDRAM和DDR2 (DDR SDRAM),SDRAM的uboot啟動網絡已經有很多資料的,對於DDR2還有有很多疑惑,如果有錯誤的地方,請大家一定指出,醍醐灌頂,不勝感激。
1、S5PV210的memory map(物理地址)
如下圖:左圖是整個芯片的內存空間(物理地址),右圖是iROM部分的內存空間(BL0的地址貌似不是物理地址==)
2、U-Boot內存分配圖
2.u-boot映像的地址0並非指物理地址0,由不同的啟動方式映射到不同的地址。例如v210是映射到0xD0000000處的irom。
3.TEXT_BASE等指向SDRAM的地址均為虛擬地址。
4.TEXT_BASE為頂層Makefile中定義的,例如三星官方BSP中定義的是0xC3E00000,它是程序實際的鏈接首地址。
5.SDRAM_BASE被MMU映射在0xC0000000。
6._end和__bss_start為鏈接腳本文件中最后定義的bss段,在鏈接時確定,並與u-boot映像編譯在一起。
7.在bl1段運行時,u-boot映像被復制到TEXT_BASE開始的地址處。
8. u-boot分配用戶棧頂的代碼為:
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ 將0xc3e00000加載到r0
sub r0, r0, #CFG_MALLOC_LEN /* malloc area */ r0減去0x4000的malloc域
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */ r0減去128字節的全局結構體
#if defined(CONFIG_USE_IRQ)
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) 如果用戶有使用IRQ,再減去2*4*1024的中斷棧空間
#endif
sub sp, r0, #12 /* leave 3 words for abort-stack */ 為取址終止異常預留3個字空間后設置好用戶sp
DMC1 0x4000_0000 ~ 0x7FFF_FFFF 512MB

如果設置chip_base為0x20:
(1)我們掛載的內存為128M,那么這個chip_mask應該設置為0xF8
(2)我們掛載256M內存時,chip_mask應該設置為0xF0
(3)我們掛載512M時,chip_mask應該設置為0xE0
(4)我們掛載1GB內存時,chip_mask就應該設置為0xC0。
以DMC0為例,當DMC0接收到來自AXI的0x2000,0000~0x3fff,ffff內的地址時,會作如下處理:
(1)將AXI地址的高8位與chip_mask相與得到結果,記為X。
(2)將X分別與MEMCONFIG0和MEMCONFIG1的chip_base相比較,如果相等,則打開相應的片選。
假如掛載的內存為128M,且CS0和CS1上分別掛了一片,那么128M=128*1024*1024=0x8000000,則128M內存的偏移范圍應該是0x0000,0000~0x07ff,ffff,高位剩余5位,那么,我們把MEMCONFIG0的chip_base設置為0x20,chip_mask設置為0xF8,為了保持內存連續,則需要將MEMCONFIG1的chip_base設置為0x28,chip_mask設置為0xF8,當AXI發來的地址為0x23xx,xxxx時,0x23&0xF8得到0x20,所以,會打開片選CS0,當AXI發來的地址為0x28xx,xxxx時,0x28&0xF8得到0x28,所以,會打開片選CS1,依此類推。
特別的,當載在的內存芯片為8bank(8bank內存芯片一般為14/15行地址,10列地址,即容量一般為512M或者1G)時,由於CS1為bank2引腳,為了保持CS0時鍾處於片選狀態,對於512M內存來講需要將chip_mask設置為0xE0,這是因為512M=512*1024*1024=0x2000,0000,也就是說,512M內存的偏移應該為0x0000,0000~0x1fff,ffff,所以高位剩余3位,即0xE0,當然了,如果內存為1G=1024*1024*1024=0x4000,0000,即偏移為0x0000,0000~0x3fff,ffff,高位剩余2為,故設置chip_mask為0xC0。這樣,就會計算偏移這兩個值了。
4、 配置流程
內存芯片的配置比較復雜,好在芯片手冊上給出了常用內存類型的初始化序列,TQ210的內存是DDR2的,可以按照如下順序進行初始化:
1. To provide stable power for controller and memory device, the controller must assert and hold CKE to a logic low level. Then apply stable clock. Note: XDDR2SEL should be High level to hold CKE to low. 2. Set the PhyControl0.ctrl_start_point and PhyControl0.ctrl_inc bit-fields to correct value according to clock frequency. Set the PhyControl0.ctrl_dll_on bit-field to ‘1’ to turn on the PHY DLL. 3. DQS Cleaning: Set the PhyControl1.ctrl_shiftc and PhyControl1.ctrl_offsetc bit-fields to correct value according to clock frequency and memory tAC parameters. 4. Set the PhyControl0.ctrl_start bit-field to ‘1’. 5. Set the ConControl. At this moment, an auto refresh counter should be off. 6. Set the MemControl. At this moment, all power down modes should be off. 7. Set the MemConfig0 register. If there are two external memo ry chips, set the MemConfig1 register. 8. Set the PrechConfig and PwrdnConfig registers. 9. Set the TimingAref, TimingRow, TimingData and TimingPower registers according to memory AC parameters. 10. If QoS scheme is required, set the QosControl0~15 and QosConfig0~15 registers. 11. Wait for the PhyStatus0.ctrl_locked bit-fields to change to ‘1’. Check whether PHY DLL is locked. 12. PHY DLL compensates the changes of delay amount caused by Process, Voltage and Temperature (PVT) variation during memory operation. Therefore, PHY DLL should not be off for reliable operation. It can be off except runs at low frequency. If off mode is used, set the PhyControl0.ctrl_force bit-field to correct value according to the PhyStatus0.ctrl_lock_value[9:2] bit-field to fix delay amount. Clear the PhyControl0.ctrl_dll_on bit-field to turn off PHY DLL. 13. Confirm whether stable clock is issued minimum 200us after power on 14. Issue a NOP command using the DirectCmd register to assert and to hold CKE to a logic high level 15. Wait for minimum 400ns. 16. Issue a PALL command using the DirectCmd register. 17. Issue an EMRS2 command using the DirectCmd register to program the operating parameters. 18. Issue an EMRS3 command using the DirectCmd register to program the operating parameters. 19. Issue an EMRS command using the DirectCmd register to enable the memory DLLs. 20. Issue a MRS command using the DirectCmd register to reset the memory DLL. 21. Issue a PALL command using the DirectCmd register. 22. Issue two Auto Refresh commands using the DirectCmd register. 23. Issue a MRS command using the DirectCmd register to program the operating parameters without resetting the memory DLL. 24. Wait for minimum 200 clock cycles. 25. Issue an EMRS command using the DirectCmd register to program the operating parameters. If OCD calibration is not used, issue an EMRS command to set OCD Calibration Default. After that, issue an EMRS command to exit OCD Calibration Mode and to program the operating parameters. 26. If there are two external memory chips, perform steps 14~25 for chip1 memory device. 27. Set the ConControl to turn on an auto refresh counter. 28. If power down modes is required, set the MemControl registers.
5、代碼的鏈接地址和運行地址等注意事項
配置好內存的代碼燒寫到Nand運行是正常的,但是用USB方式啟動時不正常,目前還沒有找到原因,如果有朋友解決了或者有其他問題請留言相告,在這里先說聲謝謝。
現在找到原因了,原來S5PV210的USB啟動過程跟Nand啟動方式不一樣,S5PV210以USB方式啟動時會先將三星提供的一個固件程序下載到0xd0020010處運行,然后,再將用戶代碼下載0x23e00000處運行,也就是說,固件程序完成了內存的初始化,因為我們的代碼位於0x23e00000處。而我們的代碼中再次配置內存時會重置內存,下載到內存中的代碼也就丟失了,所以程序執行到內存初始化函數就會掛掉。
為了證明上面的假設,我在代碼中加上一段程序,該程序將內存的中代碼拷貝到iram的16K以后的位置上(直接拷貝到0xd0020000處有問題,我是拷貝到了0xd0024000處,現在還不知道什么原因),然后將代碼跳轉到IRAM中,如果代碼可以正常運行就可以證明內存初始化部分正常,實驗結果是肯定的,下面總結下:
S5PV210以USB方式啟動時用戶代碼是下載到內存中的(0x23e00000處),要使代碼以USB方式啟動時正常運行,應該注意以下兩點:
(1)如果是位置相關的代碼,連接地址應該鏈接到0x23e00000,如果是位置無關碼,可以隨便指定連接地址。
(2)用戶代碼需要檢驗自己運行時的位置,如果運行在內存中則需跳過內存初始化,根據需要決定是否需要代碼重定位。
參考網址:http://blog.chinaunix.net/uid-122754-id-3144920.html
http://www.cnblogs.com/Efronc/archive/2012/03/01/2375578.html