第七章:基於九鼎X210開發板移植2014.10版U-boot之初始化時鐘模組
重新燒錄,啟動,發現可以正常執行,然後卡死在DRAM之後,還打印出了一個O,這個O看起來挺熟悉的,開機時候列印的那個O?一下子就想到,我們雖然自己移植的那個重定位程式碼(拷貝BL2到記憶體中),但原版程式碼中應該也有一份,要將它移除。
首先定位到DRAM是由board.c中的board_init_f函式呼叫display_dram_config打印出,board_init_f函式被crt0.S中的_main中被呼叫,看到這裡可以很明顯的看出,呼叫完board_init_f之後就開始執行程式碼重定位了。那麼,將這段程式碼遮蔽掉,應該就能解決上述問題。
再往下看程式碼,發現一個小細節問題,呼叫了coloured_LED_init
編譯完後,再次啟動,問題解決,進入了命令列,但是還是有一些問題還需要修改。
首先可以看到cpu打印出來的時鐘不對,其次就是sdhci應該是nand初始化失敗了吧,這裡我為了驗證猜想,使用了uboot提供的mmc操作命令,讀取nand中的某塊資料出來,但結果顯示有問題。
目前就開始著手解決這兩個問題吧。
Cpu時鐘的初始化在2014.10版中的lowlevel_init.S中有寫,但是並未被呼叫。這裡可以分析下到底都做了些啥。
彙編不常用,細節就不寫了,大致就是讀取CPU的id號,來判斷是S5PV100還是V110,我們的晶片是s5pv210,暫存器和110是相同的。Review完程式碼後,我們發現開頭對cpu的判斷會在system_clock_init
程式碼處理完後,就需要對時鐘相關的暫存器進行配置了,這裡我偷懶了,直接在網上看到別人寫的帖子,覺得不錯,直接用他的資料好了。
參考:http://blog.csdn.net/u010346967/article/details/46461255
他這裡設定的時鐘是datasheet推薦的,和我之前移植三星版本的uboot一致。
首先將PWR_CFG暫存器的地址放入r0暫存器,大致就是為了方便下面三個暫存器的設定,這三個暫存器分別為OSC_FREQ、MTC_STABLE、CLAMP_STABLE,查了資料手冊,並不是很理解這幾個暫存器是設定啥的,而這個章節講的是cpu的電源模式。system_clock_init: /* Check S5PC100 */ ldr r0, =0xE010C000 @ S5PC110_PWR_CFG /* Set OSC_FREQ value */ ldr r1, =0xf str r1, [r0, #0x100] @ S5PC110_OSC_FREQ /* Set MTC_STABLE value */ ldr r1, =0xffffffff str r1, [r0, #0x110] @ S5PC110_MTC_STABLE /* Set CLAMP_STABLE value */ ldr r1, =0x3ff03ff str r1, [r0, #0x114] @ S5PC110_CLAMP_STABLE
ldr r0, =S5PC110_CLOCK_BASE @ 0xE0100000
/* Set Clock divider */
ldr r1, =0x14131330 @ 1:1:4:4, 1:4:5
str r1, [r0, #0x300]
ldr r1, =0x11110111 @ UART[3210]: MMC[3210]
str r1, [r0, #0x310]
/* Set Lock Time */
ldr r1, =0x2cf @ Locktime : 30us
str r1, [r0, #0x000] @ S5PC110_APLL_LOCK
ldr r1, =0xe10 @ Locktime : 0xe10 = 3600
str r1, [r0, #0x008] @ S5PC110_MPLL_LOCK
str r1, [r0, #0x010] @ S5PC110_EPLL_LOCK
str r1, [r0, #0x020] @ S5PC110_VPLL_LOCK
/* S5PC110_APLL_CON */
ldr r1, =0x80C80601 @ 800MHz
str r1, [r0, #0x100]
/* S5PC110_MPLL_CON */
ldr r1, =0x829B0C01 @ 667MHz
str r1, [r0, #0x108]
/* S5PC110_EPLL_CON */
ldr r1, =0x80600602 @ 96MHz VSEL 0 P 6 M 96 S 2
str r1, [r0, #0x110]
/* S5PC110_VPLL_CON */
ldr r1, =0x806C0603 @ 54MHz
str r1, [r0, #0x120]
/* Set Source Clock */
ldr r1, =0x10001111 @ A, M, E, VPLL Muxing
str r1, [r0, #0x200] @ S5PC1XX_CLK_SRC0
/* OneDRAM(DMC0) clock setting */
ldr r1, =0x01000000 @ ONEDRAM_SEL[25:24] 1 SCLKMPLL
str r1, [r0, #0x218] @ S5PC110_CLK_SRC6
ldr r1, =0x30000000 @ ONEDRAM_RATIO[31:28] 3 + 1
str r1, [r0, #0x318] @ S5PC110_CLK_DIV6
oneDRAM,開發板中沒有,可以刪除。
/* XCLKOUT = XUSBXTI 24MHz */
add r2, r0, #0xE000 @ S5PC110_OTHERS
ldr r1, [r2]
orr r1, r1, #(0x3 << 8) @ CLKOUT[9:8] 3 XUSBXTI
str r1, [r2]
/* CLK_IP0 */
ldr r1, =0x8fefeeb @ DMC[1:0] PDMA0[3] IMEM[5]
str r1, [r0, #0x460] @ S5PC110_CLK_IP0
/* CLK_IP1 */
ldr r1, =0xe9fdf0f9 @ FIMD[0] USBOTG[16]
@ NANDXL[24]
str r1, [r0, #0x464] @ S5PC110_CLK_IP1
/* CLK_IP2 */
ldr r1, =0xf75f7fc @ CORESIGHT[8] MODEM[9]
@ HOSTIF[10] HSMMC0[16]
@ HSMMC2[18] VIC[27:24]
str r1, [r0, #0x468] @ S5PC110_CLK_IP2
/* CLK_IP3 */
ldr r1, =0x8eff038c @ I2C[8:6]
@ SYSTIMER[16] UART0[17]
@ UART1[18] UART2[19]
@ UART3[20] WDT[22]
@ PWM[23] GPIO[26] SYSCON[27]
str r1, [r0, #0x46c] @ S5PC110_CLK_IP3
/* CLK_IP4 */
ldr r1, =0xfffffff1 @ CHIP_ID[0] TZPC[8:5]
str r1, [r0, #0x470] @ S5PC110_CLK_IP3
/* wait at least 200us to stablize all clock */
mov r2, #0x10000
1: subs r2, r2, #1
bne 1b
這部分應該就是和一些內部外設相關的時鐘開啟這類的,先放著不管。修改完時鐘相關的暫存器後,在lowlevel_int中執行system_clock_init。
理論上是不會有太大問題,但是為了驗證是否正確,我移植了三星版本的一個列印各時鐘頻率的函式,移植完後,發現沒有太大的問題。而且之前mmc初始化失敗的問題也被解決了,但是隻是沒有初始化失敗的log而已,所以還是要對mmc進行驗證下。
首先先測試一下,是否能夠對環境變數進行儲存,環境變數會在程式碼中儲存一份,如果儲存裝置不存在環境變數的話,就會先呼叫這份程式碼中的環境變數,因此我們先對這份環境變數進行更改。
開機後在uboot命令列中輸入pri,結果打印出一堆引數,然後通過這些引數定位到X210.h中,接下來就是修改這些環境變數。
將沒用的環境變數遮蔽掉,再次燒錄sd卡並啟動,列印環境變數,嗯,整潔多了。
之後set一個環境變數,並儲存,重啟後,發現環境變數存在,因此可以證明nand是可以使用的,當然,我們還可以直接對mmc read/write進行讀寫測試,寫入一些資料,再讀取出來,如果正確也可以說明mmc可以使用。
Nand、Mmc這類裝置的相容性比較強,移植uboot的時候,大多數都是不需要過多的修改就能使用了。