(一)uboot系统移植之使用篇

(一)uboot系统移植之使用篇

1.为什么要有 uboot

1.1、计算机系统的主要部件

(1)计算机系统就说有CPU来做核心进行运行的系统。典型的计算机系统有:PC机(台式机和笔记本)、嵌入式设备(手机、平板电脑、游戏机)、单片机(家用电器如空调、电饭煲)。
(2)计算机系统的组成部件非常多,不同的计算机系统组成部件也不同。但是所有的计算机系统运行时需要的主要核心部件都是3个东西:CPU+
外部存储器( Flash/硬盘)+内部存储器( DDR SDRAM/ SDRAM/SRAM)

1.2、PC机的启动过程

(1)典型的PC机的部署:BIOS程序部署在PC机主板上(随主板出厂时已经预制了),操作系统部署在硬盘上,内存在掉电时无作用,CPU在掉电时不工作;
(2)启动过程:PC上电后先执行BIOS程序(实际上PC的BIOS航是NorFlash),BIOS程序负责初始化DDR内存,负责初始化硬盘,然后从硬盘上将OS镜像读取到DDR中,然后跳转到DDR中去执行OS直到启动(os启动后BIOS就无用了)。

1.3、典型嵌入式1inux系统启动过程

(1)嵌入式系统的部署和启动都是参考PC机的。只是设备上有一些差别; (2)典型嵌入式系统的部署:uboot程序部署在
Flash(能作为启动设备的 Flash)上、os部署在
Flash(嵌入式系统中用flash代替了硬盘)上、内存在掉电时无作用,CPU在掉电时不工作; (3)启动过程:嵌入式系统上电后先执行
uboot、然后
uboot负责初始化DDR,初化flash,然后将os从Flash中读取到DDR中,然后启动os(os启动后uboot就无用了);

总结:嵌入式系统和PC机的启动过程几乎没有两样,只是BIos成了 uboot,硬盘成了F1ash。

1.4、 android系统启动过程

(1) android系统的启动和 linux系统(前面讲的典型的嵌入式系统启动)几乎一样,意思就是和前面完全一样,只是在内核启动后加载根文件系统后不一样;
(2)可以认为启动分为2个阶段:第一个阶段是 uboot到os启动;第二个阶段是(os启动后到 rootfs加载到命令行执行;现在我们主要研究第一个阶段, android的启动和Linux差别在第二阶段。

1.5、总结:uboot到底是干嘛的

(1) uboot主要作用是用来启动操作系统内核;
(2) uboot还要负责部署整个计算机系统;
(3)ubot中还有操作 Flash等板子上硬盘的驱动;
(4) uboot还得提供一个命令行界面供人来操作。

2.为什么是 uboot

被更多人认可支持,且被SOC厂商默认支持;已经成为事实上的业内boot loader标准。现在大多数嵌入式设备默认使用uboot来做boot
loader。

2.1、uboot版本

早期的类似uboot1.3.4;现在类似uboot-2010.06; uboot核心部分基本没变但是版本越新支持的开发板越多而已。

2.2、uboot的可移植性的正确理解

(1) uboot就是universal bootloader(通用的启动代码),通用的意思就是在各种地方都可以用。所以说
uboot具有可移植性。 (2) uboot具有可移植性并不是说
uboot在哪个开发板都可以随便用,而是说uboot具有在源代码级别的移植能力,可以针对多个开发板进行移植,移植后就可以在这个开发板上使用了。

3. uboot必须解决哪些问题

3.1、自身可开机直接启动

(1)一般的SoC都支持多种启动方式,譬如SD卡启动、NorFlash启动、 Nandflash启动等,uboot要能够开机启动,必须根据具体的SoC的启动设计来设计uboot;
(2) uboot必须进行和硬件相对应的代码级别的更改和移植,才能够保证可以从相应的启动介质启动。 uboot中第一阶段的 start.S文件中具体处理了这一块。

3.2、能够引导操作系统内核启动并给内核传参

(1) uboot的终极目标是启动内核;
(2)linux内核在设计的时候,设计为可以被传参。也就是说我们可以在 uboot中事先给inux内核准备一些启动参数放在内存中特定位置然后传给内核,内核启动后会到这个特定位置去取 uboot传给他的参数,然后在内核中解析这些参数这些参数将被用来指导linux内核的启动过程。

3.3、能提供系统部署功能

(1)uboot必须能够被人借助而完成整个系统(包括 uboot、 kernel、 rootfs等的镜像)在Flash上的烧录下载工作;
(2)裸机教程中刷机就是利用 uboot中的 fastboot功能将各种镜像烧录到 iNand中,然后从 iNand启动。

3.4、能进行soc级和板级硬件管理

(1) uboot中实现了一部分硬件的控制能力( uboot中初始化了一部分硬件),因为 uboot为了完成一些任务必须让这些硬件工作。譬如 uboot要实现刷机必须能驱动 iNand,譬如 uboot要在刷机时LCD上显示进度条就必须能驱动LCD,譬如uboot能够通过串口提供操作界面就必须驱动串口;譬如 uboot要实现网络功能就必须驱动网卡芯片;
(2)SoC级(譬如串口)就是SoC内部外设,板级就是soC外面开发板上面的硬件(譬如网卡、 iNand)。

3.5、uboot的生命周期

uboot本质上是个裸机程序(不是操作系统)一
旦 uboot开始SoC就会单纯运行 uboot(意思就是 uboot运行的时候别的程序是不可能同时运行的),一旦 uboot结束运行则无法再回到 uboot(所以 uboot启动了内核后 uboot自己本身就死了,要想再次看到 uboot界面只能重启系统。重启并不是复活了刚才的uboot而是另一生);
(2)uboot的入口和出口。 uboot的入口就是开机自动启动,uboot的唯一出口就是启动内核。 uboot还可以执行很多别的任务(譬如烧录系统),但是其他任务执行完后都可以回到 uboot的命令行继续执行 uboot命令,而启动内核命令执行就回不来了。

3.6、总结:一切都是为了启动内核

4. uboot的工作方式

4.1、从裸机程序镜像 uboot.bin说起

(1) uboot的本质就是一个裸机程序,和我们裸机全集中写的那些裸机程序xx.bi
n并没有本质区别。如果非说要有区别,那就是:我们写的大部分小于16KB,而uboot大于16KB(一般
uboot在180k-400k之间); 2) uboot本身是一个开源项目,由若干个.c文件和.h文件组成,配置编译之后会生成一个
uboot.bin,这就是 uboot这个裸机程序的镜像文件。然后这个镜像文件被合理的烧录到启动介质中拿给SoC去启动。也就是说
uboot在没有运行时表现为 uboot.bin,一般躺在启动介质中; (3)
uboot运行时会被加载到内存中然后一条指令一条指令的拿给CPU去运行。

4.2、 uboot的命令式shell界面

(1)普通的裸机程序运行起来就直接执行了,执行时效果和代码有关
(2)有些程序需要和人进行交互,于是乎程序中就实现了一个shell(shell就是提供人机交互的一个界面)。

注意:shell并不是操作系统,和操作系统一点关系都没有。linux中打开一个终端后就得到了一个shell,可以输入命令回车执行。 uboot中的shell工作方式和inux中的终端shel1非常像(其实几乎是一样的,只是命令集不一样。)

4.3、掌握 uboot使用的2个关键点:命令和环境变量

(1) uboot启动后大部分时间和工作都是在shell下完成的(譬如
uboot要部署系统要在shell下输命令、要设置环境变量也得在命令行地下,要启动内核也要在命令行底下敲命令); (2)命令就是
uboot的shell中可以识别的各种命令。 uboot中有几十个命令; (3)
uboot的环境变量和操作系统的环境变量工作原理和方式几乎完全相同。υboot在设计时借助了操作系统的设计理念(命令行工作方式借鉴了linux终端命令行,环境变量借鉴了操作系统的环境变量,uboot的驱动管理几乎完全照抄了li
nux的驱动框架);
(4)环境变量可以被认为是系统的全局变量,环境变量名都是系统内置的(认识就认识,不认识就不认识,这部分是系统自带的默认的环境变量,譬如PATH;但是也有一部分环境变量是自己添加的,自己添加的系统就不认识但是我们自己认识)。系统或者我们自己的程序在运行时可以通过读取环境变量来指导程序的运行。这样设计的好处就是灵活,譬如我们要让一个程序更改运行方法:
不用去重新修改程序代码再重新编译运行,而只要修改相应的环境变量就可以;
(5)环境变量就是运行时的配置属性。

5. uboot的常用命令

5.1、类似inux终端的行缓冲命令行

(1)行缓冲:当我们向终端命令行输入命令的时候,这些命令没有立即被系统识别,而是被缓冲到一个缓存区(也就是系统认为我们还没有输入完我们按下回车键(换行)后系统就认为我们输入完了,然后将缓冲区中所有刚才输入的作为命令拿去分析处理;
(2) linux终端设计有3种缓冲机制:无缓冲、行缓冲、全缓冲

5.2、有些命令有简化的别名

譬如 printenv命令可以简化为 print,譬如 steny可以简化为set

5.3、有些命令会带参数(注意格式是固定的)

uboot的每个命令都有事先规定好的各种格式。有些命令就是不带参数的譬如
printenv/pint命令;有些命令带可选的参数(可以带也可以不带当带不带参数的执行结果是不同的);有些命令带必须的参数(譬如
setenv/set命令);

5.4、命令中的特殊符号(譬如单引号)
5.5、有些命令是一个命令族(譬如movi)

(1)命令族意思就是好多个命令开头都是用同一个命令关键字的,但是后面的参数不一样,这些命令的功能和作用也不同。这就叫一个命令族;
(2)同一个命令族中所有的命令都有极大的关联,譬如movi开头的命令族都和moviAnd(EMC、 iNand)操作有关。
在这里插入图片描述

5.6 命令
命令:printenv/ print

(1) print命令不用带参数,作用是打印出系统中所有的环境变量。
(2)环境变量就好像程序的全局变量一样。程序中任何地方都可以根据需要去调用或者更改环境变量(一般都是调用),环境变量和全局变量不同之处在于全局变量的生命周期是在程序的一次运行当中,开始运行时诞生程序结束时死下次运行程序时从头开始:但是环境变量被存储在
Flash的另一块专门区域Flash上有一个环境变量分区),一旦我们在程序中保存了该环境变量,那么下次开机时该环境变量的值将维持上一次更改保存后的值。

命令:(添加/更改)环境变量:setenv / set
命令:保存环境变量: saveenv / save

(1) saveenv/save命令不带参数,直接执行,作用是将内存中的环境变量的值同步保存到flash中环境变量的分区。
注意:环境变量的保存是整体的覆盖保存也就是说内存中所有的环境变量都会整体的将 Flash中环境变量分区中原来的内容整体覆盖。

总结:彻底更改一个环境变量的值,需要2步:
第一步set命令来更改内存中的环境变量;
第二步用save命令将其同步到Flash中环境变量的分区;
有时候我们只是想测试下这个环境变量,不希望影响到下一次开机,那就只set不save,这样set后当前本次运行的uboot已经起效果了,只不过没save下一次开机还是会恢复到原来的状况。

命令:网络测试 ping IP地址

(1)首先要插上网线;
(2)先试图ping通主机 windows。
注意 :Windows中有线网卡的地址设置(设置本地连接)。设置主机 windows的本地连接IPv4地址;
(3)确认开发板里几个网络相关的环境变量的值对不对。最重要的是ipaddr(这个环境变量表示当前开发板的IP地址),这个地址须和主机Windows的IP必须在同一网段。

开发板uboot无法ping通开发主机(PC或虚拟机)问题的完美解决

备注:uboot本身主要目标是启动内核,为了完成启动内核必须要能够部署内核,uboot为了部署内核就需要将内核镜像从主机中下载过来然后烧录到本地
flash中。uboot如何从主机( windows或者虚拟机 ubuntu)下载镜像到开发板上?主流方式是:fastboot和tftp。
fastboot的方式是通过UsB线进行数据传输;tftp的方式是通过有线网络的。典型的方式就是通过网络,
fastboot是近些年才新发展的。
Windows下搭建tftp服务器tftp32或者使用Linux下tftp服务器
注意:(1)检查开发板 uboot的环境变量,serverip必须设置为(开发主机)虚拟机 ubuntu的ip地址。( serverip这个环境变量的意义就是主机tftp服务器的ip地址);
(2)然后在开发板的 uboot下先ping通虚拟机 ubuntu,然后再尝试下载:tftp 0x30000000
zImage-qt(意思是将服务器上名为 zImage-qt的文件下载到开发板内存的0×30000000地址处。)
(3)镜像下载到开发板的DDR中后, uboot就可以用moⅵ指令进行镜像的烧写了。
命令:tftp指令:
在这里插入图片描述下载完成检查大小是否丢包
在这里插入图片描述

命令:nfs启动内核命令
命令:movi

(1)开发板如果用SD卡/EMMC/ iNand等作为Flash,则在 uboot中操作flash的指令为movi(或mmc);
(2)moⅵ指令是一个命令集,有很多子命令,具体用法可以 help movi查看。
(3)movi的指令都是 movi read和 movi write一组的,mov read用来读取 iNand到DDR上,movi write用来将DDR中的内容写入 iNand中。理解这些指令时一定要注意涉及到的2个硬件:iNand和DDR内存。
在这里插入图片描述

NandFlash操作指令nand

理解和操作类似movi指令

内存操作指令:mm、mw、md
mm:修改内存中的某一块;
md:显示内存中的内容;
mw:将内容写到内存中。

(1)DDR中是没有分区的(只听说过对硬盘、Flash进行分区,没听说过对内存进行分区……),但是内存使用时要注意。因为 uboot是一个裸机程序,不像操作系统会由系统整体管理所有内存,系统负责分配和管理,系统会保证内存不会随便越界。然后裸机程序中 uboot并不管理所有内存内存是散的随便用的,所以如果程序员(使用 uboot的人)自己不注意就可能出现自己把自己的数据给覆盖了。

在这里插入图片描述在这里插入图片描述在这里插入图片描述启动内核命令:bootm / go

(1) uboot的终极目标就是启动内核,启动内核在 uboot中表现为一个指令,uboot命令行中调用这个指令就会启动内核(不管成功与否,所以这个指令是一条死路);
(2)差别:bootm启动内核同时给内核传参,而go命令启动内核不传参。bootm才是正宗的启动内核的命令,一般情况下都用这个;go命令本来不是专为启动内核设计的,go命令内部其实就是一个函数指针指向一个内存地址然后直接调用那个函数,go命令的实质就是PC直接跳转到一个内存地址去运行而已。go命令可以用来在 uboot中执行任何的裸机程序(有一种调试裸机程序的方法就是事先启动uboot,然后在 uboot中去下载裸机程序,用go命令去执行裸机程序)。

6. uboot的常用环境变量

自动运行命令设置:bootcmd

(1) uboot开机自动启动时实际就是在内部执行了 bootsma这个环境变量的值所对应的命令集。
(3)bootcmd=‘movi read kernel 30008000; bootm 30008000’意思是:将 iNand的 kernel分区读取到DDR内存的0x30008000地址处,然后使用b ootm启动命令从内存0x30008000处去启动内核。
(4) set bootcmd printenv,然后 saveenv;然后重启则会看到倒计时后打印环境变量

注意:因为bootcmd=‘movi read kernel 30008000; bootm 30008000’中间有分号所以需要单引号括起来

uboot给 kernel传参:bootargs

(1)linux内核启动时可以接收 uboot给他传递的启动参数,这些启动参数是uboot和内核约定好的形式、内容,linux内核在这些启动参数的指导下完成启动过程。这样的设计是为了灵活,为了内核在不重新编译的情況下可以用不同的方式启动;
(2)我们要做的事情就是:在 uboot的环境变量中设置 bootargs,然后 bootm命令启动内核时会自动将 bootargs传给内核;
(3)bootargs=console=ttySAC2,115200 root=/dev/mmcblkOp2 rw init=/linuxrc rootfstype=ext3
意义解释:
console= ttySAC2,115200 控制台使用串口2,波特率115200
root=/dev/mmcblkOp2 rw
根文件系统在sd卡端口0设备( iNand)第2分区,根文件系统是可读可写的
init=/linuxrc linux的进程1(init进程)的路径rootfstype=ext3 根文件系统的类型是ext3
(4)内核传参非常重要。在内核移植的时候,新手经常因为忘记给内核传参者给内核传递的参数不对,造成内核启动不起来。

新建、更改、删除一个环境变量的方法

(1)新建一个环境变量,使用 set var value
(2)更改一个环境变量,使用 set var va1ue
(3)删除一个环境变量,使用 set var

注意:环境变量更改后需要的保存否则开机更改就没了。

这里是引用

7. uboot中对 Flash和DDR的管理

7.1uboot阶段flash的分区

(1)所谓分区,就是说对Flash进行分块管理;
(2)PC机等产品中,因为大家都是在操作系统下使用硬盘的,整个硬盘由操作系统统一管理,操作系统会使用文件系统帮我们管理硬盘空间。(管理保证了文件之间不会互相堆叠),于是乎使用者不用自己太过在意分区问题。
(3)在 uboot中是没有操作系统的,因此我们对 Flash(相当于硬盘)的管理必须事先使用分区界定(实际上在 uboot中和
kernel中都有个分区表,分区表就是我们在做系统移植时对
Flash的整体管理分配方法)。有了这个界定后,我们在部署系统时按照分区界定方法来部署,uboot和kerkel的软件中也是按照这个分区界定来工作,就不会错;
(4)分区方法不是一定的,不是固定的,是可以变动的。但是在一个移植中必须事先设计好定死,一般在设计系统移植时就会定好,定的标准是:
uboot:uboot必须从 Flash起始地址开始存放(也许是扇区0,也许是扇区1,也许是其他,取决于soc的启动设计),
uboot分区的大小必须保证 uboot肯定能放,一般设计为512KB或者1MB(因为一般
uboot肯定不足512KB,给再大其实也以工作,但是浪费);

环境变量:环境变量分区一般紧贴着 uboot来存放,大小为32KB或者更多一点;
kernel:kerne可以紧贴环境变量存放,大小一般为3M或5MB或其他。 rootfs:… 剩下的就是自由分区,一般
kernel启动后将自由分区挂载到 rootfs下使用.

> 总结:一般规律如下: (1)各分区彼此相连,前面一个分区的结尾就是后一个分区的开头; (2)整个flash充分利用,从开头到结尾; (3)
> uboot必须在Flash开头,其他分区相对位置是可变的;
> (4)各分区的大小由系统移植工程师自己来定,一般定为合适大小(不能太小太小了容易溢出:不能太大,太大了浪费空间);
> (5)分区在系统移植前确定好,在 uboot中和 kernel中使用同一个分区表。将来在系统部署时和系统代码中的分区方法也必须一样。

7.2、 uboot阶段DDR的分区

(1)DDR的分区和Flash的分区不同,主要是因为Flash是掉电存在的,而DDR是掉电消失,因此可以说DDR是每次系统运行时才开始部署使用的;
(2)内存的分区主要是在linux内核启动起来之前,linux内核启动后内核的内存管理模块会接管整个内存空间,那时候就不用我们来管;
(3)注意内存分区关键就在于内存中哪一块用来干什么必须分配好,以避免各个不同功能使用了同一块内存造成的互相踩踏。譬如说我们ttp
0x23E0000 zImage去下载
zImage到内存的0x23E00000处就会出错,因为这个内存处实际是uboot的镜像所在。这样下载会导致下载的 zImage把内存中的
uboot给冲掉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值