【Nanopi T2】 3.uboot 2016 启动流程源码解析

目录

        • s5p4418 uboot sd卡方式启动流程
        • 镜像文件内存布局
        • uboot启动(BL1)
          • start.S
          • lowlevel_init.S
          • _main
          • board_init_f
          • board_init_r
          • main_loop

s5p4418 uboot sd卡方式启动流程

4418上电后会先加载运行片内启动代码(BL0),大致工作是判断CPU的启动方式,初始化启动设备。拷贝uboot前16k(BL1)到内部RAM,对代码做校验,然后开始运行BL1。4418的BL1也是厂商直接提供的,属于闭源代码。4418的BL1大致由2nboot和2nboot配置组成,2nboot的配置可以在友善之臂的uboot源码中找到(tools/nexell/nish/nanop2.txt)。2nboot大致工作是初始化中断向量,关闭看门口,初始化ddr内存,拷贝整个uboot到ddr,然后跳转到ddr中运行uboot的后半部分(BL2)。

镜像文件内存布局

友善支之臂不同版本的2nboot代码量大小不一样,具体见我前两篇博客中的介绍
uboot 2010:https://blog.csdn.net/qq_16054639/article/details/105770048
uboot 2016:https://blog.csdn.net/qq_16054639/article/details/105829051

uboot启动(BL1)

uboot中的CONFIG_SPL是没有启用的,整个uboot的前半部分启动代码是闭源的,所以手里的源码都是从后半部分开始的。
查看源码文件/arch/arm/armv7/s5p4418/u-boot.lds

.text :
 {
  *(.__image_copy_start) //拷贝开始的位置
  *(.vectors)            //存放中断向量表
  CPUDIR/start.o (.text*)//代码开始
  *(.text*)
 }

发现开始代码段为vectors,这个vectors的来源是在配置文件tools/nexell/nish/nanop2.txt中

E59FF018 // 0x000 : MOV PC, ResetV
E59FF018 // 0x004 : MOV PC, UndefV
E59FF018 // 0x008 : MOV PC, SWIV
E59FF018 // 0x00C : MOV PC, PAbortV
E59FF018 // 0x010 : MOV PC, DAbortV
E59FF018 // 0x014 : MOV PC, NotUsed
E59FF018 // 0x018 : MOV PC, IRQV
E59FF018 // 0x01C : MOV PC, FIQV

FFFF0200 // 0x020 : SRAMBASE + Header
FFFF0204 // 0x024 : SRAMBASE + Header
FFFF0208 // 0x028 : SRAMBASE + Header
FFFF020C // 0x02C : SRAMBASE + Header
FFFF0210 // 0x030 : SRAMBASE + Header
FFFF0214 // 0x034 : SRAMBASE + Header
FFFF0218 // 0x038 : SRAMBASE + Header
FFFF021C // 0x03C : SRAMBASE + Header
start.S

之后接着开始代码/arch/arm/armv7/start.S

 .globl reset
 .globl save_boot_params_ret
 reset:
 /* Allow the board to save important registers */
 b save_boot_params
save_boot_params_ret:
 /*
  * 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
 /*
 * 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 */
	 ldr r0, =_start
	 mcr p15, 0, r0, c12, c0, 0 @Set VBAR
#endif
 /* the mask ROM code should have PLL and others stable */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
	 bl cpu_init_cp15
	 bl cpu_init_crit
#endif
 	bl _main

执行流程:

  1. save_boot_params(没做什么)
  2. save_boot_params_ret(禁用中断,设置运行模式)
  3. cpu_init_cp15(初始化cp15寄存器,主要设置cache,mmu,TLBs地址映射表,不深入分析)
  4. cpu_init_crit
  5. ->lowlevel_init(其实也没做什么,祥见下文)
  6. _main(开始后半部分初始化)
lowlevel_init.S

/arch/arm/armv7/lowlevel_init.S
【Nanopi T2】 3.uboot 2016 启动流程源码解析_第1张图片
执行流程:

  1. 初始化C语言栈
  2. 初始化global data全局结构体起始地址
  3. s_init(什么也没做)
_main

/arch/arm/lib/crt0.S

【Nanopi T2】 3.uboot 2016 启动流程源码解析_第2张图片

执行流程:

  1. 设置c语言运行环境(设置sp指针)
  2. board_init_f_mem(初始化内存配置,起始就是向global data写入栈顶地址,malloc起始地址)
  3. board_init_f(这个很重要,初始化了很多功能)
  4. 继续填充global data结构体参数(不深入分析)
  5. coloured_LED_init(初始化LED)
  6. red_led_on(点亮LED)
  7. board_init_r(很重要初始化了非常多东西)
board_init_f

/common/board_f.c

【Nanopi T2】 3.uboot 2016 启动流程源码解析_第3张图片

board_init_f这个函数主要遍历执行了init_sequence_f这个数组中的函数
挑出几个主要关键函数解释:

  1. fdtdec_setup(初始化设备树描述符)
  2. arch_cpu_init(初始化cpu,时钟)
  3. initf_dm(初始化dm驱动框架,扫描设备树,初始化设备节点)
  4. timer_init(初始化时钟线)
  5. env_init(读取环境变量)
  6. show_board_info(打印板子信息)
board_init_r

/common/board_c.c

board_init_r函数跟board_init_f函数类似,也是遍历执行一个数组中的所有函数
【Nanopi T2】 3.uboot 2016 启动流程源码解析_第4张图片
挑出几个主要关键函数解释:

  1. initr_dm(初始化设备树描述符)
  2. board_init(板级初始化)
  3. initr_net(初始化网络驱动)
  4. run_main_loop(进入主循环)
main_loop

【Nanopi T2】 3.uboot 2016 启动流程源码解析_第5张图片
执行流程:

  1. run_preboot_environment_command(执行默认环境变量命令,也就是启动命令preboot)

    preboot定义在include/env_default.h

#ifdef CONFIG_PREBOOT
 "preboot=" CONFIG_PREBOOT   "\0" //CONFIG_PREBOOT这个宏没有定义,所以这里等于什么也没做
#endif
  1. bootdelay_process(等待用户按下按键,按下按键将进入命令行模式,如果没有按下将返回系统启动命令bootcmd)
  2. autoboot_command(如果上一步有命令,执行上一步返回的命令)
  3. cli_loop(进入命令行模式)

至此整个uboot的主要启动流程就梳理结束了

你可能感兴趣的:(uboot)