Hi3556v200 u-boot+Liteos方案启动流程分析--1.Hi3556v200 start.S分析

1.前言

本文主要就Hi3556v200的U-boot+Liteos方案的启动流程做简要介绍, 本文主要分析Hi3556v200下的start.S文件。
U-boot版本:u-boot-2016.11

2.启动整体流程

上电时,会从BROM开始启动,此处猜测会将flash中前部分的代码拷贝到SRAM(需要保证不使用绝对跳转,只使用BL相对跳转),然后在SRAM中执行DDR的初始化,然后将hi uboot从flash搬移到ddr,然后执行DDR中的uboot代码(通过LDR绝对跳转)

3.1 程序入口
3.2 返回调用处
3.3 关中断并进入SVC32模式
3.4 设置异常向量表
3.5 cpu_init_cp15
3.6 check if ziju flag
3.7 normal_start_flow
3.8 enable syscnt
3.9 check_boot_type
3.10 do_clr_remap
3.11enable I-Cache
3.12 ddr_init
3.13 check_boot_mode
3.14 copy_flash_to_ddr
3.15 copy_to_ddr
3.16 relocate
3.17 _start_armboot
3.18 start_armboot

3.启动流程分析

3.1 程序入口

uboot/u-boot-2016.11/arch/arm/cpu/armv7/hi3556v200
.globl  _start
_start:
        b       reset

由uboot.lds链接脚本,我们知道整个程序的入口取决于中ENTRY声明的地方。
在uboot.lds中有ENTRY(_start),因此_start符号所在的文件就是整个程序的起始文件,_start所在的代码就是整个程序的起始代码。
.globl XX 语法:给XX外部连接的属性,一般为了在别的文件中引用这个符号
_start后面加上一个冒号’ :’,表示_start是一个标号
_start: b reset 程序开始,跳到reset标号去执行,执行完后不返回

3.2 返回调用处

reset:
        /* Allow the board to save important registers */
        b       save_boot_params

ENTRY(save_boot_params)
        b       save_boot_params_ret            @ back to my caller
ENDPROC(save_boot_params)
        .weak   save_boot_params

由于此时栈还没有初始化,因此不能保存任何的寄存器,直接返回

3.3 关中断并进入SVC32模式

/*
* disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
* except if in HYP mode already
*/
mrs r0, cpsr
and r1, r0, #0x1f @ mask mode bits
teq r1, #0x1a @ test for HYP mode
bicne r0, r0, #0x1f @ clear all mode bits
orrne r0, r0, #0x13 @ set SVC mode
orr r0, r0, #0xc0 @ disable FIQ and IRQ
msr cpsr,r0

3.4 设置异常向量表

/*
 * Setup vector:
 * (OMAP4 spl TEXT_BASE is not 32 byte aligned.
 * Continue to use ROM code vector only in OMAP4 spl)
 */
#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))
        /* Set V=0 in CP15 SCTLR register - for VBAR to point to vector */
        mrc     p15, 0, r0, c1, c0, 0   @ Read CP15 SCTLR Register
        bic     r0, #CR_V               @ V = 0
        mcr     p15, 0, r0, c1, c0, 0   @ Write CP15 SCTLR Register

        /* Set vector address in CP15 VBAR register */
        adrl    r0, _start
        mcr     p15, 0, r0, c12, c0, 0  @Set VBAR
#endif

3.5 cpu_init_cp15

       /* the mask ROM code should have PLL and others stable */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
        bl      cpu_init_cp15
#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
        bl      cpu_init_crit
#endif
#endif

3.6 check if ziju flag(TODO)

  /*
     *  read system register REG_SC_GEN2
     *  check if ziju flag
     */
    ldr     r0, =SYS_CTRL_REG_BASE
    ldr     r1, [r0, #REG_SC_GEN2]
    ldr     r2, =0x7a696a75          /* magic for "ziju" */
    cmp     r1, r2
    bne     normal_start_flow
    mov     r1, sp                   /* save sp */
    str     r1, [r0, #REG_SC_GEN2]  /* clear ziju flag */

3.7 normal_start_flow

normal_start_flow:
        /* init serial and printf a string. */
        ldr     sp, =STACK_TRAINING
#ifdef ENABLE_MINI_BOOT
        bl      timer_init
#else
        bl      uart_early_init
        bl      msg_main_cpu_startup
#endif

3.8 enable syscnt

 /*
         * enable syscnt
         */
        ldr     r0, =SYSCNT_REG_BASE
        ldr     r3, =SYSCNT_FREQ
        str     r3, [r0, #SYSCNT_FREQ_REG]
        mov     r3, #0x1
        str     r3, [r0, #SYSCNT_ENABLE_REG]

        @if running not boot from nand/spi/emmc,
        @we skipping boot_type checking.
        mov    r0, pc, lsr#24
        cmp    r0, #0x0
        bne    do_clr_remap

3.9 check_boot_type

check_boot_type:
#ifndef ENABLE_MINI_BOOT
    ldr     r0, =SYS_CTRL_REG_BASE
    ldr     r0, [r0, #REG_SYSSTAT]
    mov     r6, r0, lsr#4
        and     r6, #0x1
    cmp     r6, #0x1
    ldrlo   pc, _clr_remap_fmc_entry
#else
        ldr pc, _clr_remap_fmc_entry
#endif

3.10 do_clr_remap

do_clr_remap:
#ifndef ENABLE_MINI_BOOT
        /* do clear remap */
        ldr     r4, =SYS_CTRL_REG_BASE
        ldr     r0, [r4, #REG_SC_CTRL]

        @Set clear remap bit.
        orr     r0, #(1<<8)
        str     r0, [r4, #REG_SC_CTRL]
#endif

3.11enable I-Cache

@enable I-Cache now
        mrc p15, 0, r0, c1, c0, 0
    orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
    mcr p15, 0, r0, c1, c0, 0

        @Check wether I'm running in dynamic mem bank:<0x80000000
        mov r0, pc, lsr#28
        cmp r0, #8
        blo     ddr_init

3.12 ddr_init

ddr_init:
        ldr     r0, _blank_zone_start
        ldr     r1, _TEXT_BASE
        sub     r0, r0, r1
        adrl    r1, _start
        add     r0, r0, r1
        mov     r1, #0          /* flags: 0->normal 1->pm */
        bl      init_registers

        ldr     sp, =STACK_TRAINING
        ldr     r0, =REG_BASE_SCTL
        bl      start_ddr_training       /* DDR training */

3.13 check_boot_mode

check_boot_mode:
#ifndef ENABLE_MINI_BOOT
        ldr     r0, =SYS_CTRL_REG_BASE
        ldr     r0, [r0, #REG_SYSSTAT]
        mov     r6, r0, lsr#4
        and     r6, #0x1
        cmp     r6, #BOOT_FROM_EMMC
        bne     copy_flash_to_ddr
#else
        b copy_flash_to_ddr
#endif

3.14 copy_flash_to_ddr

copy_flash_to_ddr:
        /* relocate SPI nor/nand Boot to DDR  */
        ldr     r0, =FMC_TEXT_ADRS

3.15 copy_to_ddr

copy_to_ddr:
        /* now, r0 stores __reset offset from where we get started */
        ldr     r1, =__image_copy_start

        /* compare source and target address, *
         *if equal no copy to target address */
        cmp     r0, r1
        beq     start_armboot

        ldr     r2, =__image_copy_start/*_start*/
        ldr     r3, =__bss_start
        sub     r2, r3, r2      /* r2 <- size of armboot */
        /* memcpy(r1, r0, r2) */
        bl      memcpy

3.16 relocate

relocate:
        ldr r0, =_start_armboot
        ldr pc, [r0]

3.17 _start_armboot

_start_armboot:
        .word start_armboot

此处可以理解为_start_armboot是一个地址,里面的内容是start_armboot
此处.word的作用是放置一个变量,变量内容为start_armboot函数的地址

3.18 start_armboot

位于u-boot-2016.11/arch/arm/cpu/armv7/hi3556v200/hw_compressed/startup.c中,有如下定义:

const unsigned long IMAGE_ENTRY = (CONFIG_SYS_TEXT_BASE);

osdrv/opensource/uboot/u-boot-2016.11/include/configs/hi3556v200.h中有如下的定义:

#define CONFIG_SYS_TEXT_BASE        0x80800000

如上地址正是编译通用u-boot.bin的链接地址

/uboot/u-boot-2016.11/arch/arm/cpu/armv7/hi3516av300/hw_compressed/image_data.S文件定义如下,将uboot.bin的压缩文件嵌入到此汇编文件,它的起始地址为input_data

.section .image,#alloc
.globl  input_data
/*gzip source addr must be 16 bytes aligned*/
.balign 16
input_data:
.incbin   "image_data.gzip"

.globl    input_data_end
input_data_end:

回到u-boot-2016.11/arch/arm/cpu/armv7/hi3556v200/hw_compressed/startup.c

 pdst_l32 = (unsigned char *)IMAGE_ENTRY;
 image_data_len = input_data_end - input_data;
ret = hw_dec_decompress(pdst_l32, &pdst_len, input_data, image_data_len, NULL);

如上将通用u-boot.bin的压缩文件解压到pdst_l32地址也就是与uboot.bin的链接地址相同

   uboot = (void (*))CONFIG_SYS_TEXT_BASE;
    invalidate_icache_all();
    uboot();

osdrv/opensource/uboot/u-boot-2016.11/include/configs/hi3556v200.h中:

#define CONFIG_SYS_TEXT_BASE        0x80800000

通过调用uboot运行通用uboot的代码,首先将从start.S开始执行, 执行地址为0x80800000,注意到此前Hi uboot的执行和加载地址为0x80700000,两者之间有1M的空隙

4.参考文档

  1. https://caibiao-lee.blog.csdn.net/article/details/103292583
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值