从零开始的UBOOT的学习5--start.s上

从零开始的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);

这里需要对裸机的课程进行分析验证。

猜你喜欢

转载自blog.csdn.net/dhauwd/article/details/80216452
今日推荐