zoukankan      html  css  js  c++  java
  • 2、uboot学习前传

    2.1.1为什么要有uboot

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

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

    2.2.1.2、PC级的启动过程

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

    2.2.1.3、典型嵌入式linux系统启动过程

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

    总结:嵌入式系统和PC机启动过程几乎没有两样,知识BIOS成了uboot,硬盘成了Flash

    2.2.1.4、android系统启动过程

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

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

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

    2.1.2、为什么是uboot

    2.1.2.1、uboot是从哪里来的?

    • (1)uboot是SourceForge上的开源项目
    • (2)uboot项目的作者:德国人最早发起的项目
    • (3)uboot就是由一个人发起,然后由整个网络上所有感兴趣的人共同维护发展而来的一个bootloader

    2.1.2.2、uboot的发展历程

    • (1)自己使用的小开源项目
    • (2)被更多人认可使用
    • (3)被SoC厂商默认支持

    总结:uboot经过度年发展,已经成为事实上业内的BootLoader标准,现在大部分的嵌入式设备都默认使用uboot来作为bootloader

    2.1.2.3、uboot的版本号问题

    • (1)早期的uboot的版本号类似于这样:uboot1.3.4  后来版本号变成了类似于这样uboot-2010.06
    • (2)uboot的核心部分几乎没什么变化,越新的版本支持的开发板越多而已,对于一个老版本的芯片来说,新旧版本的uboot并没有差异。

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

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

    2.1.2.5、总结:时势造英雄,任何牛逼的东西都是时代的产物

    • uboot的出现时一种必然,如果没有uboot也会有另一个bootloader来代替

    2.1.3、uboot必须解决哪些问题

    2.1.3.1、自身可开机直接启动

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

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

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

    2.1.3.3、能提供系统部署功能

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

    2.1.2.4、能进行SoC级和板级硬件管理

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

    2.2.1.5、uboot的“声明周期

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

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

    2.1.4.uboot的启动方式

    2.1.4.1、从裸机镜像uboot.bin说起

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

    2.1.4.2、uboot的命令式shell界面

    • (1)普通的逻辑程序运行起来就直接执行了,执行时效果和代码有关
    • (2)有些程序需要和人进行交互,于是乎我们的程序中实现了一个shell(shell是提供人机交互的界面,回想ARM裸机全集的第十六部分),uboot就实现了一个shell

    注意:shell并不是操作系统,和操作系统一点关系都没有。在linux中,打开一个中断后就得到了一个shell,可以输入命令回车执行。uboot中的shell工作方式和linux中的终端

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

    • (1)uboot启动后大部分时间和工作都是在shell下完成的(譬如uboot要部署系统要在shell下输命令、要设置环境变量也得在命令行下,要启动内核也要在命令行底下敲命令行)
    • (2)命令就是uboot的shell中可以识别的各种命令。uboot中有几十个命令,其中有一些常用,另一些不常用(我们还可以给自己添加命令),后面会用几节课时间来一次学习uboot中常见命令。
    • (3)uboot的环境变量和操作系统的环境变量工作原理和方式几乎完全一样,uboot在设计是借助了操作系统的设计理念(命令行工作方式借鉴了linux中断命令行,环境变量借鉴了操作系统的环境变量,uboot的驱动管理几乎完全照抄了linux的驱动框架)
    • (4)环境变量可以被认为是系统的全局变量,系统在运行的时候环境变量名是系统内置的,认识就认识,不认识就不认识。但是也有一部分环境变量是我们自己添加的。系统就不认识,但是我们的程序自己认识。系统或者我们自己的程序在运行时可以通过读取环境变量来知道程序的运行。这样设计的好处就是灵活,譬如我们要让一个程序更改运行方法,不用去重新修改程序代码在重新编译运行,而只要修改相应的环境变量就可以了

    2.1.4.4、思考:结合ARM裸机部分进行理解和印证

    •  (1)及时复习ARM裸机中和现在讲到的相关知识点,在复习中巩固ARM裸机所学的。这过程中如果原来记了笔记的非常容易,非常好,如果没有那就难办了
    • (2)及时对照原来ARM裸机中讲到的相关部分,可以帮助理解当前讲到的知识点
    • (3)结合ARM裸机中和现在讲的,对比分析思考,会得到更多

    2.1.5、uboot的常用命令1

    2.1.5.1、类型linux终端的行缓冲命令行

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

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

    • (1)譬如printenv可以简化为print,两者效果完全一样的   (用于打印当前的环境变量)
    • (2)譬如setenv可以简化位set,这两者效果也是一样的    (用于设置环境变量的值)

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

    • (1)uboot的每个命令都有实现规定好的各种格式。有些命令就是不带参数的,譬如printenv/print命令;有些命令带可选的参数(可以带也可以不带,当然带不带参数执行 结果时不同的)

    2.1.5.4、命令中的特殊符号(譬如单引号)

    • (1)uboot的有些命令带的参数非常长,为了告诉uboot这个非常长而且中间有好多个空格的东西给他的一整个参数,所以用单引号将这个很长且中间有空格隔开的参数引起来
    • (2)别的符号也许也有,而且又特定的意义。当碰到uboot的命令行有特殊符号时要注意不是弄错了,而是可能有特别的意义。

    2.1.5.5、有些命令是一个命令族

    • (1)命令族的意思就是好多个命令开头都是同一个命令关键组,但是后面的参数不一样,这些命令的功能和作用大不相同,这就叫做一个命令族
    • (2)同一个命令族中所有的命令都有极大的关联,譬如movi开头的命令族都是和moviNand(EMMC、iNand)操作有关

    2.1.5.6、第一个命令:printenv/print

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

     2.1.6、uboot的常用命令2

    2.1.6.1、设置(添加/修改)环境变量:setenv/set

    • (1)用法:set name value

    2.1.6.2、保存环境变量的更改:saveenv/save

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

    总结:彻底更改环境变量的值需要两步:第一步set命令来更改内存中的环境变量,第二步用save命令将其同步到Flash中环境变量的分区

    有时候我们只是想测试下这个环境变量,不希望影响到下一次开机,那就孩子set不save,这样发set后当前本次运行uboot已经起到效果了,只是没有save到下一次,开机还是会恢复到原来的状况。

    2.1.6.3、网络测试指令:ping

    • (1)命令用法:ping ip地址

    注意:ping是测试开发板和主机之间的网络连接,注意一下步骤

    • (1)首先要插上网线
    • (2)先试图ping通windows,注意有限网卡的网络地址的设置(设置本地连接)设置windows的本地连接IPV4地址为192.168.1.10
    • (3)第三步确认开发板中uboot力几个网络相关的环境变量对不对,最重要的是ipaddr(这个环境变量表示当期开发板的ip地址)这个地址必须和主机windows的ip地址在同一个网段。

    网段的概念:一个ip地址分为2部分,一部分是网段地址,另一部分是网段内的主机地址(由子网掩码区分那一部分是网段地址,哪一部分是ip地址)。在子网掩码是255.255.255.0的情况下,192.168.1.10这个IP地址的前三部分(192.168.1.)属于网段地址,第四部分(10)属于主机地址。

    2.1.7、开发板和主机的ping通

    上节课最后的结构是:uboot中的ipaddr和主句windows本地连接地址已经设置到了一个网段,但实际还是ping不通

    还发现了这样的现象。

    • 1、把2个的网段都从都从192.168.1.x改到192.168.0.x时会ping通一次,第二次开始就ping不通了。
    • 2、有同学说平不同可能是uboot中的getwayip没设置,我就实际测试设置网关位同网段.1,结论是第一次ping通了,但是第二次又ping不通了。

    2.1.7.1、开发板运行linux下和主机windows的ping通

    • (1)先将开发板刷成linux+QT镜像(刷机见裸机教程第三部分),然后启动进入linux命令行终端下
    • (2)在linux下使用ifconfig命令将开发板中linux系统的IP地址设置为主机windows同一网段(为了上课方便,以后固定为:主机windows地址:192.168.1.10, 开发板uboot或linux的地址为192.168.1.20,虚拟机ubuntu地址为192.168.1.141)
    • (3)此时开发板ping windows通的
    • (4)windows中ping开发板也是通的

    说明:首先开发板和主机的网络部分硬件是好的,网络连接也是好的,主机windows中的网络软件设置时好的

    2.1.7.2、开发板运行linux下和虚拟机ubuntu的ping通

    • (1)在linux基础课中讲过:虚拟机的网卡设置可以选择好几种方式,常用的就是NAT和桥接(bridge)
    • (2)虚拟机要想被开发板ping通,设置步骤如下:

    第一步:虚拟机----->设置------->网络适配器------>桥接模式------->复制物理网络连接状态

    第二步:   编辑------->虚拟网络编辑器------>Vmnet0------>桥接模式,选择有线网卡-------->应用、确定。

    (虚拟机的菜单中有个“虚拟网络编辑器”,这里面要设置位桥接到有限网卡:一个有限的一个无线的。如果选了自动,那么虚拟机会自动桥接到无线网卡上,但是我们却是通过有限网卡来连接开发板的,自然ping不通 )

    第三步:ifconfig eth0 192.168.1.14             在虚拟机ubuntu中设置IP地址位IP地址为192.168.1.141(可以通过/etc/network/interfaces文件来设置静态的然后重启,也可以通过ifcongig去设置)

           此时开发板ping虚拟机ubuntu应该就通了

     一些指令:

         关闭ubuntu防火墙:sudo ufw disable

         开启ubuntu防火墙:sudo ufw enable

         关闭ubuntu网卡sudo ifconfig eth0 down

         打开ubuntu网卡sudo ifconfig eth0 up

    2.1.7.3、开发板运行uboot下和主机windows的ping通

    • (1)刚才在开发板运行linux时和主机windows、虚拟机ubuntu都ping通了,说明硬件和连接和主机设置都没错
    • (2)此时开发板重启进入uboot,设置好ipaddr,gatewayip,然后去ping windows发现还是不通。怀疑uboot本身网络驱动有问题
    • (3)然后同样发情况下,尝试去ping通虚拟机ubuntu

    2.1.7.4、开发板运行uboot下和虚拟机ubuntu的ping通

    • (1)uboot和虚拟机ubuntu互相ping通(前提是虚拟机设置位桥接,且桥接到有限网卡,且ip地址设置正确的情况下)

    结论:开发板中运行的uboot有点小bug,ping windows就不通,ping虚拟机的ubuntu就不通

    2.1.8、uboot常用命令3

    2.1.8.1、tftp下载指令:tftp

    uboot本身主要目标是启动内核,为了完成启动内核必须要能够部署内核,uboot为了部署内核就需要将内核镜像从主机中下载过来到本地flash中,uboot如何从主机(windows或者是虚拟机的ubuntu)下载镜像到开发板上?有很多种方式,主流方式是:fastboot和tftp

    fastboot的方式是通过USB线进行数据传输

    • (1)tftp的方式是通过有线网络的。典型的方式就是通过网络,fastboot是近些年才发展的。
    • (2)tftp方式下载时实际上uboot扮演的是tftp的客户端程序角色,主机windows或虚拟机ubuntu中必须有一个tftp服务器,然后将要下载的镜像文件放在服务器的下载目录中,然后开发板中使用uboot中的tftp命令去下载即可
    • (3)有些人习惯在windows中搭建tftp服务器,一般是用一些软件搭建(譬如tftpd32,使用起来比较简单);有些人习惯在linux下搭建tftp服务器,可以参考网盘中虚拟机下载目录下的额一个教程《嵌入式开发环境搭建-基于14.04.pdf》,这里面有ubuntu中搭建tftp服务器的教程,也可以自己上网搜索教程尝试解决。(如果用我们的虚拟机,那就已经搭建好了,不用搭建了;如果自己新装的那就参考文档搭建;如果你的版本和我的不一样,那么搭建过程可能不一样)
    • (4)我的虚拟机搭建的时候设置的tftp下载目录是/tftpboot,将要被下载的镜像赋值到这个目录下。

        怎么搭建虚拟机?

        1. 首先要保证虚拟机可以上网。在笔记本连接无线的情况下,可以通过它桥接的方式。设置如下:
        2. 第一步:编辑------->虚拟机网络编辑器------>Vmnet0桥接模式,自动。应用,确定
        3. 虚拟机----->设置------网络适配器----->桥接模式,不勾选复制物理网络连接状态
    • (5)检查开发板的uboo的环境变量,注意serverip必须设置位虚拟机ubuntu的ip地址。(serverip这个环境变量的意义就是主机tftp服务器的ip地址)
    • (6)然后在开发板的uboot下ping通虚拟机ubuntu,然后在尝试下载:tftp 0x30000000 zImage-qt(意思是将服务器上名字为zImage-qt的文件下载到开发板内存的0x30000000地址处。)
    • (7)镜像下载到开发板的DDR中后,uboot就可以用movi指令进行镜像的烧写了。

    注意:

    • 1)如果你是用的windows下的tftp服务器,那么你的开发板上的severip就要设置为和你的windows下tftp服务器的ip地址一样(windows下的tftp服务器软件设置的时候就哟个步骤让你设置服务器的ip地址,这个ip地址和主机windows必须在一个网段)
    • 2)整个过程中间环节比较多,实际做的时候可能下载不下来,这里的可能性非常多。自己对照视屏课程讲的思路一步步排查

    第一步先保证uboot和ubuntu可以ping通。第二步:保证tftp服务器搭建没错:第三步,再实现tftp下载。如果第一步有问题参考网络设置部分,第二步有问题(tftp本地测试下载OK,但是开发板不行)解决方案就是使用windows下的tftp服务器

    2.1.8.2、nfs启动内核命令:nfs

    • (1)uboot中也支持nfs命令

    2.1.9、uboot的常用命令4

    2.1.9.1、SD卡/iNand操作指令movi

    • (1)开发板如果用SD卡/EMMC/iNand等作为Flash,则在uboot中操作flash的指令位movi(或者mmc)
    • (2)movi指令是一个命令集,有很多子命令,具体用法可以用help movi命令来查看
    • (3)movi的指令都是movi read 和movi write一组的,movi read用来读取iNand到DDR上,movi write 用来将DDR的内容写入iNand中。理解这些指令时一定要注意涉及到的2个硬件;iNand和DDR内存
    • (4)movi read  {u-boot | kernel} {addr} 这个命令使用了一种通用型的描述方法来描述:movi 和read 外面没有任何的标记,说明每一次使用这个指令都是必选的,一对大括号{ }栝起来的部分必选一个,大括号中的竖线表示多选一。中括号[ ] 表示可选参数(可以有,也可以没有)
    • (5)指令有多种用法,譬如movi read u-boot 0x30000000,意思就是把iNand中的u-boot分区读出到DDR的0x30000000其实的位置处。(uboot代码中将iNand分成了很多个分区,每个分区有地址范围和分区名,uboot程序操作中可以直接地址来操作iNand分区,也可以使用分区名来操作分区)注意0x30000000也可以直接写作30000000,意思是一样的(uboot的所有命令行中所有的数字都被当作十六进制来处理,不管你加不加0x都是一样的)

    2.1.9.2NandFlash操作指令nand

    (1)理解方法和操作方法完全类似于movi指令

    2.1.9.3、内存操作指令:mm、mv、md

    • (1)DDR中没有分区的(只听说过对硬盘、Flash进行分区,没听说过对内存进行分区.......),但是内存使用时要注意,千万不能越界踩到别人了。因为uboot是一个裸机程序,不像操作系统会由系统整体管理所有内存,系统负责分配和管理,系统保证内存不会随便越界。然而裸机程序中,uboot并不管理所有内存,内存是散的随便用的,所以程序员(使用uboot的人)自己不注意就可能出现自己吧自己的数据给覆盖了。(思考:我们为什么把uboot放在0x23E00000地址处?)
    • (2)md就是memory display,用来显示内存中的内容
    • (3)mw 就是memory write,将内容写到内存中
    • (4)mm就是memory modify,修改内存中的某一块,说白了还是写内存(优点:如果需要批量的修改内存,用mm最合适)

    2.1.9.4、启动内核指令:bootm、go

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

    2.1.10、uboot的环境变量1

    2.1.10.1、如何理解环境变量

    2.1.10.2、环境变量如何参与程序运行

    • (1)环境变量有2份,一份在Flash中,另一份在DDR中,uboot开机时一次性从Flash中读取全部环境变量到DDR中作为换金变量的初始值,然后使用过程中都可以用DDR中的这一份,用户可以用saveenv指令将DDR中的环境变量重新写入Flash中去更新Flash中再读一次
    • (2)环境变量在uboot中是用字符串表示的,也就是说uboot是按照字符匹配的方式来区分各个环境变量的。因此

    2.1.10.3、自动运行导数时间:bootdelay

    2.1.10.4、wangluoshezhi ;ipaddr serverip

    • (1)ipaddr是开发板的本地IP地址
    • (2)serverip是开发板通过tftp指令去tftp指令去tftp服务器下载东西是,tftp服务器的ip地址
    • (3)gatewayip是开发板本地的网关地址
    • (4)netmask是子网掩码
    • (5)ethaddr是开发板的本地的网卡的MAC地址

    2.1.11、uboot的常用环境变量2

    2.1.11.1、自动运行命令设置: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;然后重启则会看到启动倒数后自动执行printfenv命令打印出环境变量。这个小实验说明开机自动执行了bootcmd
    • (5)set  bootcmd   ‘movi read kernel 30008000;bootm 30008000’

    2.1.11.2、uboot给kernel传参:bootargs

    • (1)linux内核启动时可以接收uboot给他传递的启动参数,这些启动参数是uboot和内核约定好的形式、内容,linux内核在这些启动参数的直到下完成启动过程。这样的设计是为了灵活,为了内核在不重新编译的情况下可以用不同的方式启动
    • (2)我们要做的事情就是:在uboot的环境变量中设置bootargs,然后bootm命令启动内核是会自动将bootargs传给内核
    • (3)bootargs=console=ttySAC2,115200   root=/dev/mmcblk0p2  rw    init=/linuxrc   rootfstype = ext3

    意义解释:

    console =ttySAC2, 115200  控制台使用ttySAC2(串口2), 波特率115200      

    root= /dev/mmcblk0p2 rw 根文件系统在SD卡端口0设备(iNand)第2分区, 根文件系统是可读可写的

    init=/linuxrc      linux的进程1(init进程)的路径

     rootfstype = ext3     根文件系统的类型是ext3

    • (4)内核传参非常重要,内核移植的时候经常忘记给内核传参,或者给内核传递的参数不对,造成内核启动不起来

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

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

    2.1.11.4、注意:环境变量更改后的保存

    • (1)修改后完成换将变量后一定要保存,否则下次开机更改就没了

    2.1.12、uboot中对flash的DDR的管理

    2.1.12.1、uboot阶段Flash的分区

    • (1)所谓分区,就是说对flash进行分块管理
    • (2)PC机等铲平中国,因为大家都是在操作系统下使用硬盘的,整个硬盘由操作系统统一管理,操作系统会使用文件系统帮我们管理硬盘的空间,这样的管理就保证了文件之间不会互相堆叠。于是乎使用者不用太过在意分区的问题
    • (3)在uboot中是没有操作系统的,因此我们对于flash(相当于硬盘)的管理必须使用分区界定(实际上在uboot中和kernel中都有分区表,分区表就是我们在做系统移植时对flash整体管理分配方法)。有了而这个界定后,我们会在部署系统时按照分区界定的方法来部署,uboot和kernel的软件中也是按照这个分区界定来工作,就不会错。
    • (4)分区方法不是一定的,不是固定的,是可以变动的。但是在一个移植中必须实现设计好定死,一般在设计系统移植时就会定好,定的标准就是uboot必须从flash的其实地址开始存放(也许是扇区0,也许是扇区1,也许是其他,取决于SoC的启动设计),uboot分区的大小必须保证uboot肯定能放下,一般设计位512KB或者1MB(因为一般uboot肯定不足512KB,给再打其实也是可以的,但是浪费了)
    • (5)环境变量:环境变量的分区一般是紧贴着uboot来放的,大小位32KB或者更多一点。
    • kernel:可以紧贴环境变量,大小一般位3MB或者5MB或者其他。
    • rootfs(根文件系统)
    • 剩下的是自由分区,一般kernel启动后将由自由分区挂在到rootfs下使用

    总结:

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

    2.1.12.2、uboot阶段DDR分区

    • (1)DDR分区和flash分区的不同,主要是flash是掉电存在的,而DDR是掉电消失的,因此可以说DDR是每次系统运行时才开始部署使用的。
    • (2)内存的分区主要是在linux内核启动前,linux内核启动之后,内核的内存管理模块会接管内存空间,那时候就不用我们来管了。
    • (3)注意内存分区关键就在于内存中那一块用来干什么必须配合好,以避免各个不同功能使用了同一块内存造成了互相踩踏。譬如说我们tftp 0x23E00000 zImage 区下载zImage到内存的0x23E00000处就会出错,因为这个内存处是uboot的镜像所在。这样下载会导致下载的zImage吧内存中的uboot给冲掉。 
  • 相关阅读:
    JSON
    什么是Jsonp?
    用border做三角形
    前端模块化
    Web 前端
    前端性能优化
    Ajax的原理
    node.js基础语法
    【真·新手初篇】菜鸟们都戳进来看看(欢迎大神指导)
    2019.11.20 开启一天的工作
  • 原文地址:https://www.cnblogs.com/jxjl/p/7371643.html
Copyright © 2011-2022 走看看