计算机系统的主要部件:
计算机系统就是以CPU为核心来进行计算的系统,比如PC机(台式机+笔记本),嵌入式系统(手机,平板电脑,游戏机),单片机(家用电器像电饭煲,空调等)
有的计算机系统的组成部件非常多,有的却很少,单都会有3个核心部件(CPU+Flash/硬盘等外部存储器+内部存储器DDR SDRAM/SRAM)
PC机的启动过程:
1)典型的PC机的部署:BIOS程序部署在PC机主板上,随主板出版已经预设,我们能够装系统,就是因为有BIOS的存在
操作系统部署在硬盘上,内存在掉电时无作用,CPU在断电时不工作
2)启动过程:PC在上电后先执行BIOS程序,实际上PC的BIOS就是NorFlash,BIOS程序负责初始化DDR内存,负责初始化到硬盘,然后从硬盘上把OS镜像读取到DDR中,然后跳转到DDR中去执行OS直到启动(启动之后BIOS就没用了)
典型的嵌入式Linux系统的启动过程:
1)系统的部署和启动都是参考PC机的
2)部署:uboot程序部署在Flash(能作为启动设备的Flash)上,OS部署在Flash(嵌入式系统中用Flash代替了硬盘)上,内存在断电时无作用,CPU在断电时不工作
3)启动过程:
嵌入式系统在上电后先执行uboot,然后uboot负责初始化DDR,初始化Flash,然后将OS从Flash中读取到DDR中,然后启动OS(OS启动后uboot就无用了)
总结:嵌入式系统和PC机的启动过程几乎没有差别只是把BIOS换成了uboot 硬盘换成了Flash
Andriod系统的启动过程:
和Linux系统的启动几乎完全相同,前边启动的过程完全一样,只是BIOD换成了Uboot,只是在内核启动后加载根文件系统后就不同了
可以认为它的启动氛围2个阶段:
1)uboot到OS启动 2)OS启动后到rootfs加载到命令行执行
uboot到底是干什么的?
1)用来启动操作系统的内核
2)负责部署整个计算机系统
3)还有操作Flash等板上硬件的驱动
4) uboot还得提供一个命令行界面来供人来操作
为什么是uboot?
1)ubbot是sourceForge上的开源项目
2)最早由一个德国人发起,后来很多人一起维护
uboot的可移植性的正确理解:
uboot就是universal
bootloader(通用的启动代码),通用的意思就是在各个地方都可以用,所以说它具有可移植性
2)uboot具有可移植性并不是说uboot在哪个开发板上都可以随便使用,而是说uboot具有子啊源代码级别的移植能力,可以针对多个开发板进行移植,移植后就可以在这个开发板上进行使用了
uboot自身必须先要解决的问题:
1)自身必须可以直接开机启动
a.一般的soc都支持多种启动方式,譬如SD卡启动,NorFlash启动,NandFlash启动等....ubbot要能够开机启动必须根据具体的Soc来设计才能实现
b.uboot必须进行和硬件相对应的代码级别的更改和移植才能保证可以相应的启动介质来启动uboot中第一阶段中的start.s文件中具体处理了这一点
2)能够引导操作系统内核启动并给内核传参
Linux内核在设计的时候,设计为可以被传参,也就是说我们可以在uboot中事先给内核准备一些启动参数放在内存中特定位置然后传给内核,内核启动的时候会到这个特定的位置去取uboot传给它的参数,然后在内核中解析这些参数,这些参数将来会被用来知道liunx内核的启动过程
3)能够提供系统部署的功能
uboot必须能够被人借助而完成整个系统(包括uboot kernel footfs等的镜像)在flash上的烧录下载工作
裸机中的刷机(ARM裸机第三部分)就是利用uboot中的fastboot功能将各种镜像烧纸到iNand中,然后从iNand启动
4)能够进行soc级和板级硬件管理
uboot中实现了一部分硬件的控制能力(uboot中初始化了一部分硬件),因为uboot为了完成一些任务必须让这些硬件工作,比如uboot要实现刷机必须能够驱动iNand,比如uboot要在刷机时LCD尚显示进度条就必须能够驱动LCD,比如uboot能够通过串口提供操作系统界面就必须能够驱动串口,要实现网络设备就必须能够驱动网卡芯片
Soc级(比如串口)就是soc内部外设,板级就是在soc外面开发板上边的硬件,比如网卡,INand
5)ubbot的生命周期
uboot的生命周期就是uboot什么时候开始运行,什么时候结束运行
uboot本质上就是一个逻辑程序,不是操作系统(从uboot可以ping主机,但是不能从主机ping uboot),一旦uboot开始soc就会单存的运行uboot(意思就是uboot运行的时候别的程序是不能同时运行的)一旦uboot结束,就无法再次回到uboot,相当于内核启动后uboot自己本身就死了,必须重启系统才能再次看到uboot界面
uboot的入口和出口:入口就是开机时的自动启动,你把它烧录到哪里他就从哪里开始启动,出口只有一个就是启动内核
6)总结:一切都是为了启动内核
uboot的工作方式
1 从逻辑程序镜像uboot.bin说起
1)uboot的本质就是一个裸机程序,和我们写的裸机程序xx.bin并没有本质的区别,如果非要说有区别,那就是:我们写的大部分小于16k,而uboot大于16kb
2)uboot本身是一个开源项目,有若干个c文件和h文件组成,配置编译之后生成一个uboot.bin,这个就是uboot的裸机程序的镜像文件,然后这个文件被合理的烧录到启动介质中拿去给soc启动,也就是说uboot在没有运行时表现为uboot.bin一般躺在启动介质中
uboot启动是会被加载到内存中然后一条指令一条指令的拿去给CPU执行
uboot的命令式shell界面:
1)普通的裸机程序运行起来就直接执行了,执行时效果和代码有关
2)有些程序需要和人进行交互,于是程序中就实现了一个shell(shell就是提供人机交互的一个界面,ARM裸机16),uboot就实现了一个shell
注意 shell并不是一个操作系统和操作系统完全没有关系,Linux中打开一个终端后就得到了一个shell,可以继续输入回车执行 uboot中的shell工作模式和Linux中的shell很像,几乎是一样的,只是命令集不同,比如Linux的shell可以使用ls,uboot不识别
掌握uboot使用的2个关键点:
1)uboot启动后大部分时间和工作都是在shell下完成的(比如uboot要部署系统要在shell下输入命令,要设置环境变量也得正在命令行下,要启动内核也要在命令行下)
2)命令就是uboot的shell中可以识别的各种命令,uboot的命令有几十个,有常用的和不常用的,还可以自己添加命令进去
3)uboot在设计时借助了Linux的操作系统的设计理念命令行的工作方式也是借鉴了Linux命令行,环境变量借鉴了操作系统的环境变量,uboot的驱动管理几乎全部抄袭了Linux的驱动框架
4)环境变量可以认为是系统的全局变量,环境变量名都是系统内置的 系统或者自己的程序再运行时就读取环境变量来指导程序的执行
5)环境变量就是运行时的配置属性
uboot的常用命令
1)类似Linux终端的行缓冲命令:当我们向Linux终端的命令行输入命令的时候,这些命令没有被系统立即识别,而是被缓冲到一个缓冲区(也就是认为我们还没输入完,当按下回车键后系统才认为输入完毕,然后把缓冲区命令拿去执行)
2)Linux的3种缓存机制:a 无缓冲 b全缓冲 c 行缓冲
有些命令有简化的别名 printenv -> print
uboot的有些命令带的参数非常长,为了告诉uboot这个非常长而且中间有好多空格隔开的东西是给他的一个完整的参数,用单引号将这个参数引起来
别的符号也许有,而且有特定的含义,当碰到uboot的命令行有特殊的字符的时候注意不是弄错了,有可能是有特别的含义
有些命令是一个命令族,比如movi
1)命令族就是好多个命令开头都是用同一个命令关键字的,但是后边的额参数不一样,这些命令的功能和作用也不同,这就叫一个命令族
2)同一个命令族的所有命令有极大的关联,如movi都和iNand有关
常用命令:
1)print不带参数,打印出所有的环境变量,环境变量就好像是程序的全局变量,程序中任何地方都可以调用或者更改,但一般只是访问,不会去更改,它和全局变量的不同在于:全局变量的生命周期是在程序的一次运行中,开始运行时诞生,结束时死亡,下次程序运行时重新开始,但是环境变量是被存储在Flash的另一个专门区域,Flash有一个环境变量分区,下次开机时,环境变量的值将维持上一次更改后保存的值
2) setenv/set name value 设置环境变量的值 set 不加参数 删除环境变量
3)saveenv/save 不带参数,直接执行时把内存中的环境变量的值整体保存到Flash的环境变量的分区,注意是整体覆盖(flash是块设备,不能单个变量save)
所以,要想彻底更改uboot中环境变量的值,要a先更改内存中的环境变量,b使用save命令同步到flash中,如果只是set不save那么它只会更改内存中的值不会影响flash中的值,下次启动时从falsh加载,所以还是原来的值
ping命令:
ping ip地址,测试开发板和主机之间的网络连接
1)要先插上网线
2)先视图ping通windows,注意设置win的本地连接ip
3)确认开发板中uboot里几个网络相关的环境变量的值对不对,最重要的是ipaddress,这个环境变量表示的是当前开发板的ip地址,这个ip必须和win主机的ip在同一个网段
开发板运行Linux下和虚拟机ubutun的ping通
1)虚拟机要想和开发板进行网络通信,只能通过桥接模式连接
2)虚拟机的菜单有个 虚拟网络编辑器,这里边要设置为桥接到有线网卡,一个是有限的一个是无线的,不能选择自动,如果选择自动的话,虚拟机会自动桥接到无线网卡上,我们事用优先网卡来连接开发板的,所以没办法ping通
uboot本身的主要目标是启动内核,为了完成启动内核必须要能够部署到内核 ,ubbot内核部署就需要内核镜像从主机中下载过来然后烧录到本地flash种,uboot从主机win或者Linux 虚拟机中下载镜像到开发板上 ? 主流的方式是fastboot和tftp
fastboot的方式是通过usb线进行数据传输
tftp下载实际上uboot扮演的是tftp客户端的角色,主机win或Linux中必须有一个tftp服务器,然后将要下载的镜像文件放到服务器的下载目录中,然后开发板使用tftp命令进行下载,检查开发板uboot的环境变量,有一个serverip必须设置为虚拟机的ip
将要下载的镜像复制到tftp的下载目录下,然后在开发板的uboot下先ping通虚拟机,然后再尝试下载
uboot也支持nfs(不太常用,网上查一下资料)
SD卡/iNand操作指令movi
开发板如果使用SD卡 /EMMC/iNand等作为flash,则在uboot中操作flash的指令为movi或者mmc
movi是一个命令族有很多子命令,可以man movi具体查看 都是movi read和movi write的一组的,movi read用来读取iNad到DDR上,movi write静DDR中的内容写入到iNand中
指令的通用描述法:例:movi read {u-boot | kernel} {addr}
没有任何标识的movi和read是必选的,大括号中的竖线标识多选一 中括号[]标识可选选项
指令有很多用法,eg movi read u-booy 0x30000000 就是把iNand中的u-boot分区读出到0x3000000000起始的位置处 uboot代码中将iNand分成了很多分区,每个分区有地址范围和分区名,uboot程序操作中可以只有直接地址来操作iNad分区,也可以使用分区名来操作分区
常用的环境变量:
如何参入程序运行 ?
1)环境变量有2份,一份在flash中,另一份在ddr中,uboot开机时一次性从flash中读取全部的环境变量到ddr中作为环境变量的初始化值,然后使用过程中都是使用ddr中的这一份,用户可以使用save命令将ddr中的值重新写入flash中去更新flash中的环境变量,下次开机时又会从falsh中重读一次
2)uboot的环境变量是用字符串表示的,也就是它是按字符匹配识别环境变量的,所以注意不能写错单词
自动运行倒数时间:bootdelay
网络设置:ipaddr serverip
1)ipaddr:是开发板的本机ip
2)serverip是开发板通过tftp指令去tftp服务器下载东西时,tftp服务器的ip地址
3)gatewayip是开发板的本机网关地址
4)netmask是子网掩码
5)ethaddr是开发开发板的本地网卡的mac地址
自动运行命令设置 bootcmd
1)uboot在启动后会开机自动倒数bootdelays,如果没有人按下enter打断这个过程,就会自动启动内核
2)uboot开机自动启动是实际上就是在内部执行了bootcmd这个环境变量的值所对应的命令集
3)bootcmd=movi read kernel 30008000;boottm 30008000就是:
将iNand的kernel分区读取到内存的0x0008000地址处,然后使用bootm启动命令从内存0x30008000处去启动内核
4)set bootcmd pritenv,然后saveenv;然后重启就会看到启动倒数后自动执行print命令打印出环境变量,也就是bootdelay后执行的命令就是bootcmd命令设置的参数
5)set bootcmd 'bootcmd=movi read kernel 30008000;boottm 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 控制台使用串口,波特率=11520
root=/dev/mmcblkop2 rw 就是根文件系统在SD卡端口0设备(iNand)第二分区,根文件系统是可读写的,
init=/linuxrc Linux的进程1 init进程的路径
rootfstype=ext3 根文件系统的类型是ext3
4)内核传参很重要,在内核一直的时候,新手经常忘记给内核传参,或者给内核传递的参数不对,导致内核无法启动
新建更改删除一个环境变量
新建:set var value
更改:set var value
删除:set var
注意:set环境变量后记得save