QT210烧写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代码如下的用宏定义的一段:
- #ifdefined(CONFIG_EVT1)&&!defined(CONFIG_FUSED)
- .word0x2000
- .word0x0
- .word0x0
- .word0x0
- #endif
- .globl_start
- _start:breset
- ldrpc,_undefined_instruction
- ldrpc,_software_interrupt
- ldrpc,_prefetch_abort
其中的.word 0x2000 代表BL1size(8K长度),.word 0x0 为保留字节.word 0x0为checksum(后续会通过一个mkbl1工具来计算bl1的checksum并填写这个位置),最后一个.word 0x0也为保留字节。
再来看看uboot的下面的部分,如果bl0正常读取了bl1,代码就会到如下段:
- /*Readbootinginformation*/
- ldrr0,=PRO_ID_BASE
- ldrr1,[r0,#OMR_OFFSET]//读OM引脚的配置状态
- bicr2,r1,#0xffffffc1
- #ifdefCONFIG_VOGUES
- /*PS_HOLD(GPH0_0)settooutputhigh*/
- ldrr0,=ELFIN_GPIO_BASE
- ldrr1,=0x00000001
- strr1,[r0,#GPH0CON_OFFSET]
- ldrr1,=0x5500
- strr1,[r0,#GPH0PUD_OFFSET]
- ldrr1,=0x01
- strr1,[r0,#GPH0DAT_OFFSET]
- #endif
- /*NANDBOOT*/
- cmpr2,#[email protected]
- moveqr3,#BOOT_NAND//根据OM引脚配置状态来给R3寄存器赋予代表系统是从何冲外部存储器启动的配置值。
- cmpr2,#[email protected]
- moveqr3,#BOOT_NAND
- cmpr2,#[email protected]
- moveqr3,#BOOT_NAND
- cmpr2,#[email protected]
- moveqr3,#BOOT_NAND
- cmpr2,#[email protected]
- moveqr3,#BOOT_ONENAND
- /*SD/MMCBOOT*/
- cmpr2,#0xc<prename="code"class="cpp">ldrsp,_TEXT_PHY_BASE/*setuptempstackpointer*/
- subsp,sp,#12
- movfp,#0/*nopreviousframe,sofp=0*/
- /*whenwealreadyruninram,wedon'tneedtorelocateU-Boot.
- *andactually,memorycontrollermustbeconfiguredbeforeU-Boot
- *isrunninginram.
- */
- ldrr0,=0xff000fff
- bicr1,pc,r0/*r0<-currentbaseaddrofcode*/
- ldrr2,_TEXT_BASE/*r1<-originalbaseaddrinram*/
- bicr2,r2,r0/*r0<-currentbaseaddrofcode*/
- cmpr1,r2/*comparer0,r1*/
- beqafter_copy/*r0==r1thenskipflashcopy*/</pre><br>
- moveqr3,#BOOT_MMCSD/*NORBOOT*/cmpr2,#0x14moveqr3,#BOOT_NOR#if0/*AndroidC110BSPusesOneNANDbooting!*//*Forseconddevicebooting*//*OneNANDBOOTONGfailed*/cmpr2,#0x8moveqr3,#BOOT_SEC_DEV#endif/*UartBOOTONGfailed*/cmpr2,#(0x1<<4)moveq
- r3,#BOOT_SEC_DEVldrr0,=INF_REG_BASEstrr3,[r0,#INF_REG3_OFFSET]//将配置值存入到用户使用的寄存器中,方便以后使用的时候读取此寄存器来了解此次启动时从何种外部存储设备启动
- <pre></pre>
- <p></p>
- <pre></pre>
- <prename="code"class="cpp">//ldrsp,=0xd0036000/*endofsramdedicatedtou-boot*/
- ldrsp,=0xd0035400//BL1段的函数进行操作的堆栈位置,这里我修改了堆栈到了0xd0035400是由于图2中所示BL0代码进行了它自己代码堆栈的初始化,而RW/ZIregionHeap的最低部就位于0xd0035400,为了不修改BL0堆栈和BL0代码已经写好的一些函数功能(会在下面用到),我将堆栈修改到了0xd0035400
- subsp,sp,#12/*setstack*/
- movfp,#0
- bllowlevel_init/*gosetuppll,mux,memory*///这里会进行始终,内存,串口初始化</pre>
- <p>之后运行到</p>
- <p></p>
- <prename="code"class="cpp">ldrsp,_TEXT_PHY_BASE/*setuptempstackpointer*///由于上面一步已经初始化了DRAM,所以在这里将以后的堆栈设置到了DRAM中的位置(以后BL2代码中函数都是基于此堆栈)
- subsp,sp,#12
- movfp,#0/*nopreviousframe,sofp=0*/
- /*whenwealreadyruninram,wedon'tneedtorelocateU-Boot.
- *andactually,memorycontrollermustbeconfiguredbeforeU-Boot
- *isrunninginram.
- */
- ldrr0,=0xff000fff
- bicr1,pc,r0/*r0<-currentbaseaddrofcode*/
- ldrr2,_TEXT_BASE/*r1<-originalbaseaddrinram*///加载程序要运行的编译地址,同现在程序运行的地址比较
- bicr2,r2,r0/*r0<-currentbaseaddrofcode*/
- cmpr1,r2/*comparer0,r1*/
- beqafter_copy/*r0==r1thenskipflashcopy*///如果两地址相等,代码程序已经再DRAM中运行不必再拷贝,不相等代表程序没有在编译地址运行,还要拷贝代码到编译地址去,最后跳到对应编译地址内运行代码。</pre><prename="code"class="cpp">ldrr0,=INF_REG_BASE
- ldrr1,[r0,#INF_REG3_OFFSET]
- cmpr1,#BOOT_NAND/*0x0=>bootdeviceisnand*/
- beqnand_boot
- cmpr1,#BOOT_ONENAND/*0x1=>bootdeviceisonenand*/
- beqonenand_boot
- cmpr1,#BOOT_MMCSD
- beqmmcsd_boot
- cmpr1,#BOOT_NOR
- beqnor_boot
- cmpr1,#BOOT_SEC_DEV
- beqmmcsd_boot//代码判断要拷贝后,读取之前存入到用户使用寄存器中的值来判断此次启动从何种外部存储设备启动,这里为sd卡启动
- ~~~~~省略若干代码~~~~~~~~
- mmcsd_boot:
- #ifDELETE
- ldrsp,_TEXT_PHY_BASE
- subsp,sp,#12
- movfp,#0
- #endif
- blmovi_bl2_copy//最后BL1代码来到此处从sd卡拷贝剩余的代码
- bafter_copy</pre><br>
- <pre></pre>
- <prename="code"class="cpp"></pre>