电子产业一站式赋能平台

PCB联盟网

搜索
查看: 1540|回复: 0
收起左侧

Uboot简单介绍

[复制链接]

2607

主题

2607

帖子

7472

积分

高级会员

Rank: 5Rank: 5

积分
7472
发表于 2020-12-13 11:56:14 | 显示全部楼层 |阅读模式
Uboot简单介绍, 1、认识uboot

U-Boot,全称 Universal Boot Loader,是遵循GPL条款是一个开源项目,用于启动操作系统内核,操作系统并不是一开机就会自动启动,是要有引导程序的。uboot就是一个这样的开源的引导程序。uboot的官方网站:http://www.denx.de/wiki/U-Boot/SourceCode uboot早期的版本号是这样的 uboot1.4.3,后来是是这样的uboot-2018.11.

2、使用uboot

我们可以在uboot启动过程中进入uboot的控制台底下,使用uboot。所谓的使用uboot也就是使用uboot的环境变量和命令。ping

3、配置编译下载uboot

这里说一下如何配置编译下载uboot,后面的部分为详细讲解uboot源代码的部分。现在最新版本的uboot的配置方法和Linux内核的配置方法是一样的,后面我会有Linux内核配置的文章。

配置

uboot和linux kernel等复杂项目,都不能直接编译,都要先配置才能编译。uboot也要先配置,配置方法是:首先cd进入uboot源码的根目录,然后在根目录下执行:make x210_sd_config(就看Makefile中的那个目标来确定,其实也就是include/configs/目录下的配置文件后面加上_config,比如我这里include/configs/x210_sd.h,所以这里就是make x210_sd_config)。执行配置命令后,如果出现:Configuring for x210_sd board…说明配置好了,如果不是这个是别的说明配置出错了。

编译

编译之前一定要注意检查arm-linux-gcc对不对,检查份2步: 第一步:检查当前编译环境中有没有安装合适的arm-linux-gcc。我们装的是arm-2009q3,因为这个是三星官方、九鼎官方开发uboot时使用的。 第二步:检查当前目录下(uboot根目录)的Makefile中编译器的设置是否正确。在工程的总Makefile中会设置交叉编译工具链的路径和名字,必须确保这个路径和名字和我们自己装的一致,否则编译会出错。 确保了以上2点,即可进行编译。编译很简单,直接make即可。或者可以make -j4 (多线程编译,主机如果是多核心电脑,可以尝试多线程编译,会快一些)

下载

uboot根目录下有一个sd_fusing文件夹,进去之后先检查sd_fusing.sh的执行权限有没有,文件中的bin文件与根目录中生成的bin文件是否一致,文件中的reader_type1=“/dev/sdc“ 中是否是对应的自己的SD卡,make clean,然后make,然后插入SD卡。执行./sd_fusing.sh /dev/sdc,即可

uboot中各个文件夹的介绍

文件介绍

(1).gitignore。git工具的文件,git是一个版本管理工具(类似的还有个svn),这个文件和git有关,和uboot本身无关的,不用去管。 (2)arm_config.mk。后缀是.mk,是一个Makefile文件,将来在某个Makefile中会去调用它。 (3)三个Changelog文件,修改记录文件,该文件记录了这个uboot项目的版本变迁以及每个版本较上个版本修改的记录。正式的项目都有这些记录的。可以直接忽略,主要是给维护uboot的人用的。 (4)config.mk。和arm_config.mk差不多性质。 (5)COPYING。版权声明,uboot本身是GPL许可证的。 (6)CREDITS。鸣谢,里面记录了对uboot有贡献的人,感谢目录。 (7)image_split。一个脚本,看说明是用来分割uboot.bin到BL1的,暂时用不到,先不管。 (8)MAINTAINERS。维护者,就是当前在参与维护uboot源码的社区工作者。 (9)MAKEALL。一个脚本,应该是帮助编译uboot的。 (10)Makefile。这个很重要,是uboot源代码的主Makefile,将来整个uboot被编译时就是用这个Makefile管理编译的,所以我们在下个课程中研究uboot配置编译过程时就要分析这个Makefile。 (11)mk。快速编译的脚本,其实就是先清理然后配置然后编译而已。 (12)mkconfig。这个很重要,是uboot配置阶段的主要配置脚本。uboot的可移植性很大程度就是靠这个配置脚本在维护的。我们在下个课程中研究uboot配置编译过程时就要分析这个配置脚本。 (13)mkmovi。暂时不去管他,一个脚本,和iNand/SD卡启动有关 (14)README。所有的软件都有README,一般拿到一个东西要先读README,这个东西其实就是个简单的使用说明书。 (15)rules.mk。这个文件是我们uboot的Makefile使用的规则,本身非常重要,但是我们不去分析他,不去看他。

文件夹介绍:

(1)api. 硬件无关的功能函数的API。uboot移植时基本不用管,这些函数是uboot本身使用的。 (2)api_examples. API相关的测试事例代码。 (3)board。board是板的意思,板就是开发板。board文件夹下每一个文件都代表一个开发板,这个文件夹下面放的文件就是用来描述这一个开发板的信息的。board目录下有多少个文件夹,就表示当前这个uboot已经被移植到多少个开发板上了(当前的uboot支持多少个开发板)。 (4)common。common是普遍的普通的,这个文件夹下放的是一些与具体硬件无关的普遍适用的一些代码。譬如控制台实现、crc校验的。但是更多的主要是两类: 一类是cmd开头的,是用来实现uboot的命令系统的;另一类是env开头的,是用来实现环境变量的。 (5)cpu。这个目录是SoC相关的,里面存放的代码都是SoC相关初始化和控制代码(譬如CPU的、中断的、串口等SoC内部外设的,包括起始代码start.S也在这里)。里面很多子文件夹,每一个子文件夹就是一个SoC系列。 注意:这个问价是严格和硬件相关的,因此移植时也是要注意的。但是因为这个文件夹内都是SoC有关的,我们自己的开发板和三星的开发板虽然板子设计不同但是SoC都是同一个,因此实际移植时这个目录几乎不用动。 (6)disk。磁盘有关的,没研究过,没用过。 (7)doc。文档目录,里面存放了很多uboot相关文档,这些文档可以帮助我们理解uboot代码。但是因为是纯英文的,而且很杂乱,所以几乎没用。 (8)drivers。顾名思义,驱动。这里面放的就是从linux源代码中扣出来的原封不动的linux设备驱动,主要是开发板上必须用到的一些驱动,如网卡驱动、Inand/SD卡、NandFlash等的驱动。要知道:uboot中的驱动其实就是linux中的驱动,uboot在一定程度上移植了linux的驱动给自己用。但是linux是操作系统而uboot只是个裸机程序,因此这种移植会有不同,让我说:uboot中的驱动其实是linux中的驱动的一部分。 (9)examples。示例代码,没用过。 (10)fs。filesystem,文件系统。这个也是从linux源代码中移植过来的,用来管理Flash等资源。 (11)include。头文件目录。uboot和linux kernel在管理头文件时都采用了同一个思路,就是把所有的头文件全部集中存放在include目录下,而不是头文件跟着自己对应的c文件。所以在uboot中头文件包含时路径结构要在这里去找。 (12)lib_开头的一坨。(典型的lib_arm和lib_generic)架构相关的库文件。譬如lib_arm里面就是arm架构使用的一些库文件。lib_generic里是所有架构通用的库文件。这类文件夹中的内容移植时基本不用管。 (13)libfdt。设备树有关的。linux内核在3.4左右的版本的时候更改了启动传参的机制,改用设备树来进行启动传参,进行硬件信息的描述了。 (14)nand_spl。nand相关的,不讲。 (15)net。网络相关的代码,譬如uboot中的tftp nfs ping命令 都是在这里实现的。 (16)onenand开头的,是onenand相关的代码,是三星加的,标准uboot中应该是没有的。 (17)post。没关注过,不知道干嘛的。 (18)sd_fusing。这里面代码实现了烧录uboot镜像到SD卡的代码。后面要仔细研究的。 (19)tools。里面是一些工具类的代码。譬如mkimage。

uboot主Makefile分析

1、uboot version确定(Makefile的24-29行) (1)uboot的版本号分3个级别: VERSION:主板本号 PATCHLEVEL:次版本号 SUBLEVEL:再次版本号 EXTRAVERSION:另外附加的版本信息 这4个用.分隔开共同构成了最终的版本号。 (2)Makefile中版本号最终生成了一个变量U_BOOT_VERSION,这个变量记录了Makefile中配置的版本号。 (3)include/version_autogenerated.h文件是编译过程中自动生成的一个文件,所以源目录中没有,但是编译过后的uboot中就有了。它里面的内容是一个宏定义,宏定义的值内容就是我们在Makefile中配置的uboot的版本号。 (4)验证方法:自己修改主Makefile中几个Version有关的变量,然后重新编译uboot,然后烧录到SD卡中,从SD卡启动,然后去看启动时uboot打印出来的版本信息,看看变化是不是和自己的分析一致。

2、HOSTARCH和HOSTOS (1)直接在shell中执行uname -m得到i686,得到的值其实你当前执行这个命令的电脑的CPU的版本号。 (2)shell中的    叫做管道,管道的作用就是把管道前面一个运算式的输出作为后面一个的输入再去做处理,最终的输出才是我们整个式子的输出。 (3)HOSTARCH这个名字:HOST是主机,就是当前在做开发用的这台电脑就叫主机;ARCH是architecture(架构)的缩写,表示CPU的架构。所以HOSTARCH就表示主机的CPU的架构。 (4)这两个环境变量是主机的操作系统和主机的CPU架构,得出后保存备用,后面自然会用到。

3、静默编译(50-54行) (1)平时默认编译时命令行会打印出来很多编译信息。但是有时候我们不希望看到这些编译信息,就后台编译即可。这就叫静默编译。 (2)使用方法就是编译时make -s,-s会作为MAKEFLAGS传给Makefile,在50-54行这段代码作用下XECHO变量就会被变成空(默认等于echo),于是实现了静默编译。

4、2种编译方法(原地编译和单独输出文件夹编译) (1)编译复杂项目,Makefile提供2种编译管理方法。默认情况下是当前文件夹中的.c文件,编译出来的.o文件会放在同一文件夹下。这种方式叫原地编译。原地编译的好处就是处理起来简单。 (2)原地编译有一些坏处:第一,污染了源文件目录。第二的缺陷就是一套源代码只能按照一种配置和编译方法进行处理,无法同时维护2个或2个以上的配置编译方式。 (3)为了解决以上2种缺陷,uboot支持单独输出文件夹方式的编译(linux kernel也支持,而且uboot的这种技术就是从linux kernel学习来的)。基本思路就是在编译时另外指定一个输出目录,将来所有的编译生成的.o文件或生成的其他文件全部丢到那个输出目录下去。源代码目录不做任何污染,这样输出目录就承载了本次配置编译的所有结果。 (4)具体用法:默认的就是原地编译。如果需要指定具体的输出目录编译则有2种方式来指定输出目录。(具体参考Makefile 56-76行注释内容) 第一种:make O=输出目录 第二种:export BUILD_DIR=输出目录 然后再make ,如果两个都指定了(既有BUILD_DIR环境变量存在,又有O=xx),则O=xx具有更高优先级,听他的。 (5)两种编译的实现代码在Makefile的78-123行。

5、OBJTREE、SRCTREE、TOPDIR (1)OBJTREE:编译出的.o文件存放的目录的根目录。在默认编译下,OBJTREE等于当前目录;在O=xx编译下,OBJTREE就等于我们设置的那个输出目录。 (2)SRCTREE: 源码目录,其实就是源代码的根目录,也就是当前目录。 总结:在默认编译下,OBJTREE和SRCTREE相等;在O=xx这种编译下OBJTREE和SRCTREE不相等。Makefile中定义这两个变量,其实就是为了记录编译后的.o文件往哪里放,就是为了实现O=xx的这种编译方式的。

6、MKCONFIG(Makefile的101行) (1)Makefile中定义的一个变量(在这里定义,在后面使用),它的值就是我们源码根目录下面的mkconfig。 这个mkconfig是一个脚本,这个脚本就是uboot配置阶段的配置脚本。后面仔细说

7、include $(obj)include/config.mk(133行) (1)include/config.mk不是源码自带的(你在没有编译过的源码目录下是找不到这个文件的),要在配置过程(make x210_sd_config)中才会生成这个文件。因此这个文件的值和我们配置过程有关,是由配置过程根据我们的配置自动生成的。 (2)我们X210在iNand情况下配置生成的config.mk内容为: ARCH = arm CPU = s5pc11x BOARD = x210 VENDOR = samsung SOC = s5pc110 (3)我们在下一行(134行)export导出了这5个变量作为环境变量。所以着两行加起来其实就是为当前makefile定义了5个环境变量而已。之所以不直接给出这5个环境变量的值,是因为我们希望这5个值是可以被人很容易的、集中的配置的。 (4)这里的配置值来自于2589行那里的配置项。如果我们要更改这里的某个配置值要到2589行那里调用MKCONFIG脚本传参时的参数。

8、ARCH CROSS_COMPILE (1)接下来有2个很重要的环境变量。一个是ARCH,上面导出的,值来自于我们的配置过程,它的值会影响后面的CROSS_COMPILE环境变量的值。ARCH的意义是定义当前编译的目标CPU的架构。 (2)CROSS_COMPILE是定义交叉编译工具链的前缀的。定义这些前缀是为了在后面用(用前缀加上后缀来定义编译过程中用到的各种工具链中的工具)。我们把前缀和后缀分开还有一个原因就是:在不同CPU架构上的交叉编译工具链,只是前缀不一样,后缀都是一样的。因此定义时把前缀和后缀分开,只需要在定义前缀时区分各种架构即可实现可移植性。 (3)CROSS_COMPILE在136-182行来确定。CROSS_COMPILE是被ARCH所确定的,只要配置了ARCH=arm,那么我们就只能在ARM的那个分支去设置CROSS_COMPILE的值。这个设置值只要能保证找到那个交叉编译工具链即可,不一定非得是全路径的,相对路径也可以。(如果已经将工具链导出到环境变量,并且设置了符号链接,这样CROSS_COMPILE = arm-linux-就可以) (4)实际运用时,我们可以在Makefile中去更改设置CROSS_COMPILE的值,也可以在编译时用make CROSS_COMPILE=xxxx来设置,而且编译时传参的方法可以覆盖Makefile里面的设置。

9、$(TOPDIR)/config.mk(主Makefile的185行) 编译工具定义(config.mk 94-107行) 包含开发板配置项目(config.mk, 112行) (1)autoconfig.mk文件不是源码提供的,是配置过程自动生成的。 (2)这个文件的作用就是用来指导整个uboot的编译过程。这个文件的内容其实就是很多CONFIG_开头的宏(可以理解为变量),这些宏/变量会影响我们uboot编译过程的走向(原理就是条件编译)。在uboot代码中有很多地方使用条件编译进行编写,这个条件编译是用来实现可移植性的。(可以说uboot的源代码在很大程度来说是拼凑起来的,同一个代码包含了各种不同开发板的适用代码,用条件编译进行区别。) (3)这个文件不是凭空产生的,配置过程也是需要原材料来产生这个文件的。原材料在源码目录的inlcude/configs/xxx.h头文件。(X210开发板中为include/configs/x210_sd.h)。这个h头文件里面全都是宏定义,这些宏定义就是我们对当前开发板的移植。每一个开发板的移植都对应这个目录下的一个头文件,这个头文件里每一个宏定义都很重要,这些配置的宏定义就是我们移植uboot的关键所在。

10、链接脚本(config.mk 142-149行) (1)如果定义了CONFIG_NAND_U_BOOT宏,则链接脚本叫u-boot-nand.lds,如果未定义这个宏则链接脚本叫u-boot.lds。 (2)从字面意思分析,即可知:CONFIG_NAND_U_BOOT是在Nand版本情况下才使用的,我们使用的X210都是iNand版本的,因此这个宏没有的。 (3)实际在boardsamsungx210目录下有u-boot.lds,这个就是链接脚本。我们在分析uboot的编译链接过程时就要考虑这个链接脚本。

11、TEXT_BASE(config.mk 156-158行) (1)Makefile中在配置X210开发板时,在board/samsung/x210目录下生成了一个文件config.mk,其中的内容就是:TEXT_BASE = 0xc3e00000相当于定义了一个变量。 (2)TEXT_BASE是将来我们整个uboot链接时指定的链接地址。因为uboot中启用了虚拟地址映射,因此这个C3E00000地址就等于0x23E00000(也可能是33E00000具体地址要取决于uboot中做的虚拟地址映射关系)。 (3)回顾裸机中讲的链接地址的问题,再想想dnw方式先下载x210_usb.bin然后再下载uboot.bin时为什么第二个地址是23E00000.

12、自动推导规则(config.mk 239-256行) 我们在讲Makefile时提到过自动推导规则

13、Makefile的目标 (1)291行出现了整个主Makefile中第一个目标all(也就是默认目标,我们直接在uboot根目录下make其实就等于make all,就等于make这个目标) (2)目标中有一些比较重要的。譬如:u-boot是最终编译链接生成的elf格式的可执行文件, (3)unconfig字面意思来理解就是未配置。这个符号用来做为我们各个开发板配置目标的依赖。目标是当我们已经配置过一个开发板后再次去配置时还可以配置。 (4)我们配置开发板时使用:make x210_sd_config,因此分析x210_sd_config肯定是主Makefile中的一个目标。

uboot配置过程详解

(1)mkconfig脚本的6个参数 $(@:_config=) arm  s5pc11x  x210  samsung  s5pc110(Makefile中2590行) x210_sd_config里的_config部分用空替换,得到:x210_sd,这就是第一个参数,所以: $1: x210_sd $2: arm $3: s5pc11x $4: x210 $5: samsumg $6: s5pc110 所以,$# = 6 (2)第23行:其实就是看BOARD_NAME变量是否有值,如果有值就维持不变;如果无值就给他赋值为$1,实际分析结果:BOARD_NAME=x210_sd (3)第25行:如果$#小于4,则exit 1(mkconfig脚本返回1) (4)第26行:如果$#大于6,则也返回1. 所以:mkconfig脚本传参只能是4、5、6,如果大于6或者小于4都不行。 (5)从第33行到第118行,都是在创建符号链接。为什么要创建符号链接?这些符号链接文件的存在就是整个配置过程的核心,这些符号链接文件(文件夹)的主要作用是给头文件包含等过程提供指向性连接。根本目的是让uboot具有可移植性。uboot可移植性的实现原理:在uboot中有很多彼此平行的代码,各自属于各自不同的架构/CPU/开发板,我们在具体到一个开发板的编译时用符号连接的方式提供一个具体的名字的文件夹供编译时使用。这样就可以在配置的过程中通过不同的配置使用不同的文件,就可以正确的包含正确的文件。 (6)创建的符号链接: 第一个:在include目录下创建asm文件,指向asm-arm。(46-48行) 第二个:在inlcude/asm-arm下创建一个arch文件,指向include/asm-arm/arch-s5pc110 第三个:在include目录下创建regs.h文件,指向include/s5pc110.h 删除第二个。 第四个:在inlcude/asm-arm下创建一个arch文件,指向include/asm-arm/arch-s5pc11x 第五个:在include/asm-arm下创建一个proc文件,指向include/asm-arm/proc-armv 总结:一共创建了4个符号链接。这4个符号链接将来在写代码过程中,头文件包含时非常有用。譬如一个头文件包含可能是:#include <asm/xx.h> (7)创建include/config.mk文件(mkconfig文件123-129行) (8)创建include/config.mk文件是为了让主Makefile在第133行去包含的。 (9)思考:uboot的配置和编译过程的配合。编译的时候需要ARCH=arm、CPU=xx等这些变量来指导编译,配置的时候就是为编译阶段提供这些变量。那为什么不在Makefile中直接定义这些变量去使用,而要在mkconfig脚本中创建config.mk文件然后又在Makefile中include这些文件呢? 个人理解是为了uboot的可移植性。 (10)理解这些脚本时,时刻要注意自己当前所处的路径。 (11)创建(默认情况)/追加(make -a时追加)include/config.h文件(mkconfig文件的134-141行)。 (12)这个文件里面的内容就一行#include <configs/x210_sd.h>,这个头文件是我们移植x210开发板时,对开发板的宏定义配置文件。这个文件是我们移植x210时最主要的文件。 (13)x210_sd.h文件会被用来生成一个autoconfig.mk文件,这个文件会被主Makefile引入,指导整个编译过程。这里面的这些宏定义会影响我们对uboot中大部分.c文件中一些条件编译的选择。从而实现最终的可移植性。 注意:uboot的整个配置过程,很多文件之间是有关联的(有时候这个文件是在那个文件中创建出来的;有时候这个文件被那个文件包含进去;有时候这个文件是由那个文件的内容生成的决定的) 注意:uboot中配置和编译过程,所有的文件或者全局变量都是字符串形式的(不是指的C语言字符串的概念,指的是都是字符组成的序列)。这意味着我们整个uboot的配置过程都是字符串匹配的,所以一定要细节,注意大小写,要注意不要输错字符,因为一旦错一个最后会出现一些莫名其妙的错误,很难排查,这个是uboot移植过程中新手来说最难的地方。

uboot的链接脚本

(1)uboot的链接脚本和我们之前裸机中的链接脚本并没有本质区别,只是复杂度高一些,文件多一些,使用到的技巧多一些。

(2)ENTRY(_start)用来指定整个程序的入口地址。所谓入口地址就是整个程序的开头地址,可以认为就是整个程序的第一句指令。有点像C语言中的main。

(3)之前在裸机中指定程序的链接地址有2种方法:一种是在Makefile中ld的flags用-Ttext 0x20000000来指定;第二种是在链接脚本的SECTIONS开头用.=0x20000000来指定。两种都可以实现相同效果。其实,这两种技巧是可以共同配合使用的,也就是说既在链接脚本中指定也在ld flags中用-Ttext来指定。两个都指定以后以-Ttext指定的为准。

4、以启动内核为主线分析代码

1、start.S引入

u-boot.lds中找到start.S入口 (1)在C语言中整个项目的入口就是main函数(这是C语言规定的),所以譬如说一个有10000个.c文件的项目,第一个要分析的文件就是包含了main函数的那个文件。 (2)在uboot中因为有汇编阶段参与,因此不能直接找main.c。整个程序的入口取决于链接脚本中ENTRY声明的地方。ENTRY(_start)因此_start符号所在的文件就是整个程序的起始文件,_start所在处的代码就是整个程序的起始代码。

2、不简单的头文件包含 (1)#include <config.h>。 config.h是在include目录下的,这个文件不是源码中本身存在的文件,而是配置过程中自动生成的文件。(详见mkconfig脚本)。 这个文件的内容其实是包含了一个头文件:#include <configs/x210_sd.h>“. (2)经过分析后,发现start.S中包含的第一个头文件就是:include/configs/x210_sd.h,这个文件是整个uboot移植时的配置文件。这里面是好多宏。 因此这个头文件包含将include/configs/x210_sd.h文件和start.S文件关联了起来。因此之后在分析start.S文件时,主要要考虑的就是x210_sd.h文件。 (3)#include <version.h>。include/version.h中包含了include/version_autogenerated.h,这个头文件就是配置过程中自动生成的。里面就一行内容: #define U_BOOT_VERSION “U-Boot 1.3.4“。这里面定义的宏U_BOOT_VERSION的值是一个字符串,字符串中的版本号信息来自于Makefile中的配置值。这个宏在程序中会被调用,在uboot启动过程中会串口打印出uboot的版本号,那个版本号信息就是从这来的。 (4)#include <asm/proc/domain.h>。asm目录不是uboot中的原生目录,uboot中本来是没有这个目录的。asm目录是配置时创建的一个符号链接,实际指向的是就是asm-arm(详解上一章节分析mkconfig脚本时). (5)经过分析后发现,实际文件是:include/asm-arm/proc-armv/domain.h (6)从这里可以看出之前配置时创建的符号链接的作用,如果没有这些符号链接则编译时根本通不过,因为找不到头文件。(所以uboot不能在windows的共享文件夹下配置编译,因为windows中没有符号链接) 思考:为什么start.S不直接包含asm-arm/proc-armv/domain.h,而要用asm/proc/domain.h。这样的设计主要是为了可移植性。因为如果直接包含,则start.S文件和CPU架构(和硬件)有关了,可移植性就差了。譬如我要把uboot移植到mips架构下,则start.S源代码中所有的头文件包含全部要修改。我们用了符号链接之后,则start.S中源代码不用改,只需要在具体的硬件移植时配置不同,创建的符号链接指向的不同,则可以具有可移植性。

3、uboot汇编部分

1、启动代码的16字节头部

(1)裸机中讲过,在SD卡启动/Nand启动等整个镜像开头需要16字节的校验头。(mkv210image.c中就是为了计算这个校验头)。我们以前做裸机程序时根本没考虑这16字节校验头,因为:1、如果我们是usb启动直接下载的方式启动的则不需要16字节校验头(irom application note);2、如果是SD卡启动mkv210image.c中会给原镜像前加16字节的校验头。 (2)uboot这里start.S中在开头位置放了16字节的填充占位,这个占位的16字节只是保证正式的image的头部确实有16字节,但是这16字节的内容是不对的,还是需要后面去计算校验和然后重新填充的。

2、异常向量表的构建 (1)异常向量表是硬件决定的,软件只是参照硬件的设计来实现它。 (2)异常向量表中每种异常都应该被处理,否则真遇到了这种异常就跑飞了。但是我们在uboot中并未非常细致的处理各种异常。 (3)复位异常处的代码是:b reset,因此在CPU复位后真正去执行的有效代码是reset处的代码,因此reset符号处才是真正的有意义的代码开始的地方。

3、有点意思的deadbeef (1).balignl 16,0xdeadbeef.    这一句指令是让当前地址对齐排布,如果当前地址不对齐则自动向后走地址直到对齐,并且向后走的那些内存要用0xdeadbeef来填充。 (2)0xdeadbeef这是一个十六进制的数字,这个数字很有意思,组成这个数字的十六进制数全是abcdef之中的字母,而且这8个字母刚好组成了英文的dead beef这两个单词,字面意思是坏牛肉 (3)为什么要对齐访问?有时候是效率的要求,有时候是硬件的特殊要求。

4、TEXT_BASE等 (1)第100行这个TEXT_BASE就是上个课程中分析Makefile时讲到的那个配置阶段的TEXT_BASE,其实就是我们链接时指定的uboot的链接地址。(值就是c3e00000) (2)源代码中和配置Makefile中很多变量是可以互相运送的。简单来说有些符号的值可以从Makefile中传递到源代码中。 (1)CFG_PHY_UBOOT_BASE     33e00000    uboot在DDR中的物理地址

5、设置CPU为SVC模式 (1)msr    cpsr_c, #0xd3    将CPU设置为禁止FIQ IRQ,ARM状态,SVC模式。 (2)其实ARM CPU在复位时默认就会进入SVC模式,但是这里还是使用软件将其置为SVC模式。整个uboot工作时CPU一直处于SVC模式。

6、设置L2、L1cache和MMU (1)bl    disable_l2cache        // 禁止L2 cache (2)bl    set_l2cache_auxctrl_cycle    // l2 cache相关初始化 (3)bl    enable_l2cache        // 使能l2 cache (4)刷新L1 cache的icache和dcache。 (5)关闭MMU 总结:上面这5步都是和CPU的cache和mmu有关的,不用去细看,大概知道即可。

7、识别并暂存启动介质选择 (1)从哪里启动是由SoC的OM5:OM0这6个引脚的高低电平决定的。 (2)实际上在210内部有一个寄存器(地址是0xE0000004),这个寄存器中的值是硬件根据OM引脚的设置而自动设置值的。这个值反映的就是OM引脚的接法(电平高低),也就是真正的启动介质是谁。 (3)我们代码中可以通过读取这个寄存器的值然后判断其值来确定当前选中的启动介质是Nand还是SD还是其他的。 (4)start.S的225-227行执行完后,在r2寄存器中存储了一个数字,这个数字等于某个特定值时就表示SD启动,等于另一个特定值时表示从Nand启动
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


联系客服 关注微信 下载APP 返回顶部 返回列表