世界早已進入cortex-a8了,我也得跟進一下所以買了QT210的開發板。
長話短說開始搞SD卡燒寫UBOOT,從SD啓動UBOOT。
從s5pv210_irom_applicationnote_preliminary_20091126.pdf知道,s5pv210啓動分BL0、BL1、BL2階段。BL0是s5pv210內部IROM固化的代碼,這段代碼根據OM引腳配置狀態來選擇從哪個外部存儲設備加載BL1段代碼(實際上BL1代碼就是我們編寫的UBOOT的前8K代碼,這段代碼要包含完整的將後半部UBOOT代碼複製和清bss段的功能,當然我們要從SD卡啓動燒寫在上面的UBOOT,OM引腳就必須配置爲從SD卡啓動配置)。
圖1
從上圖可知,從sd啓動的時候BL0加載的代碼是從第512個字節處開始加載代碼,爲什麼要這樣做呢?由於以後功能擴展的需要三星的軟件工程師寫的固化到IROM中的BL0代碼是從SD卡的512字節處加載BL1的,他就是這樣寫的,我們對應UBOOT放置在SD卡中的位置就要往後移動512字節,後面有介紹怎麼指定把uboot寫到sd卡指定的位置的命令。
還有一定要注意如下所示的地方:
圖2
在BL1之前要加16個字節的頭部信息。也就是在真正的UBOOT第一條指令之前要加16個字節的頭部信息,於是就有我們所看到的uboot代碼如下的用宏定義的一段:
- #if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)
- .word 0x2000
- .word 0x0
- .word 0x0
- .word 0x0
- #endif
- .globl _start
- _start: b reset
- ldr pc, _undefined_instruction
- ldr pc, _software_interrupt
- ldr pc, _prefetch_abort
其中的 .word 0x2000 代表BL1size(8K長度),.word 0x0 爲保留字節 .word 0x0爲checksum(後續會通過一個mkbl1工具來計算bl1的checksum並填寫這個位置),最後一個.word 0x0也爲保留字節。
再來看看uboot的下面的部分,如果bl0正常讀取了bl1,代碼就會到如下段:
- /* Read booting information */
- ldr r0, =PRO_ID_BASE
- ldr r1, [r0,#OMR_OFFSET] //讀OM引腳的配置狀態
- bic r2, r1, #0xffffffc1
- #ifdef CONFIG_VOGUES
- /* PS_HOLD(GPH0_0) set to output high */
- ldr r0, =ELFIN_GPIO_BASE
- ldr r1, =0x00000001
- str r1, [r0, #GPH0CON_OFFSET]
- ldr r1, =0x5500
- str r1, [r0, #GPH0PUD_OFFSET]
- ldr r1, =0x01
- str r1, [r0, #GPH0DAT_OFFSET]
- #endif
- /* NAND BOOT */
- cmp r2, #0x0 @ 512B 4-cycle
- moveq r3, #BOOT_NAND //根據OM引腳配置狀態來給R3寄存器賦予代表系統是從何衝外部存儲器啓動的配置值。
- cmp r2, #0x2 @ 2KB 5-cycle
- moveq r3, #BOOT_NAND
- cmp r2, #0x4 @ 4KB 5-cycle 8-bit ECC
- moveq r3, #BOOT_NAND
- cmp r2, #0x6 @ 4KB 5-cycle 16-bit ECC
- moveq r3, #BOOT_NAND
- cmp r2, #0x8 @ OneNAND Mux
- moveq r3, #BOOT_ONENAND
- /* SD/MMC BOOT */
- cmp r2, #0xc<pre name="code" class="cpp"> ldr sp, _TEXT_PHY_BASE /* setup temp stack pointer */
- sub sp, sp, #12
- mov fp, #0 /* no previous frame, so fp=0 */
- /* when we already run in ram, we don't need to relocate U-Boot.
- * and actually, memory controller must be configured before U-Boot
- * is running in ram.
- */
- ldr r0, =0xff000fff
- bic r1, pc, r0 /* r0 <- current base addr of code */
- ldr r2, _TEXT_BASE /* r1 <- original base addr in ram */
- bic r2, r2, r0 /* r0 <- current base addr of code */
- cmp r1, r2 /* compare r0, r1 */
- beq after_copy /* r0 == r1 then skip flash copy */</pre><br>
- moveq r3, #BOOT_MMCSD/* NOR BOOT */cmp r2, #0x14moveq r3, #BOOT_NOR#if 0 /* Android C110 BSP uses OneNAND booting! *//* For second device booting *//* OneNAND BOOTONG failed */cmp r2, #0x8moveq r3, #BOOT_SEC_DEV#endif/* Uart BOOTONG failed */cmp r2, #(0x1<<4)moveq
- r3, #BOOT_SEC_DEVldr r0, =INF_REG_BASEstr r3, [r0, #INF_REG3_OFFSET] //將配置值存入到用戶使用的寄存器中,方便以後使用的時候讀取此寄存器來了解此次啓動時從何種外部存儲設備啓動
- <pre></pre>
- <p></p>
- <pre></pre>
- <pre name="code" class="cpp"> //ldr sp, =0xd0036000 /* end of sram dedicated to u-boot */
- ldr sp, =0xd0035400 //BL1段的函數進行操作的堆棧位置,這裏我修改了堆棧到了0xd0035400是由於圖2中所示BL0代碼進行了它自己代碼堆棧的初始化,而RW/ZI region Heap的最低部就位於0xd0035400,爲了不修改BL0堆棧和BL0代碼已經寫好的一些函數功能(會在下面用到),我將堆棧修改到了0xd0035400
- sub sp, sp, #12 /* set stack */
- mov fp, #0
- bl lowlevel_init /* go setup pll,mux,memory */ //這裏會進行始終,內存,串口初始化</pre>
- <p>之後運行到</p>
- <p></p>
- <pre name="code" class="cpp"> ldr sp, _TEXT_PHY_BASE /* setup temp stack pointer */ //由於上面一步已經初始化了DRAM,所以在這裏將以後的堆棧設置到了DRAM中的位置(以後BL2代碼中函數都是基於此堆棧)
- sub sp, sp, #12
- mov fp, #0 /* no previous frame, so fp=0 */
- /* when we already run in ram, we don't need to relocate U-Boot.
- * and actually, memory controller must be configured before U-Boot
- * is running in ram.
- */
- ldr r0, =0xff000fff
- bic r1, pc, r0 /* r0 <- current base addr of code */
- ldr r2, _TEXT_BASE /* r1 <- original base addr in ram */ //加載程序要運行的編譯地址,同現在程序運行的地址比較
- bic r2, r2, r0 /* r0 <- current base addr of code */
- cmp r1, r2 /* compare r0, r1 */
- beq after_copy /* r0 == r1 then skip flash copy */ //如果兩地址相等,代碼程序已經再DRAM中運行不必再拷貝,不相等代表程序沒有在編譯地址運行,還要拷貝代碼到編譯地址去,最後跳到對應編譯地址內運行代碼。</pre><pre name="code" class="cpp"> ldr r0, =INF_REG_BASE
- ldr r1, [r0, #INF_REG3_OFFSET]
- cmp r1, #BOOT_NAND /* 0x0 => boot device is nand */
- beq nand_boot
- cmp r1, #BOOT_ONENAND /* 0x1 => boot device is onenand */
- beq onenand_boot
- cmp r1, #BOOT_MMCSD
- beq mmcsd_boot
- cmp r1, #BOOT_NOR
- beq nor_boot
- cmp r1, #BOOT_SEC_DEV
- beq mmcsd_boot //代碼判斷要拷貝後,讀取之前存入到用戶使用寄存器中的值來判斷此次啓動從何種外部存儲設備啓動,這裏爲sd卡啓動
- ~~~~~省略若干代碼~~~~~~~~
- mmcsd_boot:
- #if DELETE
- ldr sp, _TEXT_PHY_BASE
- sub sp, sp, #12
- mov fp, #0
- #endif
- bl movi_bl2_copy //最後BL1代碼來到此處從sd卡拷貝剩餘的代碼
- b after_copy</pre><br>
- <pre></pre>
- <pre name="code" class="cpp"></pre>