Nov 17, 2023
本文阅读量次
一、uboot基础了解 # 1. U-boot是什么 # U-Boot,全称 Universal Boot Loader,是遵循GPL条款的从FADSROM、8xxROM、PPCBOOT逐步发展演化而来的 开放源码项目。
U-boot,是一个主要用于嵌入式系统的引导加载程序,可以支持多种不同的计算机系统结构,其主要作用为:==引导系统的启动!==目前,U-Boot不仅支持Linux系统的引导,还支持NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS, android等多种嵌入式操作系统。
2. U-boot主要特性及功能 # 开放:开放的源代码 多平台:支持多种嵌入式操作系统,如Linux、NetBSD、android等 生态:有丰富的设备驱动源码,如以太网、SDRAM、LCD等,同时也具有丰富的开发文档。 3. U-boot下载地址 # Uboot开发源码:
https://source.denx.de/u-boot/u-boot
https://ftp.denx.de/pub/u-boot/
其他厂商定制的uboot源码:
野火 4. U-boot目录结构 # 目录 含义 arch 各个厂商的硬件信息,目录下包括支持的处理器类型 arch/arm/cpu/xxx **每一个子文件夹,包含一种cpu系列。**每个子文件夹下包含cpu.c(CPU初始化),interrupts.c(设置中断和异常),start.S(U-boot的启动文件,早期的初始化)。 board 与开发板有关,每一个子文件夹代表一个芯片厂家,芯片厂家下,每一个子文件夹,表示一个开发板 common 存放与处理器体系无关的通用代码,可以说为通用核心代码! cmd 存放uboot的相关命令实现部分 drivers 存放外围芯片驱动,网卡,USB等 disk 存放驱动磁盘的分区处理代码 fs 本目录下存放文件系统相关代码,每一个子文件夹表示文件系统 net 网络协议相关代码 doc uboot说明文档 include 各种头文件 post 上电自检代码 api 外部扩展程序的API和示例 tools 编译S-Record或者U-boot镜像的相关工具 5. 如何编译Uboot # make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean make ARCH=arm CORSS_COMPILE=arm-linux-gnueabihf- colibri-imx6ull_defconfig make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8 ARCH=arm:arm架构
...
Nov 17, 2023
本文阅读量次
二、uboot启动流程分析 # 上一篇文章:(一)uboot基础了解 下一篇文章:(三)Uboot驱动模型
同大多数的Bootloader一样,uboot的启动过程也分为BL1、BL2两个阶段,分别对应着SPL和Uboot。
SPL(BL1阶段):负责开发板的基础配置和设备初始化,并且搬运Uboot到内存中,由汇编代码和少量的C语言实现
Uboot(BL2阶段):主要负责初始化外部设备,引导Kernel启动,由纯C语言实现。
我们这篇文章,主要介绍Uboot(BL2阶段)的启动流程,BL1阶段启动流程的详细分析,可以见我的后续文章。想要深入了解的,可以好好研究下!
2.1、程序执行流程图 # 我们先总体来看一下Uboot的执行步骤,这里以EMMC作为启动介质,进行分析!
无论是哪种启动介质,基本流程都相似,我们这就往下看!
==打开图片,结合文档、图片、代码进行理解!==
2.2、u-boot.lds——Uboot的入口函数 # u-boot.lds:是uboot工程的链接脚本文件,对于工程的编译和链接有非常重要的作用,决定了uboot的组装,并且u-boot.lds链接文件中的ENTRY(_start)指定了uboot程序的入口地址。
如果不知道u-boot.lds放到在哪里,可以通过find -name u-boot.lds查找,根目录要进入到uboot的源码的位置哦!
如果查找结果有很多,结合自己的板子信息,确定自己使用的u-boot.lds。
当然,准确的方法是查看Makefile文件,分析出来u-boot.lds所生成的位置。
在u-boot.lds的文件中,可以看到.text段,存放的就是执行的文本段。截取部分代码段如下:
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(_start) SECTIONS { . = 0x00000000; @起始地址 . = ALIGN(4); @四字节对齐 .text : { *(.__image_copy_start) @映像文件复制起始地址 *(.vectors) @异常向量表 arch/arm/cpu/armv7/start.o (.text*) @启动函数 } ...... } ENTRY(_start):程序的入口函数,_start在arch/arm/lib/vectors.S中定义.globl _start
SECTIONS定义了段,包括text文本段、data数据段、bss段等。
__image_copy_start在System.map和u-boot.map中均有定义
arch/arm/cpu/armv7/start.o对应文件arch/arm/cpu/armv7/start.S,该文件中定义了main函数的入口。
Tip:上面只进行大概分析,有汇编经验的朋友,可以详细进行分析!
2.3、board_init_f——板级前置初始化 # 跟随上文的程序执行流程图,我们看board_init_f这个函数。其位于common/board_f.c。
void board_init_f(ulong boot_flags) { gd->flags = boot_flags; gd->have_console = 0; if (initcall_run_list(init_sequence_f)) hang(); } static const init_fnc_t init_sequence_f[] = { setup_mon_len, .
...
Jan 17, 2024
本文阅读量次三、Uboot驱动模型 # 全文耗时一周,精心汇总,希望对大家有所帮助,感觉可以的点赞,关注,不迷路,后续还有更多干货!
看文章前,答应我,静下心来,慢慢品!
3.1、什么是Uboot驱动模型 # 学过Linux的朋友基本都知道Linux的设备驱动模型,Uboot根据Linux的驱动模型架构,也引入了Uboot的驱动模型(driver model :DM)。
**这种驱动模型为驱动的定义和访问接口提供了统一的方法。**提高了驱动之间的兼容性以及访问的标准型,uboot驱动模型和kernel中的设备驱动模型类似。
3.2、为什么要有驱动模型呢 # 无论是Linux还是Uboot,一个新对象的产生必定有其要解决的问题,驱动模型也不例外!
提高代码的可重用性:为了能够使代码在不同硬件平台,不同体系架构下运行,必须要最大限度的提高代码的可重用性。 高内聚,低耦合:分层的思想也是为了达到这一目标,低耦合体现在对外提供统一的抽象访问接口,高内聚将相关度紧密的集中抽象实现。 便于管理:在不断发展过程中,硬件设备越来越多,驱动程序也越来越多,为了更好的管理驱动,也需要一套优秀的驱动架构! 3.3、如何使用uboot的DM模型 # DM模型的使用,可以通过menuconfig来配置。
make menuconfig
①:menuconfig配置全局DM模型 # Device Drivers -> Generic Driver Options -> Enable Driver Model 通过上面的路径来打开Driver Model模型,最终配置在.config文件中,CONFIG_DM=y
②:指定某个驱动的DM模型 # 全局的DM模型打开后,我们对于不通的驱动模块,使能或者失能DM功能。如MMC驱动为例:
Device Drivers -> MMC Host controller Support -> Enable MMC controllers using Driver Model 最终反映在.config文件中的CONFIG_DM_MMC=y
在对应的驱动中,可以看到判断#if !CONFIG_IS_ENABLED(DM_MMC),来判断是否打开DM驱动模型。
在管理驱动的Makefile文件中,也能看到obj-$(CONFIG_$(SPL_)DM_MMC) += mmc-uclass.o,来判断是否将驱动模型加入到编译选项中。
总之,我们要打开DM模型,最后反映在几个配置信息上:
CONFIG_DM=y,全局DM模型打开 CONFIG_DM_XXX=y,某个驱动的DM模型的打开 可以通过Kconifg、Makefile来查看对应宏的编译情况 3.4、DM模型数据结构 # 要想了解DM模型整套驱动框架,我们必须先了解它的一砖一瓦!也就是组成驱动框架的各个数据结构。
① global_data # typedef struct global_data { .
...
Jan 17, 2024
本文阅读量次四、Uboot命令行模式分析 # 前几篇文章,我们也了解了Uboot的启动流程,那么这节就主要讲讲Uboot的命令行模式。
另外,文章末尾还提供eMMC5.1官方标准协议.pdf和eMMC4.51官方标准协议-中文.pdf下载渠道,方便深入了解底层协议。
正文如下:
4.1 如何进入命令行模式 # 我们正常启动流程,默认是直接跳过Uboot命令行模式的,因为Uboot主要的作用是引导Kernel,一般我们不进行uboot开发时,都默认跳过进入命令行模式。
那么,我们要想进入Uboot命令行模式,需要进行哪些配置呢?
打开我们准备好一份Uboot源码,进入menuconfig配置菜单,主要设置下列几个配置信息!
CONFIG_CMDLINE:命令行模式开关 CONFIG_SYS_PROMPT:命令行模式提示符 CONFIG_HUSH_PARSER:使用hush shell 来对命令进行解析 BOOTDELAY:设置启动延时 Tip:meneconfig中查找苦难?实时/符号,输入1或2或3,直接查找指定标识。
打开之后,重新编译,并将Uboot镜像烧录到开发板中,再次启动,我们就能够看到倒计时。
[2022-03-02:13:33:47]U-Boot 2020.10-rc1-00043-ge62a6d17c6-dirty (Feb 08 2022 - 10:14:14 +0800) [2022-03-02:13:33:47] [2022-03-02:13:33:47]Model: xxxxxx [2022-03-02:13:33:47]MMC: mmc1@xxxxxx: 1 [2022-03-02:13:33:47]In: serial [2022-03-02:13:33:47]Out: serial [2022-03-02:13:33:47]Err: serial [2022-03-02:13:33:47]Model: xxxxxx [2022-03-02:13:33:49]Hit any key to stop autoboot: 2 Hit any key to stop autoboot:我们在倒计时结束前,任意键入一个按键,即可进入!
4.2 Uboot基本命令解析 # 进入Uboot命令行模式后,键入help或者?,可以查看所有支持的Uboot命令。
注意:Uboot支持的命令大都远远超过显示的,还有好多没有打开,可以在menuconfig中,打开相应的功能,如mmc相关的,md内存相关的。
常用命令如下:
version #查看uboot版本 reset #重启Uboot printenv #打印uboot环境变量 setenv name value #设置环境变量 md addr #查看内存指令 nm addr #修改内存值 mm addr #自增修改内存值 mmc dev id #选择mmc卡 mmc rescan #扫描卡 echo $name #打印环境变量 更多指令使用,可以见文末整理的文档
...