1.参考:http://blog.51cto.com/9291927/1791237
2.参考:https://wenku.baidu.com/view/de785ef427fff705cc1755270722192e4536582e.html?from=search
3.参考:http://blog.51cto.com/9291927/category5.html
4.转载:https://blog.csdn.net/wangweijundeqq/article/details/79127800
————————————————————————————————————————————————
一、uboot简介
U-Boot,全称 Universal Boot Loader,是遵循GPL条款的从FADSROM、8xxROM、PPCBOOT逐步发展演化而来的 开放源码项目。
- 在操作系统方面 ,U-Boot不仅支持
- 嵌入式Linux系统的引导,它还支持NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS, android嵌入式操作系统。目前支持的目标操作系统是OpenBSD, NetBSD, FreeBSD,4.4BSD, Linux, SVR4, Esix, Solaris, Irix, SCO, Dell, NCR, VxWorks, LynxOS, pSOS, QNX, RTEMS, ARTOS, android。
- 在CPU架构方面 ,U-Boot除了支持PowerPC系列的处理器外,还能支持MIPS、 x86、ARM、NIOS、XScale等诸多常用系列的处理器。
- uboot主要作用 是用来启动操作系统内核
uboot什么时候开始运行,什么时候结束运行?
1.uboot本质上是一个裸机程序(不是操作系统),一旦uboot开始SoC就会单纯运行uboot(意思就是uboot运行的时候别的程序是不可能同时运行的),一旦uboot结束运行则无法再回到uboot(所以uboot启动了内核后uboot自己本身就死了,要想再次看到 uboot界面只能重启系统。重启并不是复活了刚才的uboot,重启只是uboot的另一生)
2. **uboot的入口就是开机自动启动,uboot的唯一出口就是启动内核** 。uboot还可以执行很多别的任务(譬如烧录系统),但是其他任务执行完后都可以回到uboot的命令行继续执行uboot命令,而启动内核命令一旦执行就回不来了
二、uboot的工作模式
* U-Boot的工作模式有启动加载模式和下载模式。*
1、启动加载模式
启动加载模式是Bootloader的正常工作模式,嵌入式产品发布时,Bootloader必须工作在这种模式下,Bootloader将 [嵌入式操作系统](file:///h)从FLASH中加载到SDRAM中运行,整个过程是自动的
2、下载模式
下载模式就是Bootloader通过某些通信手段将 内核映像或 根文件系统映像等从PC机中下载到 目标板的FLASH中。用户可以利用Bootloader提供的一些命令接口来完成自己想要的操作。开发人员可以使用各种命令,通过串口连接或网络连接等通信手段从主机(Host)下载文件(比如内核映像、文件系统映像),将它们直接放在内存运行或是烧入Flash类固态存储设备中。
板子与主机间传输文件时,可以使用串口的xmodem/ymodem/zmodem协议,还可以使用网络通过tftp、nfs协议来传输,以及USB下载等方法。
一般来说,嵌入式开发人员采用下载模式进行开发嵌入式系统。通常采用交叉网线将PC与目标开发板连接,通过TFTP服务器下载内核,用NFS服务器挂载文件系统。
三、uboot的常用命令
有些命令有简化的别名
譬如printenv命令可以简化为print,譬如setenv可以简化为set
1、查询命令
命令:help 或 ?
功能:查看当前U-boot版本中支持的所有命令。
2、环境变量命令
环境变量就是运行时的配置属性,我们可以在不更改源程序的情况下,通过修改环境变量,直接修改运行结果(delay变量)。
环境变量有2份,一份在Flash中,另一份在DDR中。uboot开机时一次性从Flash中读取全部环境变量到DDR中作为环境变量的初始化值,然后使用过程中都是用DDR中这一份
bootdelay | 执行自动启动(bootcmd中的命令)的等候秒数 |
---|---|
baudrate | 串口控制台的波特率 |
netmask | 以太网的网络掩码 |
ethaddr | 以太网的MAC地址 |
bootfile | 默认的下载文件名 |
bootargs | 传递给Linux内核的启动参数 |
bootcmd | 自动启动时执行命令 |
serverip | TFTP服务器端的IP地址 |
ipaddr | 本地的IP地址 |
stdin | 标准输入设备,一般是串口 |
stdout | 标准输出,一般是串口,也可是LCD(VGA) |
stderr | 标准出错,一般是串口,也可是LCD(VGA) |
- 使用* print *命令可以打印出当前开发板的环境变量。
- setenv envname value设置环境变量的值(设置后记得save保存
(1)新建一个环境变量,使用set var value
(2)更改一个环境变量,使用set var value
(3)删除一个环境变量,使用set var
(4)save将修改的环境变量保存到固态存储器中,若不save,则只保存在DDR中。
1.bootcmd 自动启动执行命令
uboot开机后会自动倒计时,在倒计时结束前如果没有外部按键打断自动计时,uboot将自动执行bootcmd变量保存的命令。
意思是:将iNand的kernel分区读取到DDR内存的0x30008000地址处,然后使用bootm启动命令从内存0x30008000处去启动内核。
(1)可以将bootcmd设置为:set bootcmd print
然后save保存;重启则会看到启动倒数后自动执行print命令打印出环境变量,因此环境变量的设置没有限制。
(2) 再还原为内核启动命令:
set bootcmd 'movi read kernel 30008000; movi read rootfs 30B00000 300000; bootm 30008000 30B00000'
( 中间有分号记得必须得加 ' 单引号 ')
2.uboot给kernel传参:bootargs(内核移植中必定使用)
(1)linux内核启动时可以接收uboot给他传递的启动参数,这些启动参数是uboot和内核约定好的形式、内容,linux内核在这些启动参数的指导下完成启动过程。
(2)我们在uboot的环境变量中设置bootargs,然后bootm命令启动内核时会自动将bootargs传给内核。
意义解释:
console=ttySAC2,115200 控制台使用串口2,波特率115200.
root=/dev/mmcblk0p2 rw 根文件系统在SD卡端口0设备(iNand)第2分区,根文件系统是可读可写的
init=/linuxrc linux的进程1(init进程)的路径
rootfstype=ext3 根文件系统的类型是ext3
3、网络命令
. uboot可以通过网络来传输文件到开发板,直接用交叉网线连接开发板和电脑,也可以用普通直连网线连接路由器。
ping ipaddrs
-
网络命令搭建开发板uboot和虚拟机ubuntu互相ping通在我的2.1番外篇
如果网络连通,就可以通过tftp、NFS挂载开发板,然后下载文件
4.tftp下载指令:tftp
作用:使uboot为了部署内核就需要将内核镜像从主机中下载过来然后烧录到本地flash中去。
将要下载的镜像文件放在服务器的下载目录中,然后开发板中使用uboot的tftp命令去下载即可。
我的虚拟机搭建的时候设置的tftp下载目录是/tftpboot,将要被下载的镜像复制到这个目录下。
具体参考另一博客tftp服务器的安装搭建及使用(保证已经可以ping通)
5.nfs启动内核命令:nfs
作用: nfs服务,通过它"挂载"制作好的根文件系统。
主机开启nfs服务后,就可以像tftp一样传文件到开发板了,而且nfs还可以挂载根文件系统,这就是nfs的主要作用
具体参考另一博客* nfs服务器的安装及使用*
6.SD卡/iNand操作指令movi
-
movi的指令都是movi read和movi write一组的,
movi read用来读取iNand到DDR上,movi write用来将DDR中的内容写入iNand中。理解这些指令时一定要注意涉及到的2个硬件:iNand和DDR内存
-
movi指令是一个命令集,有很多子命令,具体用法可以help ,这里说明怎么看
例:movi read {u-boot | kernel} {addr}
这个命令使用了一种通用型的描述方法来描述:movi 和 read外面没有任何标记说明每一次使用这个指令都是必选的;一对大括号{}括起来的部分必选1个,大括号中的竖线表是多选一。中括号[]表示可选参数(可以有也可以没有)
譬如命令 movi read u-boot 0x30000000表示如下:
意思就是把iNand中的u-boot分区读出到DDR的0x30000000起始的位置处。
(uboot代码中将iNand分成了很多个分区,每个分区有地址范围和分区名,uboot程序操作中可以使用直接地址来操作iNand分区,也可以使用分区名来操作分区。);注意这里的0x30000000也可以直接写作30000000,意思是一样的( uboot的命令行中所有数字都被默认当作十六进制处理 ,不管你加不加0x都一样)。
7.NandFlash操作指令nand
nand info |
显示可使用的Nand Flash |
nand device [dev] |
显示或设定当前使用的Nand Flash |
nand read addr off size |
Nand Flash读取命令,从Nand的off偏移地址处读取size字节的数据到SDRAM的addr地址。 |
nand write addr off size |
Nand Flash烧写命令,将SDRAM的addr地址处的size字节的数据烧写到Nand的off偏移地址。 |
nand write[.yaffs[1]] addr off size |
烧写yaffs 映像专用的命令,.yaffs1 for 512+16 NAND |
nand erase [clean] [off size] |
Nand Flash檫除命令,擦除Nand Flash的 off 偏移地址处的size 字节的数据 |
nand bad |
显示Nand Flash的坏块 |
nand dump[.oob] off |
显示Nand Flash中的数据(16进制) |
nand scrub |
彻底擦除整块Nand Flash中的数据,包括OOB。可以擦除软件坏块标志。 |
nand markbad off |
标示 Nand的 off 偏移地址处的块为坏块 |
8.内存操作指令:mm、mw、md
-
nm 修改内存值 * ( *指定地址* )
格式: nm [.b, .w, .l] address
-
mm 修改内存值(地址自动加一) 输入y会退出
格式: mm [.b, .w, .l] address
-
md 显示内存值
格式: md [.b, .w, .l] address [# of objects]
-
mw 用指定的数据填充内存
格式: mw [.b, .w, .l] address value [count]
-
cp 内存的拷贝(包括内存与Nor Flash间的数据拷贝)
格式:cp [.b, .w, .l] source target count
.b:表示一个字节
9.启动内核指令:bootm、go
uboot命令行中调用这个指令就会启动内核(不管成功与否,所以这个指令是一条死路)。
差别: bootm启动内核同时给内核传参,而go命令启动内核不传参。
bootm其实才是正宗的启动内核的命令,一般情况下都用这个 ;
go命令本来不是专为启动内核设计的,go命令内部其实就是一个函数指针指向一个内存地址然后直接调用那个函数,go命令的实质就是PC直接跳转到一个内存地址去运行而已,
go命令可以用来在uboot中执行任何的裸机程序(有一种调试裸机程序的方法就是事先启动uboot,然后在uboot中去下载裸机程序,用go命令去执行裸机程序)
10、USB操作命令
usb reset |
初始化USB控制器 |
usb stop [f] |
关闭USB控制器 |
usb tree |
已连接的USB设备树 |
usb info [dev] |
显示USB设备[dev]的信息 |
usb storage |
显示已连接的USB存储设备 |
usb dev [dev] |
显示和设置当前USB存储设备 |
usb part [dev] |
显示USB存储设备[dev]的分区信息 |
usb read addr blk# cnt |
读取USB存储设备数据 |
使用USB操作命令前必须确保USB设备连接好,usb reset,以初始化USB控制器,获取设备信息。
11、SD/MMC操作命令
mmc init [dev] - 初始化MMC子系统
mmc device [dev] - 查看和设置当前设备
使用SD/MMC操作命令前必须确保SD/MMC设备连接好,mmc init,以初始化MMC 控制器,获取设备信息。
12、自动运行命令设置:bootcmd
(1)uboot启动后会开机自动倒数bootdelay秒,如果没有人按下回车打断启动,则uboot会自动执行启动命令来启动内核。
(2)uboot开机自动启动时实际就是在内部执行了bootcmd这个环境变量的值所对应的命令集。
(3)bootcmd=movi read kernel 30008000; bootm 30008000 意思是:将iNand的kernel分区读取到DDR内存的0x30008000地址处,然后使用bootm启动命令从内存0x30008000处去启动内核。
(4)set bootcmd printenv,然后saveenv;然后重启则会看到启动倒数后自动执行printenv命令打印出环境变量。这个小实验说明开机自动执行了bootcmd。
(5)set bootcmd 'movi read kernel 30008000; bootm 30008000'
四.uboot中对Flash和DDR的管理
uboot在Flash中的分区
Flash分区如下: | 功能: |
---|---|
自由分区 | 待用空间(一般做根文件系统使用) |
rootfs | 根文件系统文件 |
kernel | 内核文件 |
var | 环境变量 |
uboot | bootlater(必须在最前面) |
(1)各分区彼此相连,前面一个分区的结尾就是后一个分区的开头。
(2)整个flash充分利用,从开头到结尾。
(3)uboot必须在Flash开头,其他分区相对位置是可变的。
(4)各分区的大小由系统移植工程师自己来定,一般定为合适大小(不能太小,太小了容易溢出;不能太大,太大了浪费空间)
(5)分区在系统移植前确定好,在uboot中和kernel中使用同一个分区表。将来在系统部署时和系统代码中的分区方法也必须一样。
- uboot阶段DDR的分区 参考: http://blog.csdn.net/qq_25827755/article/details/53671992
因为Flash是掉电不丢失的,因此,在对Flash进行分区的时候要考虑到以后的使用条件。而DDR是掉电丢失的,因此,在系统的每个阶段都可以对它进行重新分区,例如在uboot阶段它有自己的分区管理,而在kernel启动起来之后,整个内存又将被kernel给接替过来,kernel将会对内存进行重新的分区和管理。
综上:DDR要根据具体使用情况对其进行分区管理,注意内存不要重叠。
五:uboot必须解决哪些问题
1、自身可开机直接启动
(1)一般的SoC都支持多种启动方式,譬如SD卡启动、NorFlash启动、NandFlash启动等·····uboot要能够开机启动,必须根据具体的SoC的启动设计来设计uboot
(2)uboot必须进行和硬件相对应的代码级别的更改和移植,才能够保证可以从相应的启动介质启动。uboot中第一阶段的start.S文件中具体处理了这一块。
2、能够引导操作系统内核启动并给内核传参
(1)uboot的终极目标就是启动内核。
(2)linux内核在设计的时候,设计为可以被传参。也就是说我们可以在uboot中事先给linux内核准备一些启动参数放在内存中特定位置然后传给内核,内核启动后会到这个特定位置去取uboot传给他的参数,然后在内核中解析这些参数,这些参数将被用来指导linux内核的启动过程。
3、能提供系统部署功能
(1)uboot必须能够被人借助而完成整个系统(包括uboot、kernel、rootfs等的镜像)在Flash上的烧录下载工作。(难怪在第一部分时,要把三个文件依次烧到210中)
(2)裸机教程中刷机(ARM裸机第三部分)就是利用uboot中的fastboot功能将各种镜像烧录到iNand中,然后从iNand启动。
4、能进行soc级和板级硬件管理
(1)uboot中实现了一部分硬件的控制能力(uboot中初始化了一部分硬件),因为uboot为了完成一些任务必须让这些硬件工作。譬如uboot要实现刷机必须能驱动iNand,譬如uboot要在刷机时LCD上显示进度条就必须能驱动LCD,譬如uboot能够通过串口提供操作界面就必须驱动串口。譬如uboot要实现网络功能就必须驱动网卡芯片。
(2)SoC级(譬如串口)就是SoC内部外设,板级就是SoC外面开发板上面的硬件(譬如网卡、iNand)
5、uboot的“生命周期”
(1)uboot的生命周期就是指:uboot什么时候开始运行,什么时候结束运行。从他开始运行到操作系统启动后。
(2)uboot本质上是一个裸机程序(不是操作系统),一旦uboot开始SoC就会单纯运行uboot(意思就是uboot运行的时候别的程序是不可能同时运行的),一旦uboot结束运行则无法再回到uboot(所以uboot启动了内核后uboot自己本身就死了,要想再次看到uboot界面只能重启系统。重启并不是复活了刚才的uboot,重启只是uboot的另一生)
(3)uboot的入口和出口。uboot的入口就是开机自动启动,uboot的唯一出口就是启动内核。uboot还可以执行很多别的任务(譬如烧录系统),但是其他任务执行完后都可以回到uboot的命令行继续执行uboot命令,而启动内核命令一旦执行就回不来了。
6、总结:一切都是为了启动内核