Learning UBOOT from scratch on 5--start.s

Learning UBOOT from scratch on 5--start.s

1. The meaning of the header files included in start.s

It is important to remember that UBOOT is configured in a way that enables it to support so many development boards.

Looking back at the 4 symbolic links generated by the mkconfig.mk file, these 4 symbolic links will play a key role in being able to find the header files in the future.

(1) Create an asm file under the include directory, point to asm-arm
(2) Create an arch file under include/asm-arm, point to include/asm-arm/arch-s5pc110
(3) Create regs under the include directory. h file, point to include/s5pc110.h, and remove the second symlink.
(4) Create an arch file under inlcude/asm-arm, point to include/asm-arm/arch-s5pc11x
(5) Create a proc file under include/asm-arm, point to 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) The config.h file cannot be found in the entire UBOOT file that has not been compiled because it is generated by configuration compilation.

The following program proved to be generated by the mkconfig script file.
The first is to create the config.h file.

Then put #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) Mapping relationship of version.h header file
version.h-->include/version_autogenerated.h

include/version_autogenerated.h:

#define U_BOOT_VERSION  "U-boot 3.1.4"

(3) Mapping relationship of asm/proc/domain.h file

include/asm-arm/proc-armv/domain.h

Equivalent to mapping to this directory.

(4) The mapping relationship of the regs.h file.

Equivalent to the file corresponding to the architecture of the relational chip of s5pc110.h.

2. Construction of exception vector table

(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);

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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325387149&siteId=291194637