工程分析 - u-boot

一 环境搭建

  1. 编译环境
  2. 编译方法

二 启动流程

1. u-boot 启动到 main_loop

  1. u-boot 启动流程

  2. 启动流程特别说明:crt0.S:_main
    参考1 + 参考2

  3. 启动流程特别说明:init_sequence_f
    参考1 + 参考2

  4. 启动流程特别说明:gd 的意义、用途

  5. 启动流程特别说明:init_sequence_r

  6. 启动流程特别说明:u-boot relocate 技术

2. u-boot-spl 启动到 u-boot

  1. 为什么需要SPL?
    SPL 技术在产品设计中是可选的,当sram的存储不足以容纳u-boot的时候推荐使用。
    思考问题:sram 较小的情况下,为什么不直接使用dram呢:bootrom直接把 u-boot加载到dram不就可以了吗?这样多好,中间环节spl就省略了。
    笔者看来,问题可能出在bootrom 不支持dram的最优初始化参数,甚至不清楚如何初始化dram。这部分工作只能交给u-boot-spl、u-boot来做。

  2. SPL 和非SPL U-boot 在执行流程上的差异

  3. 一个支持SPL技术的平台:DM814*
    3.1 dm184x 应用了SPL技术(TI 把二进制spl文件命名为MLO)

    export ARCH=arm
    export CROSS_COMPILE=arm-linux-gnueabi-
    make  ti814x_evm_defconfig
    make  "CFLAGS+= -g OPTFLAGS= -Os" -j4| tee log
    

    3.2 MLO 和 u-boot.img 在二进制大小的差异

    ospin@ospin-VirtualBox:~/code/ti814x_boot$ ls -l MLO 
    -rw-rw-r-- 1 ospin ospin 49436 25 16:06 MLO
    ospin@ospin-VirtualBox:~/code/ti814x_boot$ ls -l  u-boot.img 
    -rw-rw-r-- 1 ospin ospin 390840 25 16:06 u-boot.img
    
  4. u-boot-spl 和 u-boot 在职能和源码组成上的差异?
    4.1 MLO 和 u-boot 在二进制文件的差异

3. u-boot 加载内核以及ramdisk

  1. 内核:一般内核镜像的格式分类

  2. 适配:u-boot支持的内核格式

  3. ramdisk:ramdisk制作方法

  4. u-boot 如何引导内核
    4.1 引导Legacy Image

    bootm, bootz, booti
    这几个都是从内存中的某个地址获得kernel image。
    bootz是启动zImage,而bootm和booti是启动uImage,其中booti专门用来启动ARM64的kernel image。
    它们的基本语法是:bootX <kernel address> <rootdisk address> <fdt(dts file) address>,这里的address都是指内存的物理地址,需要提前把image和file加载到内存中,其中根文件系统的地址可以省略(包含在kernel image中),用-来代替。
    
    在常规的启动引导过程中,uboot的各种启动方式实际上最后都是调用bootz的,但之前会设置很多环境变量作为启动的参数。在调试过程中,我们也同样可以手动设置好参数,直接用bootX系列来启动系统。
    

    4.2 引导FIT Image

    bootm 
    

3. U-boot SPL 功能分析

  1. SPL 和 非SPL U-boot 在二进制文件上的差异

    3.4 SPL(对于TI:MLO),是可以编译dtb的,命名为:u-boot-spl.dtb,它怎么得到的呢?

    /tools/fdtgrep -b u-boot,dm-pre-reloc -b u-boot,dm-spl -RT arch/arm/dts/origin-dtb-name.dtb -n /chosen -n /config -O dtb | ./tools/fdtgrep -r -O dtb - -o dts/dt-spl.dtb
    

    可见u-boot-spl.dtb 是从origin-dtb-name.dtb 通过fdtgrep 过滤得到:
    spl设备树只取带有{u-boot,dm-pre-reloc/u-boot,dm-spl 标记|| /chosen//config Node} 的节点,并且最终spl-dtb文件中的u-boot,dm-pre-reloc/u-boot,dm-spl 属性被去掉了。

    3.5

三 功能分析

1. 源码特点:平台抽象

u-boot 依赖Kconfig 完成特定代码的编译工作,依赖链接脚本完成代码链接工作。

链接好的代码又存在一层抽象,即:arm common level 代码形成模板调用接口,接口具体由cpu/board level代码实现。

  1. Arm-Soc 平台代码:mach-xx

    ospin@ospin-VirtualBox:~/code/u-boot-2018.11$ ls arch/arm/
    config.mk  Kconfig        mach-at91     mach-exynos      mach-k3        mach-mvebu    mach-qemu      mach-snapdragon  mach-stm32mp   mach-versal     Makefile
    cpu        Kconfig.debug  mach-bcm283x  mach-highbank    mach-keystone  mach-omap2    mach-rmobile   mach-socfpga     mach-sunxi     mach-versatile  thumb1
    dts        lib            mach-bcmstb   mach-imx         mach-kirkwood  mach-orion5x  mach-rockchip  mach-sti         mach-tegra     mach-zynq
    include    mach-aspeed    mach-davinci  mach-integrator  mach-meson     mach-owl      mach-s5pc1xx   mach-stm32       mach-uniphier  mach-zynqmp-r5
    
  2. Cpu-Core 平台代码
    arm产品系列 + 特别说明 cpu core 架构源码列表如下:

    ospin@ospin-VirtualBox:~/code/u-boot-2018.11$ ls arch/arm/cpu/
    arm11  arm1136  arm1176  arm720t  arm920t  arm926ejs  arm946es  armv7  armv7m  armv8  built-in.o  Makefile  pxa  sa1100  u-boot.lds  u-boot-spl.lds
    
    #禁止FIQ, IRQ中断,重设异常向量表,进入svc Mode
    /home/ospin/code/u-boot-2018.11/arch/arm/cpu/armv7/start.S
    
  3. Board 平台代码
    lowlevel_init 存储在板级代码里

    /*_start 阶段板级平台代码*/
    /home/ospin/code/u-boot-2018.11/board/armltd/vexpress/vexpress_common.c
    
    CONFIG_SYS_INIT_SP_ADDR /*_start 阶段gd 的地址*/
    
  4. Arm-common代码
    4.1 Arm 中断向量表模板

    /home/ospin/code/u-boot-2018.11/arch/arm/lib/vectors.S
    #中断向量_start 存储在平台代码里 /home/ospin/code/u-boot-2018.11/arch/arm/cpu/armv7/start.S
    

    4.2 Arm 初始化模板

    /home/ospin/code/u-boot-2018.11/arch/arm/lib/crt0.S
    /*
    #arm 初始化模板
    sram alloc
    board_init_f
    relocate_code
    relocate_vectors
    init relocated bss
    board_init_r
    */
    
    
  5. All-arch common 模板

    /*初始化通用模板*/
    /home/ospin/code/u-boot-2018.11/common/board_f.c
    

2. DM 技术

  1. 参考博客
    DM 技术是对driver 的上层封装/抽象。 比如serial-uclass 或者gpio-uclass, 用户可以选择支持他们,也可以不支持。
  2. 优点:
    通过DM 技术, 用户可以把全部的平台设备和驱动程序bind 到 uclass 结构中,进行统一管理。

3. device_probe

  1. device_probe 设计的初衷:
    笔者认为主要是完成硬件层面的配置。当然也可以用来完成driver 数据结构的组织工作。
  2. device_probe 什么时候调用?
    上层通过uclass层准备获取设备的时候,可能调用下面两个函数。最终调用了uclass_get_device_tail 并在这个函数里完成device_probe.
    意义:用户在准备使用设备时才probe!
    int uclass_get_device_by_name(enum uclass_id id, const char *name,
    			      struct udevice **devp)
    int uclass_get_device(enum uclass_id id, int index, struct udevice **devp)
    

4. 板级配置:.config 和 config.h

4.1 .config

  1. .config 借助Kconfig 语法生成,参考link
  2. .config 的意义
    .config 决定了哪些源码文件被编译,以及源码文件中哪些预处理代码并编译。就好像从u-boot 的整体集合中选中了一个子集,支持自己的板子。
  3. .config 文件的输出
    3.1 编译过程中,.config 文件中的key=val pair 被转换为C风格的头文件,然后存储在 include/generated/autoconf.h
    3.2 u-boot.cfg 文件记录了 .config 和 conifg.h 的最终结果!!!

4.2 config.h

  1. conifg.h 文件用于板子所用到的参数,比如地址信息等,例如:
    ./include/config.h includes ./include/configs/vexpress_ca9x4.h

2. env 加载和存储

  1. env 存储整体设计

  2. 参考大图

3. serial 设备驱动、接口

参见大图

5. u-boot-spl 引导 u-boot

5. U-boot 二进制输出命名规则

  1. u-boot.img vs u-boot.bin
  2. 其它

6. U-boot设备树功能分析

  1. U-boot 源码和设备树 编译过程
  2. U-boot 设备树的设计思想
  3. U-boot 设备树格式与解析

7. U-boot 增加一个命令

https://blog.csdn.net/zd845101500/article/details/104017849

8. U-boot 启动内核 bootcmd

  1. booti/bootz/bootm
  2. bootcmd

9. 内存布局和检测

9.1 内存分类

SRAM 是 SOC 片内存储, 容量非常小。 在 init_sequence_f 阶段用于存储 struct global_data 结构体

SDRAM 是SOC 片外存储, 容量和体积大。 在init_sequence_f 阶段调用 dram_init 实现检测。
dram_init 函数由board level 代码实现,通过读写内存完成存储单元功能检测。

9.2 内存布局

gd->ram_base = CONFIG_SYS_SDRAM_BASE; //内存基地址
gd->ram_top = gd->ram_base + get_effective_memsize(); //内存顶部地址
... reserve memorys...
gd->relocaddr = gd->ram_top - reserveed mem - ; 
gd->relocaddr -= gd->mon_len; //uboot 重放地址

gd->start_addr_sp = gd->relocaddr;
gd->start_addr_sp -=  TOTAL_MALLOC_LEN;//malloc 内存分配

gd->start_addr_sp -= sizeof(bd_t);
gd->bd = (bd_t *)map_sysmem(gd->start_addr_sp, sizeof(bd_t)); //board info 内存分配

gd->start_addr_sp -= sizeof(gd_t); 
gd->new_gd = (gd_t *)map_sysmem(gd->start_addr_sp, sizeof(gd_t)); //新的gd_t 在sdram的分配

gd->start_addr_sp -= gd->fdt_size;// fdt 内存分配
gd->new_fdt = map_sysmem(gd->start_addr_sp, gd->fdt_size); 

debug("New Stack Pointer is: %08lx\n", gd->start_addr_sp); //最后得到栈顶

11. struct global_data

参考博客

四 工程设计

1.

五 工具的使用

  1. qemu 也能支持gdb调试
    1.1 qemu 启动gdbserver
    1.2 arm-linux-gdb 安装方法
    1.3 u-boot 符号表支持gdb

    #qemu
    $qemu-system-arm -M vexpress-a9 -s -S -kernel u-boot
    
    #gdb
    $arm-linux-gnueabi-gdb
    $(gdb) target remote localhost:1234
    $(gdb) bt
    
  2. qemu 学习资料

  3. vexpress a9 学习资料
    3.1 qemu 对 vexpress的介绍:mothter board + daughter card
    3.2 Versatile Express 的一篇wiki
    3.3 qemu退出方法

  4. 反汇编dtb
    https://blog.csdn.net/xiezhi123456/article/details/82416165

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值