RK3399 系列 U-BOOT(V2017)流程解析(一)

在这里插入图片描述

一般ROM Code是固化在芯片内部的,BL1是有厂商提供的bin文件,并不会开放源代码,所以从BL2开始。

从系统启动打印的信息可以找到BL2的入口如下,关键是_start函数。

//log
Load uboot, ReadLba = 2000     //加载uboot (BL2)
Load OK, addr=0x200000, size=0x873d4  //uboot 地址和大小 mainload结束
...
INFO:    Entry point address = 0x200000  //UBoot 入口地址

//u-boot 符号表
4019: 0000000000200000     0 NOTYPE  GLOBAL DEFAULT    1 _start

參考 RK3399——裸机大全 | hceng blog

arch/arm/cpu/armv8/start.S

20 .globl  _start
 21 _start:
 22         nop
 23         b       reset     //jump to reset


 68 reset:
 69 
 70 #ifdef CONFIG_ROCKCHIP
 71         /*
 72          * check loader tag
 73          */
 74         ldr     x0, =__loader_tag
 75         ldr     w1, [x0]
 76         ldr     x0, =LoaderTagCheck
 77         ldr     w2, [x0]
 78         cmp     w1, w2
 79         b.eq    checkok

.......

87           * Could be EL3/EL2/EL1, Initial State:
88          * Little Endian, MMU Disabled, i/dCache Disabled

97   ldr x0, =COUNTER_FREQUENCY //hceng:晶振频率:24000000hz

.............

3.配置ARM核心特定勘误表(apply_core_errata)

112         /* Apply ARM core specific erratas */
113         bl      apply_core_errata
..........

122         /* Processor specific initialization */
123         bl      lowlevel_init                 ==>    187 WEAK(lowlevel_init)
..........

是否U-Boot开启多核CPU

125 #ifdef CONFIG_ARMV8_MULTIENTRY

bl  _main //跳转到_main执行  crt0_64.S

------start.S說明-------------------------------------

CONFIG_ROCKCHIP 說明:

1. make menuconfig

 Target select (Support Rockchip arch64 SOC)  --->

 (X) Support Rockchip arch64 SOC

rockchip platform select (rk33xx platform)  --->     

       (X) rk33xx platform   

2./arch/arm/cpu/armv8/rk33xx/Kconfig

如果ROCKCHIP_ARCH64选项选中了则在endif范围内的选项才会被选

if ROCKCHIP_ARCH64
config ROCKCHIP
        bool     //
择可能:TRUE选中、FALSE不选 选中则编译,不选中则不编译。
                                        如果后面没有字符串名称,则表示其不会出现在选择软件列表中

choice
        prompt "rockchip platform select"  標題

config PLAT_RK33XX
        bool "rk33xx platform"  選項 true/fale
        select ROCKCHIP

endchoice

config SYS_CPU
        default "armv8"

config SYS_SOC
        default "rk33xx"

source "board/rockchip/rk33xx/Kconfig"

source "board/rockchip/common/Kconfig"

endif

~~~~~~~~~~~~~~~~~~

loader_tag 說明

302 #ifdef CONFIG_ROCKCHIP
          .section .loader_tag, "ax"
  //ax是allocation execute的缩写,表示该节区可分配并且可执行

/* rockchip uboot loader tag */

arch/arm/lib/sections.c
char __loader_tag[0] __attribute__((section(".__loader_tag")));

~~~~~~~~~~~~~~~~

LoaderTagCheck 說明

 39 .globl  LoaderTagCheck
 40 LoaderTagCheck:
 41         .word   0x4B415351
~~~~~~~~

97   ldr x0, =COUNTER_FREQUENCY //hceng:晶振频率:24000000hz

//include/configs/rk33plat.h:
//#define COUNTER_FREQUENCY        CONFIG_SYS_CLK_FREQ_CRYSTAL

//include/configs/rk_default_config.h:
//#define CONFIG_SYS_CLK_FREQ_CRYSTAL    24000000

====crt0_64.S===============================================

參考 uboot启动流程(5)之board_init_f 函数详解_蒋文韬的博客-CSDN博客_board_init_f

arch/arm/lib/crt0_64.S

ENTRY(_main)

1.设置栈 
2.board_init_f 
bl  board_init_f  /*调用board_init_f,硬件准备 设置初始化环境*/
调用initcall_run_list(init_sequence_f),init_sequence_f是个数组,里面是将要进行初始化的函数列表

3.重定位

b relocate_code

4.重新设置异常向量表 

 bl      c_runtime_cpu_setup             /* still call old routine */
5.清理BSS段

6.board_init_r
b board_init_r   /*调用board_init_r,最终完成环境初始化*/

~~~~~~~~~~

crt0_64.S

59 ENTRY(_main)
 60 
 61 /*
 62  * Set up initial C runtime environment and call board_init_f(0).
 63  */
 64         ldr     x0, =(CONFIG_SYS_INIT_SP_ADDR)
 65         sub     x0, x0, #GD_SIZE        /* allocate one GD above SP */   440
 66         bic     sp, x0, #0xf    /* 16-byte alignment for ABI compliance */
 67         mov     x18, sp                 /* GD is above SP */
 68         mov     x0, #0
 69         bl      board_init_f

71 /*
 72  * Set up intermediate environment (new sp and gd) and call
 73  * relocate_code(addr_moni). Trick here is that we'll return
 74  * 'here' but relocated.
 75  */
 76         ldr     x0, [x18, #GD_START_ADDR_SP]    /* x0 <- gd->start_addr_sp */ 152
 77         bic     sp, x0, #0xf    /* 16-byte alignment for ABI compliance */
 78         ldr     x18, [x18, #GD_BD]              /* x18 <- gd->bd */   0
 79         sub     x18, x18, #GD_SIZE              /* new GD is below bd */

 81 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
 82         adr     lr, relocation_return
 83         ldr     x9, [x18, #GD_RELOC_OFF]        /* x9 <- gd->reloc_off */
 84         add     lr, lr, x9      /* new return address after relocation */
 85         ldr     x0, [x18, #GD_RELOCADDR]        /* x0 <- gd->relocaddr */
 86         b       relocate_code
 87 #endif
 88 
 89 relocation_return:
 90 
 91 /*
 92  * Set up final (full) environment
 93  */
 94         bl      c_runtime_cpu_setup             /* still call old routine */
 95 
 96 /*
 97  * Clear BSS section
 98  */
 99         ldr     x0, =__bss_start                /* this is auto-relocated! */
100         ldr     x1, =__bss_end                  /* this is auto-relocated! */
101         mov     x2, #0
102 clear_loop:
103         str     x2, [x0]
104         add     x0, x0, #8
105         cmp     x0, x1
106         b.lo    clear_loop
107 
108         /* call board_init_r(gd_t *id, ulong dest_addr) */
109         mov     x0, x18                         /* gd_t */
110         ldr     x1, [x18, #GD_RELOCADDR]        /* dest_addr */

111         b       board_init_r                    /* PC relative jump */
112 
113         /* NOTREACHED - board_init_r() does not return */
114 
115 ENDPROC(_main)
 

-------crt0_64.S 說明----------------------------------------------------------------

64         ldr     x0, =(CONFIG_SYS_INIT_SP_ADDR)說明:

CONFIG_SYS_INIT_SP_ADDR  =0x08000000

在内部RAM 的末尾预留一些空间给global_data 结构体

rk_default_config.h:#define CONFIG_SYS_INIT_SP_ADDR        CONFIG_RAM_PHY_END

rk33plat.h:#define CONFIG_RAM_PHY_END        (CONFIG_RAM_PHY_START + CONFIG_RAM_PHY_SIZE)

rk33plat.h:#define CONFIG_RAM_PHY_START        0x00000000

rk33plat.h:#define CONFIG_RAM_PHY_SIZE        SZ_128M

include/linux/sizes.h:#define SZ_128M        0x08000000

-------------------------

65 sub     x0, x0, #GD_SIZE        /* allocate one GD above SP */

include/generated/generic-asm-offsets.h:#define GD_SIZE 440 /* sizeof(struct global_data)    // */

 76         ldr     x0, [x18, #GD_START_ADDR_SP]    /* x0 <- gd->start_addr_sp */

include/generated/generic-asm-offsets.h:#define GD_START_ADDR_SP 152 /* offsetof(struct global_data, start_addr_sp)    // */

include/generated/generic-asm-offsets.h:#define GD_BD 0 /* offsetof(struct global_data, bd)    // */

===================================================

common/board_f.c

CSDN board_init_f() 解析聯結

void board_init_f(ulong boot_flags)

{     if (initcall_run_list(init_sequence_f))
                hang();
}

static init_fnc_t init_sequence_f[] = {
#ifdef CONFIG_SANDBOX
        setup_ram_buf,
#endif
        setup_mon_len,
        setup_fdt,
#ifdef CONFIG_TRACE
        trace_early_init,
#endif
.........

..........

        display_new_sp,
#ifdef CONFIG_SYS_EXTBDINFO
        setup_board_extra,
#endif
        INIT_FUNC_WATCHDOG_RESET
        reloc_fdt,
        setup_reloc,
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)
        jump_to_copy,
#endif
        NULL,
};

common/board_r.c

void board_init_r(gd_t *new_gd, ulong dest_addr)
{
      if (initcall_run_list(init_sequence_r))
                hang();

    -----------------

init_fnc_t init_sequence_r[] = {
        initr_trace,
        initr_reloc,

#ifdef CONFIG_BOARD_LATE_INIT
        board_late_init, board/rockchip/rk33xx/rk33xx.c:int board_late_init(void)
#endif    

        run_main_loop,
};
 

board/rockchip/rk33xx/rk33xx.c:int board_late_init(void)

int board_late_init(void) 
{
board_fbt_preboot();   board/rockchip/common/rkboot/fastboot.c:

}

void board_fbt_preboot(void) 这里检测了按键并且执行了启动流程
{

rk3288正常启动流程_groundhappy的博客-CSDN博客

RK3399 uboot启动_kernel_my的博客-程序员宅基地 - 程序员宅基地

fbt_fastboot_init
board_fbt_get_reboot_type    //读取reboot flag
board_fbt_key_pressed //再次检查key有没有按下来决定进入哪种模式。
board_fbt_low_power_check    //电量检查,过低就充电,如果失败就直接关机.
fdtdec_get_int    //读取u-boot是否显示logo值
}

static int run_main_loop(void)
{
#ifdef CONFIG_SANDBOX
        sandbox_main_loop_init();
#endif
        /* main_loop() can return to retry autoboot, if so just run it again */
        for (;;)
                main_loop();

        return 0;
}

~~~~~~~~~~~~~~

 common/main.c

void main_loop(void)
{
run_preboot_environment_command();
 s = bootdelay_process();

autoboot_command(s);  //common/autoboot.c: 只有一条指令。那就是bootrk ???


 

        cli_loop();
}

common/autoboot.c
const char *bootdelay_process(void)
              s = getenv("bootcmd");

void autoboot_command(const char *s)    s=bootcmd=bootrk

{    run_command_list(const char *cmd, int len, int flag)    }  common/cli.c

如果倒计时自然结束那么就执行函数
run_command_list,此函数会执行参数 s 指定的一系列命令,也就是环境变量 bootcmd 的命令,
bootcmd 里面保存着默认的启动命令,因此 linux 内核启动!

------------------------------------------------------------------------------------------------------------------

common/autoboot.c

/* bootrk [ <addr> | <partition> ] */
int do_bootrk(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
  

U_BOOT_CMD(
                bootrk, 2,      1,      do_bootrk,
                "boot rockchip android bootimg",
#ifdef DEBUG
                "[ <addr> | <partition> ]\n    - boot application image\n"
                "\t'addr' should be the address of the boot image which is\n"
                "\tzImage+ramdisk.img if in memory.  'partition' is the name\n"
                "\tof the partition to boot from.  The default is to boot\n"
                "\tfrom the 'boot' partition.\n"
#else
                "\n"
#endif
                );
 

[Boot]硬件上电到Bootloader - 知乎

rk3288正常启动流程_groundhappy的博客-CSDN博客


       






 


 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值