搞嵌入式的你,为啥要懂uboot?
内容提要
本文介绍了uboot的作用、启动过程、来源和发展历程,版本号、可移植性、功能,常用命令和环境变量,以及对Flash和DDR的管理方法。
延伸解读
uboot与BIOS的类比:理解嵌入式启动的关键
文章将嵌入式系统的启动过程与PC机类比:PC上电先执行BIOS,再由BIOS初始化硬件并引导操作系统;嵌入式系统则用uboot替代BIOS,用Flash替代硬盘。这一类比有助于理解uboot的核心角色——它同样是上电后第一个运行的程序,负责初始化DDR和存储设备,并将操作系统内核从存储介质加载到内存中执行。理解这个类比,就能明白为什么uboot是嵌入式开发的基础环节。
uboot的生命周期:一次性引导程序
uboot本质上是一个裸机程序,其生命周期从开机自动启动开始,到启动内核后结束。一旦执行启动内核的命令,uboot自身就不再运行,无法返回。这与PC的BIOS类似,操作系统启动后BIOS便不再起作用。因此,uboot的唯一出口就是启动内核,其他任务(如烧录、调试)执行后仍可回到命令行,但启动内核的命令一旦执行就不可逆。理解这一点有助于合理规划uboot的使用场景。
环境变量的双份存储与持久化
uboot的环境变量在Flash和DDR中各存一份。开机时,uboot从Flash读取全部环境变量到DDR作为初始值,运行期间使用DDR中的副本。若用set命令修改环境变量,只影响当前运行;只有执行saveenv命令,才会将DDR中的环境变量整体覆盖保存到Flash。下次开机时,又会从Flash重新读取。因此,彻底修改环境变量需要两步:先set,再save。若只想临时测试,可以只set不save,重启后恢复原值。
Flash与DDR的分区管理:避免冲突与浪费
uboot阶段需要对Flash和DDR进行分区管理。Flash分区是静态的,uboot必须位于起始地址,环境变量、内核、根文件系统等依次存放,各分区大小需在移植前确定,避免溢出或浪费。DDR分区则是动态的,每次系统运行时才部署,关键是要为不同用途分配好内存区域,防止相互覆盖。例如,若将内核下载到uboot镜像所在的内存地址,就会破坏uboot。因此,合理的内存规划是系统稳定运行的前提。
Q&A
uboot的主要作用是什么?
uboot的主要作用是启动操作系统内核,同时负责部署整个计算机系统,并提供命令行界面供用户操作。
uboot的启动过程是怎样的?
嵌入式系统上电后首先执行uboot,uboot负责初始化DDR和Flash,然后将操作系统从Flash读取到DDR中,最后启动操作系统。操作系统启动后uboot就不再运行。
uboot的版本号是如何演变的?
早期版本号类似uboot1.3.4,后来变为类似uboot-2010.06。核心部分变化不大,新版本主要增加了对更多开发板的支持。
uboot的可移植性是什么意思?
uboot具有可移植性是指它可以在源代码级别针对多个开发板进行移植,移植后即可在该开发板上使用,而不是直接在任何开发板上运行。
uboot中常用的命令有哪些?
常用命令包括printenv/print(打印环境变量)、setenv/set(设置环境变量)、saveenv/save(保存环境变量)、ping(网络测试)、tftp(下载文件)、movi(操作SD卡/iNand)、nand(操作NandFlash)、mm/mw/md(内存操作)、bootm/go(启动内核)等。
uboot的环境变量是如何存储和使用的?
环境变量有两份,一份存储在Flash中,另一份在DDR中。uboot启动时从Flash读取全部环境变量到DDR作为初始值,使用过程中操作DDR中的副本,通过saveenv命令将DDR中的环境变量保存回Flash。
uboot如何管理Flash和DDR?
uboot对Flash的管理通过分区实现,分区在系统移植前确定,uboot必须位于Flash起始地址,其他分区如环境变量、kernel、rootfs等依次存放。对DDR的管理主要是分配不同内存区域给不同功能,避免冲突。