从零开始的UBOOT的学习5--start.s上
1、start.s包含的头文件的意思
一定要记住,UBOOT是使用配置的方式,使其能够支持如此多的开发板的。
回顾mkconfig.mk文件产生的4个符号链接,此4个符号链接会将来能够找到头文件起到了关键性的作用。
(1)在include目录下面创建asm文件,指向asm-arm
(2)在include/asm-arm下创建一个arch文件,指向include/asm-arm/arch-s5pc110
(3)在include目录下面创建regs.h文件,指向include/s5pc110.h,并删除第二个符号链接。
(4)在inlcude/asm-arm下创建一个arch文件,指向include/asm-arm/arch-s5pc11x
(5)在include/asm-arm下创建一个proc文件,指向include/asm-arm/proc-armv
#include <config.h>
#include <version.h>
#if defined(CONFIG_ENABLE_MMU)
#include <asm/proc/domain.h>
#endif
#include <regs.h>
(1)config.h文件在整个没有进行编译过的UBOOT文件中是查找不到的,因为他是通过配置编译产生的。
下面的程序证明是通过mkconfig脚本文件产生的。
首先是创建config.h文件。
然后把#include\<configs/x210_sd.h
if [ "$APPEND" = "yes" ] # Append to existing config file
then
echo >> config.h
else
> config.h # Create new config file
fi
echo "/* Automatically generated - do not edit */" >>config.h
echo "#include <configs/$1.h>" >>config.h
(2)version.h头文件的映射关系
version.h-->include/version_autogenerated.h
include/version_autogenerated.h:
#define U_BOOT_VERSION "U-boot 3.1.4"
(3)asm/proc/domain.h文件的映射关系
include/asm-arm/proc-armv/domain.h
相当于映射到这个目录下面。
(4)regs.h文件的映射关系。
相当于对应s5pc110.h的关系芯片的架构的文件。
2、异常向量表的构建
(1)CONFIG_EVT1变量在x210_sd.h文件中进行定义
而且CONFIG_FUSED变量在上面没有定义。
然后就可以定义一个整型数组
(2)然后下面的是创建异常中断向量表
其实UBOOT并没有为所有的异常向量表进行处理,这里不在分析。
关键的入口代码b reset
(3).balignl 16,0xdeadbeef此地方是用来进行字节对齐的。
#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
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
.balignl 16,0xdeadbeef
3、定义链接地址和UBOOT的物理地址
(1)_TEXT_BASE: 此处是链接脚本的基地址:
TEXT_BASE是Makefile中
make x210_sd_config
里面的链接地址。
CFG_PHY_UBOOT_BASE:这个地方式使用UBOOT的物理地址。
_TEXT_BASE:
.word TEXT_BASE
_TEXT_PHY_BASE:
.word CFG_PHY_UBOOT_BASE
4、复位后需要完成
reset:
msr cpsr_c, #0xd3 @ I & F disable, Mode: 0x13 - SVC
/* SD/MMC BOOT */
cmp r2, #0xc
moveq r3, #BOOT_MMCSD
(1)在复位的时候,msr cpsr_c,#0xd3
此处的CPSR是把IRQ和FIQ的中断模式去掉,并且使得芯片处于ARM模式下面,然后模式处于SVC模式下面。
(2)SD卡和MMC的启动过程
5、lowlevel_init函数完成的事情
(1)因为此时UBOOT启动阶段还是处于SRAM里面中,但是我们需要调用函数lowlevel_init,所以我们需要使用栈才可以调用函数。
这里是UBOOT的第一次使用栈的代码
ldr sp, =0xd0036000 /* end of sram dedicated to u-boot */
sub sp, sp, #12 /* set stack */
mov fp, #0
(2)因为后面需要跳到别的函数中进行
push lr 把此处的地址压入到堆栈当中。
此处开始说明了底层初始化的函数需要说明的地方:
(1)check reset status
检查复位的状态
(2)disable watchdog
关闭看门狗
(3)判断开发板是否处于重定位的阶段
如果我们判断此时我们的代码在SRAM里面的话,那么我们需要重新的初始化系统时钟
初始化内存管理。
为什么?根本原因就是因为UBOOT是一个裸机程序,裸机程序所有的事情都需要你进行配置。
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 1f /* r0 == r1 then skip sdram init */
/* init system clock */
bl system_clock_init
/* Memory initialize */
bl mem_ctrl_asm_init
(4)uart_asm_init进行串口的初始化
在串口初始化的过程中打印一个'O'
因为串口初始化是一个函数,最后可以返回刚刚压入LR寄存器的一个地址。
因为用汇编语言初始化了串口了,所以后面都可以使用串口的初始化函数了。后面又用串口初始化了一个'K'
ldr r1, =0x4f4f4f4f
str r1, [r0, #UTXH_OFFSET] @'O'
mov pc, lr
/* Print 'K' */
ldr r0, =ELFIN_UART_CONSOLE_BASE
ldr r1, =0x4b4b4b4b
str r1, [r0, #UTXH_OFFSET]
6、开发板供电锁存和在DDR中设置栈
前面的在E010E81C此个寄存器当中写入:5301字可以使用供电锁存。
中间的内容是实现长跳转的指令;为什么,因为此处是跳转到UBOOT的物理地址去的。在DDR中设置栈,用来调用函数的。
后面的内容是重新判断是否是重定位的代码了:
但是此处的判断是否重定位已经不一样了,本次判断是是否决定把UBOOT进行重定位,把UBOOT定位到DDR中,因为DDR中的空间更加的大。
(1)完全掉电后上电时将UBOOT的前16KB的内容开机自动的从SD卡中加载到SRAM中运行。
(2)UBOOT的第二部分,此时还是躺在SD卡的某个扇区开头的N个扇区中。此时UBOOT的第一阶段已经即将结束了。
(3)结束之前将第二部分加载到DDR中链接地址处33e00000,这个加载的过程就叫做重定位。
ldr r0, =0xE010E81C /* PS_HOLD_CONTROL register */
ldr r1, =0x00005301 /* PS_HOLD output high */
str r1, [r0]
/* get ready to call C functions */
ldr sp, _TEXT_PHY_BASE /* setup temp stack pointer */
sub sp, sp, #12
mov fp, #0 /* no previous frame, so fp=0 */
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 */
7、UBOOT如何来进行重定位?
我们内容SRAM里面自动维护了三个环境变量:
0xD0037480: globalBlockSize
0xD0037484: globalSDHClnfoBit【2】 SD通道
0xD0037488: V210_SDMMC_BASE
(1)D0037488这个内存地址在SRAM中,这个地址中的值是被硬件自动设置的,硬件根据我们实际电路中SD卡在哪个通道中,会将这个地址中的值设置为相应的数字,比如我们从SD0通道启动时,这个值为EB000000;从SD2通道启动时,这个值为EB200000。
我们是在第269行第260行确定了MMCSD启动,然后又在278行将这个#BOOT_MMCSD写入了INF_REG3寄存器中存储的,然后又在322行读出来,再和#BOOT_MMCSD去比较,确定在哪里启动。
最终跳转到MMCSD_BOOT函数中去执行这个函数。
bl movi_bl2_copy
b after_copy
(3)真正的重定位是在UBOOT/cpu/s5pc11x/movi.c
是一个C语言函数,可以从一个寄存器中考虑到UBOOT到底是从什么方式下载到开发板当中的。
(4)copy_bl2(2,MOVI_BL2_POS,MOVI_BL2_BLKCNT,CFG_PHY_UBOOT_BASE,0);
这里需要对裸机的课程进行分析验证。