Uboot和系统移植

来源:互联网 发布:windows ce 6.0 编辑:程序博客网 时间:2024/05/17 23:50

Author: sx                                                          E-mail:598726409@qq.com

资料整理于自己的笔记(有许多的图片和代码块没有添加,后面会慢慢补齐),也有些是博客之类 ,如有侵权,请及时联系我,我会及时删除。因为都是手码的,可能会有些错别字,理解有误的地方请联系我,以便及时修改


<Uboot的前传 >

计算机系统的组成:

CPU(控制器/运算器)   + 内存(DDR /SDRAM ) +外存(硬盘、flash)

嵌入式系统的启动过程:Uboot存放在norflash中,开机从norflah启动Uboot、uboot去初始化DDR,OS存放flash中,DDR初始化结束以后,将OS加载到DDR中去运行,这是就启动了操作系统。

简而言之,分为两个部分

(1)Uboot加载启动操作系统

(2)操作系统启动以后,加载rootfs(跟文件系统)

<自己动手安装交叉编译工具链2>

1.4.4.自己动手安装交叉编译工具链2

1.4.3.1、环境变量的意义

环境变量就是操作系统的全局变量。每一个环境变量对操作系统来说都是唯一的,名字和所代表的意义都是唯一的。linux系统可以有很多个环境变量。其中有一部分是linux系统自带的,还有一些是我们自己来扩充的。我们这里涉及到的一个环境变量是

PATH。PATH这个环境变量是系统自带的,它的含义就是系统在查找可执行程序时会搜索的路径范围。

1.4.3.2、将工具链导出到环境变量

exportPATH=/usr/local/arm/arm-2009q3/bin:$PATH

在一个终端中执行以上命令后,该终端中就可以直接使用arm-linux-gcc了,但是只要关掉这个终端再另外打开一个立马就不行了。原因是我们本次终端中执行时的操作只是针对本终端,以后再打开的终端并未被执行过这个命令所以没导出。

解决方案是在~/.bashrc中,添加export PATH=/usr/local/arm/arm-2009q3/bin:$PATH 即可。

注意:我们导出这个环境变量是在当前用户,如果你登录时在其他用户下是没用的。

 

1.4.3.3、为工具链创建arm-linux-xxx符号链接

lnarm-none-linux-gnueabi-addr2line -s arm-linux-addr2line

< Uboot是干嘛的 >

(1)原始目的:启动操作系统

启动操作系统中,有一项也很重要,就是给内核传参,依靠传参来配置内核启动的细节。

(2)部署整个操作系统(部署就是把响应的东西放到该在的地方,比如OS在flash中,Uboot把它加载到DDR中去运行)根文件系统的布置,Uboot可以布置操作系统(烧录系统镜像。)

(3)操作flash等板子上的驱动

Uboot支持SOC级,和版级的硬件驱动,比如在Uboot刷系统中,LCD屏幕上显示了一个进度条,在开机自启动的时间,自动提供了一个Shell界面(SOC),如果在启动时需要配置网络之类的,那么就要包含驱动网卡芯片的功能。

(4)提供一个命令行界面供人操作

< Uboot必须解决的问题 >

(1)必须能自动启动,给内核传参

(2)部署整个操作系统

(3)驱动版级和SOC的硬件

< Uboot的生命周期 >

Uboot本质上是一个裸机程序,裸机程序和操作系统不同,裸机程序只能单个运行,操作系统可以多进度运行,重复运行,而uboot不可以,这也是为什么Uboot可以ping通主机而主机不能Ping通uboot的原理,因为Uboot内不具备接收数据包的功能。

<Uboot的入口和出口 >

Uboot的入口就是自动启动,它的终极目标就是启动操作系统,如果它没有成功启动操作系统,就会一直打转,知道启动为止,而一旦操作系统启动代码开启,这就是它的出口,它就死了。

 

Uboot的两个关键点:

(1)命令

(2)环境变量

< Uboot常用命令 >

(1)print   = printenv 打印环境变量

(2)set    = setenv name value 设置环境变量

(3)save 保存更改(这里有一个机制,uboot中的环境变量都是存放在Flash中的,所以可以实现掉电保存,而在uboot中修改的环境变量是在内存中,所以当我们需要重启依旧保持环境变量的修改,那么就需要save)

(4)ping:

(1)umask:需要设置为同一个子网掩码255.255.255.0

(2)保证Uboot和虚拟机/PC机在同一个网段

(3)虚拟机的网络需要设立为桥接模式

(4)虚拟机的菜单中有个“虚拟网络编辑器”,这里面要设置为桥接到有线网卡。(默认是自动的,自动的一般会影响ping通。因为电脑现在一般都有2个网卡:一个有线的一个无线的。如果选了自动,那么虚拟机会自动桥接到无线网卡上,但是我们却是通过有线网卡来连接开发板的,自然ping不通)

如图所示

 

(5)tftp

Uboot有两种部署镜像的方法

(1)fastboot 装裸机驱动部分有教程

(2)tftp 利用在Ubuntu中的tftp工具,发送

安装和配置教程在(嵌入式开发环境搭建中有详述)

注意:

(1)安装好以后会在Ubuntu中有一个文件夹(我的是tftpboot),我们把需要传输的镜像放在这个文件夹下,然后去uboot去pingUbuntu,如果通了,就可以使用命令

tftp0x30000000 name 来传输了

(2)传输时是依靠字符来匹配文件,所以命令中的字符一定要匹配

(3)传输的地址要有效,比如S5PV210中是0x30000000~0x50000000

(6)movi指令族

 

(7)读写DDR指令

md[.b, .w, .l] address [# of objects]

读取一个地址的内容

可以指定读取的字节数.b .w .l 分别对应不同的字节数

mw[.b, .w, .l] address value [count]

向一个地址写内容

mm[.b, .w, .l] address

向一个地址写内容,但是是地址会自动向下增加,输入Y结束

(7)bootcmd

开机自动启动的环境变量,是一个命令集合,所以在设置bootcmd时需要加' '双单引号。

(8)bootarg

前面说过了在bootm启动系统时需要给内核传参,这里的Bootarg就是给内核的传参

注意:如果在启动时启动不起来,那么就需要查询环境变量,以及bootarg,仔细观察是否有写错,修改完环境变量以后要记得保存。

 

<Uboot对flash和DDR的分区>

(1)Uboot对flash的分区

flash是掉电仍然在的,所以用来存储Uboot.kernel.。。。。

Uboot规定必须在flash的开头,因为作为启动代码

环境变量贴着Uboot分区

剩下的分区如图所示

除了Uboot必须在开头以外,其它的分区相对位置是可以改变的。

(2)Uboot对DDR的分区

DDR相对于Flash是掉电消失的,所以对DDR的分区管理是在内核启动之前的,当操作系统内核启动起来之后,会接手对内存的管理,我们只需要在对DDR分区是注意不要内存踩踏即可。

<Uboot的初体验 >

<配置 >

在编译U-boot之前要对Uboot进行配置

(1).make  执行:make x210_sd_config

(2).查看交叉编译工具链是否正确(路径/版本)

在Uboot的makefile 147行

CROSS_COMPILE= ?????查看行代码,如果不正确就需要按照路径装交叉编译工具链

 

<编译 >

make  make -j4(多线程编译)

<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使用的规则,本身非常重要,但是我们不去分析他,不去看他。

 

总结:以上这些文件中,对我们比较重要,需要认真看的有2个:mkconfig和Makefile。一个负责uboot的配置,一个负责编译。

<Uboot各文夹介绍>

(1)api.硬件无关的功能函数的API。uboot移植时基本不用管,这些函数是uboot本身使用的。

(2)api_examples. API相关的测试事例代码。

(3)boardboard是板的意思,板就是开发板。board文件夹下每一个文件都代表一个开发板,这个文件夹下面放的文件就是用来描述这一个开发板的信息的。board目录下有多少个文件夹,就表示当前这个uboot已经被移植到多少个开发板上了(当前的uboot支持多少个开发板)。

问题一:思考uboot如何支持多套开发板,如何具有可移植性

问题二:board下有这么多文件夹,究竟如何确定具体使用的是哪一个?uboot在配置阶段会有一些手段帮助我们来确定具体使用的是board目录下的哪一个文件夹。(想想为什么不能直接编译而要先配置)

问题三:开发板越来越多,board目录下文件夹越来越多不方便管控

Q1:Uboot之所以支持多套开发板,是因为在每移植好一块开发板以后会在board目录下放上这个开发版的信息,表示支持了这个开发板

Q2:之所以不能直接编译Uboot的原因就在于此,我们不知道Uboot需要的是哪一部分代码,配置就是对broad下支持的开发板文件夹进行一个索引

Q3:开发板越来越多,所以后来在board中添加了一个文件夹,用来标识开发板的IC厂商,然后在把开发板的信息放到相应的厂商文件夹下,那么为了向前兼容,之前的开发板信息不会改变,因为一旦改变之前的代码就不能用了(路径)

注意:

在Uboot配置阶段,其实就是在mkconfig脚本和makefile中配置关键的路径,找到相应的文件(已解决兼容性问题)

 

(4)commoncommon是普遍的普通的,这个文件夹下放的是一些与具体硬件无关的普遍适用的一些代码。譬如控制台实现、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。

 

总结:文件夹里面比较重要的,后面会分析涉及到的有:board、common、cpu、drivers、include、lib_arm、lib_generic、sd_fusing

<Uboot编译和配置详解>

TIPS

在shell中  ` cmd `可以执行该命令

shell  uname 也可以执行命令

 

makefile分析(环境变量)

1.Uboot version(uboot的版本号)

 

 

 

 

 

 

2.HOSTARCH(主机的架构号)

shelluname -m :显示主机的架构号 ix86

sed-e s/i.86/i386/   以/为分隔符替换字符串 (.)是通配符

 

 

 

 

 

 

 

 

 

 

 

3.HOSTOS(主机操作系统)

shelluname -s  : 显示主机的操作系统

tr'[:upper:]' '[:lower:]' 将大写字符串转换为小写的字符串

cygwin是早期的虚拟Linux

export就是导出环境变量

 

4.静默编译

makefile后加的参数去找字符串,又没有s,然后和空去做对比

如果是空则成立,就是非静默的,如果makeflag中有s,则XECHO标志为空,即为静默编译

 

5.原地编译和单独输出编译

两种方法:

1) AddO= to the make command line

#'make O=/tmp/build all'

2) Setenvironement variable BUILD_DIR to point to the desired location

#'export BUILD_DIR=/tmp/build'

#'make'

 

 

 

 

 

 

 

 

这句指令就表面,在make时加 o=参数会覆盖掉环境变量导出的路径

注意:

1)在配置时就需要 make O=/.....  [ 配置指令]

(2)编译时make O=/....

如果报错信息中是某个文件夹为空无法创建,则需要我们手动创建。

 

 

 

 

 

 

OBJTREE生产的目标文件树。SRCTREE源代码树,决定我们单独输出编译的输出路径的

 

6.OBJTREE / SRCTREE  MKCONFIG

OBJTREE:就是编译生产的.o根目录

SRCTREE:就是源代码根目录

如果OBJTREE不等于SRCTREE,那么就证明是单独输出编译的

如果OBJTREE等于SRCTREE,那么就是原地编译的

obj= OBJTREE  src = SRCTREE

 

MKCONFIG是SRCTREE下的一个配置脚本

 

7./ CROSS_COMPLI / ARCH

/ include $(obj)include/config.mk

include$(obj)include/config.mk 

:obj编译输出的文件夹,文件夹下的include/config.mk  是一个配置文件

从这个脚本导出了一些环境变量

 

 

 

 

 

ARCH:芯片架构

如果是arm架构,那么交叉编译工具链就是相对应的前缀为arm-none-linux-guneabi-(默认没有导入到Linux系统环境变量,以及符号链接)如果有导入linux系统环境变量和符号链接则是arm-linux-.

 

7.TOPDIR := $(SRCTREE)

TOPDIR:顶层目录(源代码目录)

 

 

 

 

主makefile加载了顶层目录下的一个mk文件

config.mk (vip)

这个文件是辅助配置文件(这里包含了一个非常重要的配置头文件)

编译工具定义(config.mk94-107行)

包含开发板配置项目(config.mk,112行)

(这里包含了一个非常重要的配置头文件)

注意:这里的autoconf.mk是自动生成的,所以是在配置生成的。所以在非编译时是没有的(遇到auto之类的就需要在linux编译好的文件夹下寻找)

根据autoconfig.mk中的参数,判断uboot使用哪个链接脚本

TEXT_BASE:

指定了一个链接地址(在配置阶段)

路径:$(obj)board/samsung/x210/config.mk

 

内容就是TEXT_BASE= c3e00000

 

config.mk中的自动推断:

8.剩下的一些makefile

292~351:利用u-boot为以来生成一些u-boot.bin之类文件

<Uboot配置过程>

x210_sd_config的依赖为unconfig(未配置的)所以重复配置

MKCONFIG是主目录下一个脚本文件,这里开始对它传参

根据上面给MKCONFIG传参$# = 6

($(@:_config=)为目标 x210_sd_config中的_config替换为 空

所以$1就是x210_sd

[ $1 =x210_sd ]     [ $2 = arm ]   [ $3= s5pc11x ]

[ $4 =x210 ]  [ $5 = sansung ]  [ $6 = s5pc110 ]

$# = 6,所以这段代码直接break 

注意:shell中上语句中的break,不是case的break,shell中的case是不需要break的,所以这里跳出的是while循环

这样的语句相当于一个简易版的if,因为之前的BOARD_NAME上来就被置空了。所以前句为fause,后面的执行

下面的指令就是传参的个数限定在4~6之内,否则就exit

剩下的33~118就是在创建符号连接

第一个:在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>  -->  asm-arm/...

 

 

(1)创建include/config.mk文件(mkconfig文件123-129行)

(2)创建include/config.mk文件是为了让主Makefile在第133行去包含的。

(3)思考:uboot的配置和编译过程的配合。编译的时候需要ARCH=arm、CPU=xx等这些变量来指导编译,配置的时候就是为编译阶段提供这些变量。那为什么不在Makefile中直接定义这些变量去使用,而要在mkconfig脚本中创建config.mk文件然后又在Makefile中include这些文件呢?

(4)理解这些脚本时,时刻要注意自己当前所处的路径。

(5)创建(默认情况)/追加(make -a时追加)include/config.h文件(mkconfig文件的134-141行)。

(6)这个文件里面的内容就一行#include <configs/x210_sd.h>,这个头文件是我们移植x210开发板时,对开发板的宏定义配置文件。这个文件是我们移植x210时最主要的文件。

(7)x210_sd.h文件会被用来生成一个autoconf.mk文件,这个文件会被主Makefile引入,指导整个编译过程。这里面的这些宏定义会影响我们对uboot中大部分.c文件中一些条件编译的选择。从而实现最终的可移植性。

<Uboot的链接脚本 >

ENTRY:

ALIGEN(4):四字节对齐

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

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

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

(4)uboot的最终链接起始地址就是在Makefile中用-Ttext 来指定的,具体参见2.4.5.2节,注意TEXT_BASE变量。最终来源是Makefile中配置对应的命令中,在make xxx_config时得到的。

(5)在代码段中注意文件排列的顺序。指定必须放在前面部分的那些文件就是那些必须安排在前16KB内的文件,这些文件中的函数在前16KB会被调用。在后面第二部分(16KB之后)中调用的程序,前后顺序就无所谓了。

(6)链接脚本中除了.text  .data .rodata .bss段等编译工具自带的段之外,编译工具还允许我们自定义段。譬如uboot总的.u_boot_cmd段就是自定义段。自定义段很重要。

 

<Uboot启动的第一阶段 >

 

任何工程的起点

在C语言中是以main.c开始的,而在汇编中,是以链接脚本中的ENTRY ...开始的所以需要从链接脚本入手

找到以后,用SI搜索这个标号(crtl + /)

ONENAND之类不是我们需要的,所以由此找到了这个标号

 

 

 

start.S分析1.开局头文件包含

< config.h >-->include下是在mkconfig自动生成的

其实包含了是这个头文件,这个头文件中包含了许多的配置信息

 

 

 

 

<version.h>-->在incude下 会自动生产一个"version_autogenerated.h"文件,这个文件是(主makefile)自动生成的。里面是u-boot的版本信息

 

 

 

<asm/proc/domain.h>  -->符号链接

asm  -> asm-arm(ARCH)

proc->   proc-armv

所以其实是

include下 asm-arm/proc-armv

这样设计的原因是为了兼容性

 

 

start.S的向下继续分析(1)

就是16字节的校验头(有些CPU没有)

.word= 就是定义一个4字节的数据(变量)

以16字节对齐0xdeadbeef是句玩笑

 

 

 

这是一种汇编的技巧,定义一个标号,再定义一个变量,变量中存放一个地址,然后在使用的时间去ldr加载这个标号,就相当于加载这个地址

 

 

 

 

 

 

start.S的向下继续分析(2)

 

 

UBoot运行的物理地址

 

清楚bss

 

设置CPSR的状态(工作模式,中断禁止)

reset后CPU自动进入SVC模式(CPSR_C就是设置CPSR的0~7位)禁止I F  设置SVC模式(使程序不以来于硬件设定),进入ARM状态

注意:Uboot整个工作程序中都工作在SVC模式,特权模式

 

 

l2cache的初始化(流程:关闭->设置->使能)

 

 

从OMPIN读取启动方式。

 

 

设置栈并调用lowlevel_init函数

TIPS

SP:在调用函数前初始化栈,主要原因是在被调用的函数内还有再次调用函数,而BL只会将返回地址存储到LR中,但是我们只有一个LR,所以在第二层调用函数前要先将LR入栈,否则函数返回时第一层的返回地址就丢了。

lowlevel_init:低层初始化,CPU,底层一些非常重要的初始化

 

在跳转lowlevel_init函数时,注意要查看路径是否正确,因为Uboot的可移植性,内置了很多的一样名字的代码,而对应的开发板不同。

比如在210中路径对于的就是这个。

Pushlr  :就是给lr压栈保存

Lr 压栈保存 ->

检查复位状态(冷启动/热启动(休眠))->

冷启动:CPU上电,此时DDR,是需要初始化的

休眠:此时只有CPU在工作,其余的外设都关闭了,但是是初始化过的,所以不需要初始化。

关看门狗->在CPU上电后,在启动阶段需要关闭看门狗,因为如果不关闭看门狗,当看门狗计数器的数值计数完毕后,会产生复位(中断),打断启动。

内存的一些初始化->

PS_HOLD(供电琐存)->

 

 

检查代码运行在DRAM(DDR ) 中还是运行在IRAM中,(冷热启动),决定是否进行始终和内存的初始化。

原理和裸机部分一致,通过对比链接地址和运行地址是否相同。

区别:这里判断的是PC,所以将地址的部分高低位都清了0,只对有用部分进行对比。

beq:1f  1是标号,f是向下查找, b是向后查找

 

 

 

 

 

跳转到DRAM初始化程序(和裸机部分基本一致)

 

 

 

 

 

Uart的初始化程序

 

 

返回

 

 

 

 

第二次栈设置到DDR中

当代码在Ram中就需要重定位了,至此,第一阶段基本结束;

 

(1)D0037488这个内存地址在SRAM中,这个地址中的值是被硬件自动设置的。硬件根据我们实际电路中SD卡在哪个通道中,会将这个地址中的值设置为相应的数字。譬如我们从SD0通道启动时,这个值为EB000000;从SD2通道启动时,这个值为EB200000

(2)我们在start.S的260行确定了从MMCSD启动,然后又在278行将#BOOT_MMCSD写入了INF_REG3寄存器中存储着。然后又在322行读出来,再和#BOOT_MMCSD去比较,确定是从MMCSD启动。最终跳转到mmcsd_boot函数中去执行重定位动作。

(3)真正的重定位是通过调用movi_bl2_copy函数完成的,在uboot/cpu/s5pc11x/movi.c中。是一个C语言的函数

(4)copy_bl2(2,MOVI_BL2_POS, MOVI_BL2_BLKCNT,

CFG_PHY_UBOOT_BASE,0);

分析参数:2表示通道2;MOVI_BL2_POS是uboot的第二部分在SD卡中的开始扇区,这个扇区数字必须和烧录uboot时烧录的位置相同;MOVI_BL2_BLKCNT是uboot的长度占用的扇区数;CFG_PHY_UBOOT_BASE是重定位时将uboot的第二部分复制到DDR中的起始地址(33E00000).

虚拟地址映射:

MMU单片在CP15协处理器中进行控制,也就是说要操控MMU进行虚拟地址映射,方法就是对cp15协处理器的寄存器进行编程。

MMU提供了一个虚拟地址映射层,用来实现虚拟地址映射。

(1)提供了内存管理

(2)cache的实现(cache的工作和虚拟地址映射有关系)

总结:

Uboot的第一阶段:

(1)构件异常向量表

(2)设置CPSR的状态(SVC,I/F终端禁止)

(3)PS_HOLD供电锁存

(4)OMPing启动个引脚读取

(5)第一次设置栈,进入low_lever_init(CPU相关初始化)

1):检验启动状态(冷热启动)

2):IO状态

3):关看门狗

4):判断当前代码位置(在SRAM中还是DDR中)

1):选择是否初始化时钟

2):选择是否初始化内存

5):初始化串口

 

Uboot的第二阶段:

(1)初始化外设

(2)进入main_loop  - -> 启动内核

最近准备笔试面试,休息了慢慢补全