姓名:张硕 学院:电子工程学院 学号:19020100006
转自:https://blog.csdn.net/qq_38612145/article/details/107497384
嵌牛导读:本文主要介绍了uboot基础以及uboot的工作方式以及常见命令
嵌牛鼻子:嵌入式,uboot
嵌牛提问:uboot有哪些常用命令
嵌牛正文:
uboot基础
1.为什么要有uboot?
预备知识
计算机系统运行时的主要核心部件包含3个东西:CPU+外部存储器+内部存储器
PC机启动过程为:PC上电后先执行BIOS程序(实际上PC 的BIOS就是NorFlash),BIOS负责初始化DDR内存和硬盘,然后从硬盘上将OS镜像读取到DDR中,然后跳转到DDR中去执行OS直到启动(OS启动后BIOS就无用了)
uboot主要作用是用来启动操作系统内核,部署整个计算机系统,有操作Flash等板子上硬件的驱动,提供一个命令行界面供人操作
uboot程序部署在能作为启动设备的Flash做上,OS部署在Flash上,内存在掉电时无作用,CPU在掉电时不工作
嵌入式系统上电后先执行uboot、然后uboot负责初始化DDR,初始化Flash,然后将OS从Flash中读取到DDR中,然后启动OS(OS启动后uboot就无用了)
2. uboot必须解决的问题
自身可开机直接启动
必须根据具体的SoC的启动方式来设计uboot
uboot必须进行和硬件相对应的代码级别的更改和移植,才能保证响应启动介质的启动,uboot中第一阶段的start.S文件中处理了这一块
能够引导操作系统内核启动并给内核传参
我们可以在uboot中事先给Linux内核准备一些启动参数放在内存中特定位置然后传给内核,内核启动后会到这个特定位置去取uboot传给他的参数,然后内核解析这些参数
能提供系统部署功能
uboot必须能够被人借助而完成整个系统在Flash上的烧录下载工作(裸机在刷机时就是利用uboot中的fastboot功能将各种镜像烧录到iNand中,然后从iNand启动)
能进行SoC级和板级硬件管理
uboot中实现了一部分硬件的控制能力,因为uboot为了完成一些任务必须让一些硬件工作。譬如uboot要在刷机时LCD上显示进度条就必须驱动LCD。
SoC级就是SoC内部外设,板级就是SoC外面开发板上面的硬件
uboot存在生命周期
uboot本质上是一个裸机程序,一旦uboot开始SoC就会单纯运行uboot,一旦uboot结束运行就无法再回到uboot
uboot入口为开机自动启动;出口为启动内核
3. uboot的工作方式
从裸机程序镜像uboot.bin说起
uboot的本质就是一个裸机程序,和裸机教程中的裸机程序xx.bin没有本质区别,区别主要在于文件大小,uboot在180k-400k之间
uboot本身为一个开源项目,由若干个.c文件和.h文件组成,配置编译之后会生成一个uboot.bin,这就是uboot这个裸机的镜像文件。然后镜像文件被合理的烧录到启动介质中拿去给SoC启动,即uboot在没有运行时表现为uboot.bin
uboot运行时会被加载到内存中,然后逐次拿给CPU去运行
uboot的命令式shell界面
有些程序需要人机交互,于是程序中就实现了一个shell
shell并不是操作系统,和操作系统一点关系都没有,裸机也可以有shell
uboot使用的关键点:命令和环境变量
uboot启动后大部分时间和工作都是在shell下完成的。uboot部署系统要在shell下输入命令、要设置环境变量也需要在命令行下,要启动内核也要在命令行下输入命令
uboot中有几十个命令,其中一些常用,还可以自己给uboot添加命令
uboot的环境变量和操作系统的环境变量工作原理和方式几乎完全相同,uboot的驱动管理完全照抄了linux的驱动框架。系统或者程序在运行时可以通过读取环境变量来指导程序的运行。环境变量就是运行时的配置属性。
4. uboot常用命令
命令特点
有些命令有简化的别名
printenv -> print
setenv -> set
有些命令会带参数
每个命令都有事先规定好的格式,可以通过help命令查看
命令中的特殊符号(譬如单引号)
uboot有些命令带的参数非常长,为了告诉uboot这个非常长且中间有好多空格的语句为一整个参数,使用单引号将这个语句引起来
有些命令是一个命令族(譬如movi)
命令族的意思就是好多个命令开头都是用同一个命令关键字的,但是后面的参数不一样,这些命令的功能和作用也不同
同一个命令族中所有的命令都有极大的关联,譬如movi开头的命令族都和moviNand(EMMC、iNand)操作有关。
常见命令
打印环境变量:printenv/print
命令不用带参数,打印出系统中所有的环境变量。环境变量被存储在Flash的一块专门区域,一旦程序中保存了该环境变量,下次开机时该环境变量的值将维持上一次更改保存后的值
设置(添加/更改)环境变量:setenv/set
set name value
保存环境变量的更改:saveenv/save
不带参数,直接执行。是对整体环境变量的保存
网络测试指令:ping
步骤
用网线将电脑和开发板连接
设置电脑本地连接IPV4地址为192.168.1.10
确认开发板中uboot里几个与网络相关的环境变量的值对不对。最重要的是ipaddr的地址必须与主机的IP地址在同一个网段内。(set ipaddr 192.168.1.xx)
tftp下载命令:tftp
uboot主要目标是启动内核,为了完成启动内核必须要能够部署内核,而内核镜像需要从主机中下载烧录到开发板的Flash中,下载镜像的主流方式为fastboot和tftp。fastboot的方式是通过usb线进行数据传输;tftp是通过网络传输的
tftp方式下载时uboot扮演的是tftp客户端程序角色,主机中必须有一个tftp服务器,然后将要下载的镜像文件放在服务器的下载目录中,然后在开发板中使用uboot的tftp命令去下载
虚拟机和开发板ping通的步骤
虚拟机处选择桥接方式
在虚拟网络编辑器中设置为桥接到有线网卡
在虚拟机中设置IP静态地址为192.168.1.102(修改/etc/network/interfaces文件中的内容)
重启网络
sudo ifconfig eth0 down
sudo ifconfig eth0 up
在虚拟机上搭建tftp的下载目录/tftpboot,将要被下载的镜像复制到这个目录下
检查开发板uboot的环境变量,注意serverip必须设置与虚拟机Ubuntu的ip静态地址相同
在开发板uboot中使用tftp命令下载虚拟机中的镜像
tftp 0x30000000 zImage-qt
意思为将服务器上名为zImage-qt的文件下载到开发板内存的0x30000000地址处
镜像下载到开发板DDR中后,uboot就可以用movi指令进行镜像的烧写了
SD卡/iNand操作指令:movi
开发板如果用SD卡/EMMC/iNand等作为Flash,则在uboot中操作Flash用指令movi
movi指令是一个命令集,在uboot中可通过help movi查看
movi 的指令都是movi read和movi write一组的,movi read用来读取iNand到DDR上,movi write用来将DDR中的内容写入iNand中。
NandFlash操作指令:nand
操作方法完全类似于movi指令
内存操作指令:mm、mw、md
DDR中是没有分区的,但是内存使用时千万不能越界,因为uboot是一个裸机程序,不像操作系统会由系统整体管理所有内存,则可能会出现程序的覆盖
md:memory display,显示内存中的内容
mw:memory write,将内容写到内存中
mm:memory modify,修改内存中的一块,会批量逐个修改
启动内核指令:bootm、go
bootm启动内核同时给内核传参,而go命令启动内核不传参。
bootm是正宗的启动内核的命令,go命令本来不是专为启动内核设计的,go命令的实质是PC直接跳转到一个内存地址去运行而已。go命令可以用来在uboot中执行任何的裸机程序
5. uboot环境变量
如何理解环境变量
环境变量有2份,一份在Flash中,一份在DDR中。uboot开机时一次性从Flash中读取全部环境变量到DDR中作为环境变量的初始化值,然后使用过程中都是用DDR中这一份,用户可以通过saveenv指令将DDR中的环境变量重新写入Flash中去更新Flash中环境变量。下次开机时又会从Flash中再读一次
环境变量在uboot中是用字符串表示的,注意不要错别字,出现保存错误环境变量后set xxx消除并保存
自动运行命令设置:bootcmd
uboot在启动后会开机自动倒数bootdelay秒,如果没有打断则会自动启动内核
uboot中打印环境变量可以看到
bootcmd=movi read kernel 30008000
上述语句意思为将iNand的kernel分区读取到DDR内存的0x30008000地址处,然后使用bootm启动命令从内存0x30008000处去启东内核
uboot给kernel传参:bootargs
Linux内核启动时可以接收uboot给他传递的启动参数,这些参数使uboot和内核约定好的形式、内容,为了内核在不重新编译的情况下可以用不同的方式启动
在uboot的环境变量中设置bootargs,然后bootm命令启动内核时会自动将bootargs传给内核
bootargs=console=ttySAC2,115200 root=/dev/mmcblk0p2 rw init=/linuxrc rootfstype=ext3
意义解释:控制台使用串口2,波特率为115200
root=… 根文件系统在SD卡端口0设备(iNand)第2分区,根文件系统是可读可写的
init=… Linux的进程1(init进程)的路径
rootfstype=… 根文件系统的类型是ext3
内核传参非常重要。在内核移植的时候,新手经常忘记给内核传参,或者给内核传递的参数不对,造成内核无法启动
新建、更改、删除一个环境变量的方法
新建和更改
set var value
删除
set var
修改完环境变量后一定要保存
6. uboot对Flash和DDR的管理
uboot阶段的Flash分区
所谓分区,就是对Flash进行分块管理
PC机等产品,都是在操作系统下使用硬盘的,整个硬盘由操作系统统一管理,使用者不用自己太在意分区问题
在uboot中没有操作系统,对Flash的管理必须事先使用分区界定,在部署系统时按照分区界定方法来部署,uboot和kernel的软件中也是按照这个分区界定来工作就不会出错
分区不是固定的,在一个移植中必须事先设计好定死。一般在设计系统移植时就会定好,定的标准是:uboot必须从Flash起始地址开始存放,uboot分区大小必须保证uboot肯定能放下,一般设计为512kb或者1MB;环境变量分区一般紧贴着uboot来存放,大小为32KB或多一点;kernel可以紧贴环境变量存放,大小一般为3MB或5MB或其他;rootfs紧贴着kernel;剩下的就是自动分区,一般kernel启动后将自由分区挂载到rootfs下使用
总结
各分区彼此相连
整个Flash充分利用,从开头到结尾
uboot必须在Flash开头,其他分区相对位置可变
各分区的大小由系统移植工程师来定
分区在系统移植前确定好,在uboot中和kernel中使用同一个分区表
uboot阶段DDR的分区
因为Flash是掉电存在的,而DDR是掉电消失,因此可以说DDR是每次系统运行时才开始部署使用的
内存的分区主要是在Linux内核启动之前,Linux内核启动后内核的内存管理模块会接管整个内存空间
内存分区关键就在于内存中哪一块用来干什么必须分配好,以避免各个不同功能使用了同一块内存造成覆盖。