浅析嵌入式系统 uboot
uboot
1. 相关基础介绍
1.1 计算机系统的主要部件
-
计算机系统就是以CPU为核心来运行的系统。
典型的计算机系统有:
① PC机(台式机+笔记本)、
② 嵌入式设备(手机、平板电脑、游戏机)
③ 单片机(家用电器像电饭锅、空调) -
计算机系统的组成部件非常多,不同的计算机系统组成部件也不同。
但是所有的计算机系统运行时需要的主要核心部件都是3个东西:
CPU + 外部存储器(Flash/硬盘) + 内部存储器(DDR SDRAM/SDRAM/SRAM)
1.2 PC机的启动过程
-
部署:典型的PC机的BIOS程序部署在PC机主板上(随主板出厂时已经预制了),操作系统部署在硬盘上,内存在掉电时无作用,CPU在掉电时不工作。
-
启动过程:PC上电后先执行BIOS程序(实际上PC的BIOS就是NorFlash),BIOS程序负责初始化DDR内存,负责初始化硬盘,然后从硬盘上将OS镜像读取到DDR中,然后跳转到DDR中去执行OS直到启动(OS启动后BIOS就无用了)
1.3 典型嵌入式linux系统启动过程
-
典型嵌入式系统的部署:uboot程序部署在Flash(能作为启动设备的Flash)上、OS部署在FLash(嵌入式系统中用Flash代替了硬盘)上、内存在掉电时无作用,CPU在掉电时不工作。
-
启动过程:嵌入式系统上电后先执行uboot、然后uboot负责初始化DDR,初始化Flash,然后将OS从Flash中读取到DDR中,然后启动OS(OS启动后uboot就无用了)
-
总结:嵌入式系统和PC机的启动过程几乎没有两样,只是BIOS成了uboot,硬盘成了Flash。
实际上,Linux系统的启动分为2个阶段:
- 第一个阶段是BootLoader到OS启动;
- 第二个阶段是OS启动后到rootfs加载到命令行执行;
1.4 android系统启动过程
启动的内核基本一样
Android的内核也是Linux,因此,和传统的LInux启动几乎一样。
唯一的差别在于:在内核启动后加载根文件系统后不同了。
android的启动和linux的差别在第二阶段。
1.5 总结
uboot 到底是干嘛的?
- uboot主要作用是用来启动操作系统内核。
- uboot还要负责部署整个计算机系统。
- uboot中还有操作Flash等板子上硬盘的驱动。
- uboot还得提供一个命令行界面供人来操作。
2. uboot 的来源
uboot经过多年发展,已经成为事实上的业内bootloader标准。现在大部分的嵌入式设备都会默认使用uboot来做为bootloader。
2.1 uboot 从哪里来的
- uboot是SourceForge上的开源项目
- uboot项目的作者:一个德国人最早发起的项目
- uboot就是由一个人发起,然后由整个网络上所有感兴趣的人共同维护发展而来的一个bootloader。
2.2 uboot 的发展历程
- 自己使用的小开源项目。
- 被更多人认可使用。
- 被SoC厂商默认支持。
2.3 uboot 的版本号问题
- 早期的BootLoader的版本号类似于这样:uboot 1.3.4。后来版本号便成了类似于uboot-2010.06。
- uboot的核心部分几乎没怎么变化,越新的版本支持的开发板越多而已,对于一个老版本的芯片来说,新旧版本的uboot并没有差异。
注意,uboot不是越新越好。庞大的没必要的功能只会拖累内核的启动。
2.4 uboot 的可移植性的正确理解
- uboot就是universal bootloader(通用的启动代码),通用的意思就是在各种地方都可以用。所以说uboot具有可移植性。
- uboot具有可移植性并不是说uboot在哪个开发板都可以随便用,而是说uboot具有在源代码级别的移植能力,可以针对多个开发板进行移植,移植后就可以在这个开发板上使用了。
3. uboot 必须解决哪些问题
具体参考 浅析嵌入式系统之bootloader 中Bootloader必须解决哪些问题
4. uboot 的工作方式
4.1 从裸机程序镜像 uboot.bin 说起
-
uboot的本质就是一个裸机程序,和我们裸机全集中写的那些裸机程序xx.bin并没有本质区别。如果非说要有区别,那就是:我们写的大部分小于16KB,而uboot大于16KB(一般uboot在180k-400k之间)
-
uboot本身是一个开源项目,由若干个.c文件和.h文件组成,配置编译之后会生成一个uboot.bin,这就是uboot这个裸机程序的镜像文件。然后这个镜像文件被合理的烧录到启动介质中拿给SoC去启动。也就是说uboot在没有运行时表现为uboot.bin,一般躺在启动介质中。
-
uboot运行时会被加载到内存中然后一条指令一条指令的拿给CPU去运行。
4.2 uboot 的命令式shell界面
-
普通的裸机程序运行起来就直接执行了,执行时效果和代码有关。
-
有些程序需要和人进行交互,于是乎程序中就实现了一个shell(shell就是提供人机交互的一个界面,回想ARM裸机全集第十六部分),uboot就实现了一个shell。
注意:shell并不是操作系统,和操作系统一点关系都没有。linux中打开一个终端后就得到了一个shell,可以输入命令回车执行。uboot中的shell工作方式和linux中的终端shell非常像(其实几乎是一样的,只是命令集不一样。譬如linux中可以ls,uboot中ls就不识别)
4.3 掌握uboot使用的2个关键点:命令和环境变量
- uboot启动后大部分时间和工作都是在shell下完成的(譬如uboot要部署系统要在shell下输命令、要设置环境变量也得在命令行地下,要启动内核也要在命令行底下敲命令)
- 命令就是uboot的shell中可以识别的各种命令。uboot中有几十个命令,其中有一些常用另一些不常用(我们还可以自己给uboot添加命令),后面抽点时间发布 uboot 的常用命令。
- uboot的环境变量和操作系统的环境变量工作原理和方式几乎完全相同。uboot在设计时借助了操作系统的设计理念(命令行工作方式借鉴了linux终端命令行,环境变量借鉴了操作系统的环境变量,uboot的驱动管理几乎完全照抄了linux的驱动框架)。
- 环境变量可以被认为是系统的全局变量,环境变量名都是系统内置的(认识就认识,不认识就不认识,这部分是系统自带的默认的环境变量,譬如PATH;但是也有一部分环境变量是自己添加的,自己添加的系统就不认识但是我们自己认识)。系统或者我们自己的程序在运行时可以通过读取环境变量来指导程序的运行。这样设计的好处就是灵活,譬如我们要让一个程序更改运行方法,不用去重新修改程序代码再重新编译运行,而只要修改相应的环境变量就可以了。
- 环境变量就是运行时的配置属性。
4.4 uboot 中对Flash和DDR的管理
4.4.1 uboot阶段Flash的分区
-
所谓分区,就是说对Flash进行分块管理。
-
PC机等产品中,因为大家都是在操作系统下使用硬盘的,整个硬盘由操作系统统一管理,操作系统会使用文件系统帮我们管理硬盘空间。(管理保证了文件之间不会互相堆叠),于是乎使用者不用自己太过在意分区问题。
-
在uboot中是没有操作系统的,因此我们对Flash(相当于硬盘)的管理必须事先使用分区界定(实际上在uboot中和kernel中都有个分区表,分区表就是我们在做系统移植时对Flash的整体管理分配方法)。有了这个界定后,我们在部署系统时按照分区界定方法来部署,uboot和kernel的软件中也是按照这个分区界定来工作,就不会错。
-
分区方法不是一定的,不是固定的,是可以变动的。但是在一个移植中必须事先设计好定死,一般在设计系统移植时就会定好,定的标准是:
① uboot:uboot必须从Flash起始地址开始存放(也许是扇区0,也许是扇区1,也许是其他,取决于SoC的启动设计),uboot分区的大小必须保证uboot肯定能放下,一般设计为512KB或者1MB(因为一般uboot肯定不足512KB,给再大其实也可以工作,但是浪费);
② 环境变量:环境变量分区一般紧贴着uboot来存放,大小为32KB或者更多一点。
③ kernel:kernel可以紧贴环境变量存放,大小一般为3MB或5MB或其他。
④ rootfs:······
剩下的就是自由分区,一般kernel启动后将自由分区挂载到rootfs下使用
总结:一般规律如下:
(1)各分区彼此相连,前面一个分区的结尾就是后一个分区的开头。
(2)整个flash充分利用,从开头到结尾。
(3)uboot必须在Flash开头,其他分区相对位置是可变的。
(4)各分区的大小由系统移植工程师自己来定,一般定为合适大小(不能太小,太小了容易溢出;不能太大,太大了浪费空间)
(5)分区在系统移植前确定好,在uboot中和kernel中使用同一个分区表。将来在系统部署时和系统代码中的分区方法也必须一样。
4.4.2 uboot 阶段DDR的分区
-
DDR的分区和Flash的分区不同,主要是因为Flash是掉电存在的,而DDR是掉电消失,因此可以说DDR是每次系统运行时才开始部署使用的。
-
内存的分区主要是在linux内核启动起来之前,linux内核启动后内核的内存管理模块会接管整个内存空间,那时候就不用我们来管了。
-
注意内存分区关键就在于内存中哪一块用来干什么必须分配好,以避免各个不同功能使用了同一块内存造成的互相踩踏。譬如说我们tftp 0x23E00000 zImage去下载zImage到内存的0x23E00000处就会出错,因为这个内存处实际是uboot的镜像所在。这样下载会导致下载的zImage把内存中的uboot给冲掉。