U-Boot启动流程详解(大白话版)
U-boot的官方网址:ftp://ftp.denx.de/pub/u-boot/
一般我们做开发的不会直接去官网下载u-boot,需要直接去官网下载的时bsp工程师
芯片结构图:
单片机:
如果是单片机,芯片内部有SRAM、ROM
就可以了
跑操作系统的芯片
如果要跑linux操作系统,就需要外接emmc(Nand Flash)
,emmc
就是给Nand Flash
穿的一层外套。
烧录的时候先是烧入的u-boot
(u-boot
只是Bootloader
的一种,u-boot
是当前比较通用的一个启动程序)
Bootloader的分类
u-boot里面的文件夹
随后uImage、rootfs
,这三个只有u-boot
是在开发板上的,其他两个都是在Ubuntu
中需要都烧录到emmc
中去,在emmc中的顺序是u-boot、参数区、kernel(uImage)、rootfs
。
上电后,ROM
里面一般都会有一段固化的代码,这段固化代码是用来判断到底是从emmc
中启动,还是在SD卡上启动
假设从emmc
中启动:
第一步:硬件会直接将u-boot
的前16k的汇编启动代码拷贝到SRAM
中的零地址,由于emmc
不是内存,它无法在里面运行程序
为什么不是直接拷贝到SDRAM
中呢?
因为SDRAM是需要初始化的,所以需要先在SRAM中先初始化,再拷贝到SDRAM中。
为什们只拷贝u-boot
中的前16k?
因为一般SRAM
是64k大小(已经很大了),且无需初始化,由于u-boot
编译过后大概有300k左右,一下子无法全拷贝进去,所以只先拷贝前16k(这16k是用汇编写的启动代码)。
上电硬件直接硬拷贝,先把汇编拷贝进去,随后从SRAM的零地址开始运行,零地址就是u-boot的前16k汇编代码,在执行这16k的汇编代码的过程中会初始化整个CPU、设置时钟频率,关闭看门狗、设置各种硬件参数。
u-boot启动后的工作:
1.初始化时钟\串口;
2.初始化SDRAM
;
3.将u-boot
拷贝到SDRAM
;
4.加载内核;
5.u-boot
传递参数给内核;
具体来说u-boot必须具备的功能如下:
①读写
FLASH
或SD
卡;
②写SDRAM
;
③从SDRAM
中启动内核;
④初始化时钟;
⑤初始化串口甚至网口;
比如:
现有串口,我们要设置一下串口的波特率,一开机同时需要板子上的一个指示灯亮起来,就可在u-boot
中先完成这些,做完之后最重要的一步就是初始化SDRAM
,在运行前16k的汇编代码时,初始化SDRAM
,设置内存控制器就可以了,在执行前16k的u-boo
t汇编代码的时候,会用汇编指令将整个初始化好的u-boot拷贝到SDRAM
中去,在SRAM
中执行完u-boot
中的前16k汇编后,会紧接着在SDRAM中继续执行后续的C代码,此时C代码会做一些其他的初始化操作。这段C代码最重要的作用就是把Linux
内核uImage
从emmc
中拷贝到SDRAM
中去。
比如:
打开屏幕,初始化屏幕,让屏幕亮起来,我们可以观察板子一上电,Linux
还没起来,屏幕上就显示了一个logo,这就是u-boot
把屏幕驱动起来的,u-boot
是一个单片机程序,所以u-boot
的驱动就是单片机的驱动。
**uImage
**就是zImage + 64字节的头
,这64字节的头会告诉它当前是用的什么内核,是Linux
内核还是vxbox
内核以及我们的加载地址在哪,然后u-boot
会去解析这段地址,识别内核的头,随后把这段64字节的头剪掉,再把 zImage
重定位(拷贝)到Linux
内核的加载地址中去,随后从u-boot
执行完后,直接跳转到这个Linux
内核的加载地址中去运行,此时就开始执行Linux
内核的代码,u-boot
就到此执行完毕了。
Linux
内核中也有汇编启动代码,为什么还要BootLoader
呢?
首先Linux
内核包罗万象,不管什么平台都可,平台不一样,芯片不一样,故初始化代码也就不一样,最后启动时,启动地址也不一样,片内的SRAM
在哪也不会固定,有的芯片的SRAM
的零地址还需要映射。
总的一句话就是:不同的芯片它启动时,硬件操作也完全不一样
那如果没有u-boot
,那就要把这样所有对硬件的操作都要放到Linux
内核中去。这样会导致我们的Linux
内核代码会越来越庞大,所以这就是为什么有u-boot的原因了。
因此,在Linux
内核整个启动之前,首先要有一段针对当前芯片,当前板子的一段启动引导程序,这就是我们的BootLoader
,然而BootLoader
中最重要的、最通用的就是u-boot
.
优点:小并且经典,代码也不是很复杂。
补充:内核的启动:
1.执行汇编代码(初始化工作);
2.执行C代码(内核中C起始位置:Start_kernel
)
①加载驱动;
②挂载根文件系统;
③执行
此时:板子就运行起来了.
作者:嵌入式攻城师