S5PV210之UBOOT-2011.06启动过程解析

发布者:温柔之风最新更新时间:2024-12-18 来源: cnblogs关键字:S5PV210  启动过程 手机看文章 扫描二维码
随时随地手机看文章

//主题:S5PV210之UBOOT-2011.06启动过程解析

//作者:kevinjz2010@gmail.com

//版权:kevinjz原创

//平台:S5PV210 ARMV7 TINY210

//发布日期:2012-05-24

//最后修改:2012-11-27

//注意事项:欢迎转载,但不得在转载的时候擅自修改、删除文章的任何部分

//-------------------------------------------------------------------------------------------------

        本文使用的UBOOT版本:u-boot for tiny210 ver3.1 (by liukun321咕唧咕唧)

        源码地址:http://blog.csdn.net/liukun321/article/details/7438880#comments

        感谢作者liukun321的辛勤劳动啊,呵呵!

一、配置与使用

        1、在系统根目录下的Makefile中的第601行,通过下列语句:

        sinclude$(obj).boards.depend

        $(obj).boards.depend: boards.cfg

                awk'(NF && $$1 !~ /^#/) { print $$1 ': ' $$1 '_config;$$(MAKE)' }' $< > $@

        读取了boards.cfgboards.cfg中关于tiny210_onfig的配置项,其中.boards.depend是隐藏文件;

        2、在Makefile的160行添加: 

        + ifeq($(ARCH), arm)

        + CROSS_COMPILE= arm-none-linux-gnueabi-

        + endif

        这样配置好了默认的编译器

        3、在根目录下执行:

        $make tiny210_config

        $make -j all

        即可在根目录得到tiny210-uboot.bin,可用于SD卡启动和NAND启动;

        4、烧入SD卡的时候使用下面命令:

        $sudodd iflag=dsync oflag=dsync if=tiny210-uboot.bin of=/dev/sdb seek=1

        dd命令用于对SD进行烧写,根据三星手册《S5PV210_iROM_ApplicationNote_Preliminary_20091126》,将tiny210-uboot.bin烧写到,SD卡的第一个Block,保留第0个block不用,每个block=512B。

        5、从SD卡启动后可以就可以将UBOOT烧写到nand里了:

        $tftp 21000000 tiny210-uboot.bin

        $nand erase 0 40000

        $nand write 21000000 0 40000

        6、注意:若要启动linux内核,需要在/arch/arm/mach-s5pv210/include/mach/memory.h中将SECTION_SIZE_BITS 及NODE_MEM_SIZE_BITS改成29,对应一个内存区512M。tiny210和mini210在硬件上挂载内存上是不同的。tiny210将512M内存全部挂在0x20000000开始1区,而mini210将256M挂在0x20000000-0x2fffffff,另外256M挂在0x40000000-0x4fffffff。这也涉及到uboot的config头文件中对210内存控制寄存器的不同设置。要注意!!另外要注意,该UBOOT只能引导uImage,所以在正常编译完内核之后要,要make uImage!

二、启动流程分析

        按照三星《S5PV210_UM_REV1.1》手册上说明的启动流程,S5PV210上电将从IROM处执行固化的启动代码,对时钟等初始化、对启动设备进行判断,并从启动设备中复制BL1(最大16KB)到IRAM(0xd002_0000处,其中0xd002_0010之前的16个字节储存的BL1的校验信息和BL1尺寸)中,并对BL1进行校验,校验OK转入BL1进行执行;BL1继续初始化,并将BL2复制到IRAM中并对其校验,OK后转入BL2;BL2则要进行比较复杂的初始化,包括DRAM的初始化,完成后将OS代码复制到DRAM中,并转入到OS中执行并完成启动引导。

        但是,上述的IRAM只有96K大小,对于日益复杂的uboot来说,肯定是不够的,所以使用UBOOT启动引导的时候,也没全按三星手册上说的执行,具体如下:      

        首先解释一下我认为的BL0、BL1、BL2:

        BL0:是指S5PV210的IROM中固化的启动代码;

        BL1:是指在IRAM中执行的UBOOT的部分代码;

        BL2:是指在内存中执行的的UBOOT的完整代码;

        此版本的UBOOT,其实会编译两个UBOOT.bin,即最终生成的tiny210-uboot.bin包括两部分,前段是spl(重用u-boot中既有的驱动,来生成更小的secondaryprogramloader)文件夹内的tiny210-spl.bin,后段是用于在RAM中执行的完整UBOOT代码。所以学习UBOOT代码是也要两个部分来看。

         1、第一步与三星手册上一致,执行IROM内固化的代码,即BL0,BL0会将存储于启动设备的UBOOT代码的前16KB:tiny210-spl.bin复制到IRAM。(tiny210-spl.bin设置为24KB了,但实际绝不会超过16KB,后面全填充的0,所以拷不完也OK。这里是liukun321为了统一MMC与NAND启动而作的修改,也许改成16K就应该OK了,应为IROM里的代码最多拷贝16K进IRAM嘛,一会改改试试。所以呢实际上执行BL1就是执行tiny210-spl.bin。在UBOOT的代码中并不会看到tiny210-spl.bin和完整的UBOOT代码分开两套文件进行编写,都在同样的文件中,只是通过宏定义来控制执行流程,SPL文件夹内由自己的Makefile文件。

        2、第一步入口程序是/arch/arm/cpu/armv7/start.S中的_start,设置异常向量地址(地址由ARM 架构决定,不能改变),执行reset,进入SVC32模式,并调用cpu_init_crit对ARM的CP15寄存器进行设置,如清空TLB,关闭MMU等,进入/board/samsung/tiny210/lowlevel_init.S中的lowlevel_init中,进行低级初始化,主要是对时钟、内存、串口、nand等进行初始化,为下一步的代码拷贝做准备。

        3、从lowlevel_init出来之后执行call_board_init_f,通过读取OMR_OFFSET寄存器的值,对启动设备进行判断,看看是从mmc启动还是nand启动,判断好后跳入mmc_boot.c或nand_cp.c中,将UBOOT代码拷贝到内存中,地址为_TEXT_BASE:在tiny210.h中定义为0x23e0_0000,换成别的地方也可以,比如3000_0000(注:在跳转到内存中执行之前,所有的语句都是基于PC寻址的,也就是说和代码具体存放的地址没有关系,进行跳转的时候都会计算出跳转目标相对与PC的位置,在跳转过去。)。这里有一个很大的问题,稍后讨论。拷贝完成后直接冲0x23e0_0000出开始执行。那么执行的是什么呢,那先看看拷贝的是什么吧!

        a.nand启动

        在/arch/arm/cpu/armv7/s5pc1xx/nand_cp.c中,第105行:

        for(i = (0x6000>>page_shift); i < (size>>page_shift);i++, buf+=(1<        nandll_read_page(buf,i, large_block);

        }

        指定了拷贝的起始page是nand起始24K之后的第一个PAGE,偏移0x6000的位置,该地址上存储的是完整的UBOOT在RAM中执行的完整启动代码;

        b.mmc启动

        在/arch/arm/cpu/armv7/s5pc1xx/mmc_boot.c中,第49行:

        #defineMOVI_BL2_POS ((eFUSE_SIZE / MOVI_BLKSIZE) +MOVI_BL1_BLKCNT + MOVI_ENV_BLKCNT)

        经计算MOVI_BL2_POS位于第24.5K的位置,也即第49个block,偏移0x6200的位置,该地址上存储的同样是UBOOT在RAM中执行的完整启动代码;

        注:针对第一点提出的将24K偏移改成16K,经过验证:改成16KB并不可行,其实这里不仅仅是BL1的容量的问题,UBOOT_SPL.BIN实际上只有4K不到,所以对于nand启动来说4KB就足够了,但是对于MMC启动来说却不行,因为SD卡的布局并不一样,它在BL1与BL2之间还插入了16KB的ENV区,所以只能是24K,而对NAND的ENV区在BL2之后了。

        所以,无论是MMC启动还是NAND启动,将代码copy到DRAM中并跳转之后,执行的是DRAM中的_start入口函数,重新执行一遍UBOOT,但是一些宏定义已经发生变化,如CONFIG_SPL_BUILD被取消定义,相应的代码也不会执行。

          4、因为第一编执行UBOOT的时候ARM的状态都已经初始化OK了,包括时钟,内存等,第二遍执行时只是跳转到内存中执行了,所以这里判断是否在DRAM中执行,如果在内存中执行,则可以直接跳到call_board_init_f去进行班级初始化。当然,源码并不是这样执行的,而是重新执行RESET、LOWLEVEL_INIT等函数,但我验证过,可以不用执行。有兴趣的同志也可以验证一下。

          5 、进入board_init_f以后将:

          a、对gd_t数据结构(include/asm/global_data.h中定义)进行初始化,并填入相关数据,如内存大小、UBOOT镜像长度等;

          b、对打印CPU信息、UBOOT版本信息等,并对串口、console进一步初始化,输出nand信息,对内存大小进行计算,并打印出来。

 

          c、为UBOOT的重定向设置物理地址,重定向后UBOOT可使用的end地址为0x3fff_0000,

          UBOOT镜像起始地址为0x3ff8_5000。

          打印调试信息:

TLBtable at: 3fff0000

Topof RAM usable for U-Boot at: 3fff0000

Reserving424k for U-Boot at: 3ff85000

Reserving928k for malloc() at: 3fe9d000

Reserving24 Bytes for Board Info at: 3fe9cfe8

Reserving120 Bytes for Global Data at: 3fe9cf70

NewStack Pointer is: 3fe9cf60

第一个疑问:

第201行:

/*Pointer is writable since we allocated a register for it */

gd= (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);

打印CONFIG_SYS_INIT_SP_ADDR的值为0x20ff_ff80,为啥gd_t数据结构会在这个位置,之后好像没有看到重定向gd数据结构的代码!

        6、完成board_init_f中的处理后,转入start.S中的relocate_code函数进行代码搬运及重定向。搬运完成之后,清空BSS后转入board.c中的board_init_r函数执行。

        第二个疑问:

        这里重定向的意义是什么?以前S3C6410或S3C2410的UBOOT中对代码进行重定向是将代码从FLASH或nand或MMC中复制到内存中,但是这里之前的代码已经将UBOOT从nand或mmc复制到了DRAM中,而且目前也是运行在DRAM中。那么为什么在之前的代码中不直接将UBOOT复制到0x3ff8_5000,就可以省去relocate_code步骤?我尝试将CONFIG_SYS_TEXT_BASEdefine为0x3ff8_5000过之后,UBOOT可以启动,但所有的CMD都丢失了,比如:Unknowncommand 'printenv' - try 'help'?目前也没搞明白哪里出问题了!

        7、在board_init_r中,会清空malloc()区的内存,对nand、MMC等进行初始化,执行env_relocate()对环境变量进行初始化(第6步中的问题不知道是不是由于这个函数没有处理好引起的,研究了半天也没发现问题),如果将环境变量保存在NAND中,则会将其读入到内存中来。如果出现什么问题的话,就使用默认的环境变量代替。此步还会对网络、中断等进行初始化。全部初始化完成之后则跳入/common/main.c中的main_loop()中执行,等待用户命令或自动加载内核。

 

三、总结

        本文对S5PV210平台UBOOT的启动流程做了分析,并对一些有疑问的地方做了验证,比如哪一块代码会执行两遍,哪一块代码第二编制行的时候可以省去等。

        验证的方法一般就是电灯或者判断代码执行的位置等。另外,调试过程需要多次的进行烧写,如果每次都敲命令进行烧写的华会很费时间的,所以最好是在/common/main.c中写一个自己的的菜单,并且将烧写任务设为一个命令就行了,这样会轻松一些。


关键字:S5PV210  启动过程 引用地址:S5PV210之UBOOT-2011.06启动过程解析

上一篇:S5PV210启动过程分析
下一篇:S5PV210 Linux字符驱动之PWM蜂鸣器驱动

推荐阅读最新更新时间:2026-03-20 11:21

S5PV210启动过程详解1
内存: SRAM 静态内存 特点就是容量小、价格高、优点是不需要软件初始化直接上电就能用 DRAM 动态内存 特点就是容量大、价格低、缺点就是上电后不能直接使用,需要软件初始化后才可以使用 单片机中:内存需求小、而且希望开发尽量简单,适合全部SRAM PC中: 内存需求大、而且软件复杂,不在乎DRAM的初始化开销,适合全部用DRAM 外存: NorFlash 特点就是容量小、价格高,优点是可以和CPU直接总线式相连,CPU上电后可以直接读取,所以一般用作启动介质 NandFlash 特点就是容量大、价格低、缺点就是不能直接总线式访问,也就是说不能上电CPU直接读取,需要CPU先运
[单片机]
S5PV210启动过程分析
一、三星官方推荐方式 1、数据手册《S5PV210_iROM_Application_note》中截取: (1)第一步:执行BL0。执行完成后调用BL1 (2)第二步:执行BL1。加载BL2到SRAM中 (3)第三步:执行BL2。初始化DDR。 (4)第四步:将OS加载到DDR中 (5)第五步:操作系统在DDR中启动运行 2、详细分析 (1)BL0:这一段代码是三星官方出厂时烧录的一段代码,存在SoC内部的iROM(就是SROM,容量64KB)中。 (2)BL1:启动代码的前16KB,负责初始化NandFlash和读取启动代码的后面80KB代码到SRAM中运行。 (3)BL2:初始化DRAM,将OS读取到DRAM中,最
[单片机]
<font color='red'>S5PV210</font><font color='red'>启动</font><font color='red'>过程</font>分析
嵌入式开发学习(2)<S5PV210启动过程详解>
基本概念: 内存:   SRAM 静态内存 特点:容量小、价格高,优点:不需要软件初始化,上电就能用。   DRAM 动态内存 特点:容量大、价格低,缺点:上电不能用,需要软件初始化。   单片机中:内存需求量小,而且希望开发尽量简单,适合全部用SRAM。   嵌入式系统:内存需求量大,而且没有NorFlash等可启动介质。(介于单片机和PC机中间)。   PC机:内存需求量大,而且软件复杂,不在乎DRAM的初始化开销,适合全部用DRAM。 外存:   NorFlash 容量小,价格高,可以和cpu总线式相连,上电cpu直接能读取。所以一般用来作启动。   NandFlash(跟硬盘一样,容量大,价格低,缺点:不能总线式访问,不能
[单片机]
嵌入式开发学习(2)<<font color='red'>S5PV210</font><font color='red'>启动</font><font color='red'>过程</font>详解>
S5PV210启动过程详解
S5PV210芯片简介: S5PV210是ARM架构(crotex_A8内核)的32位芯片,理论上支持4G的内存空间,但因为是统一编址,实际只支持1.5G的内存,内置了iROM和iRAM。启动方式由下图所示: 启动方式详解: (1)上电后首先从iROM中读取预先设置的代码BL0,BL0会初始化芯片内部,包括CPU的时钟、关看门狗、初始化栈等等。这一段代码时出厂的时候内置的,因为不知道将来芯片会接哪些型号的外设,所以没法去初始化外设,都是初始化芯片内部。BL0其中有一个特别重要的功能,就是判断启动模式,也就是判断BL1要通过哪种存储介质读取,比如图中有NorFlash、eSSd、NandFlash、USB等。Soc判断启动模式
[单片机]
<font color='red'>S5PV210</font>的<font color='red'>启动</font><font color='red'>过程</font>详解
06-S3C2440学习之移植2012u-boot到S3C2440(移植过程二)支持NAND启动
说明: 原来的代码在链接时加了 -pie 选项, 使得u-boot.bin里多了 *(.rel*) , *(.dynsym) (*(.rel*) , *(.dynsym)这些地址信息用于实现UBOOT可以被拷贝到任何地方,更新地址信息),但使得程序非常大,结构复杂,不利于从NAND启动(重定位之前的启动代码应该少于4K)。所提去掉了pie功能。 (1)使用一下之前写的init.c 拷贝到2440单板下: 修改init内容为: /* NAND FLASH控制器 */ #define NFCONF (*((volatile unsigned long *)0x4E000000)) #define
[单片机]
<font color='red'>06</font>-S3C2440学习之移植2012u-boot到S3C2440(移植<font color='red'>过程</font>二)支持NAND<font color='red'>启动</font>
uboot总结:uboot配置和启动过程1(主Makefile分析)
说明:文件位置:在uboot的目录下,文件名为:Makefile 从文件的头部开始分析 1、24-29行,配置uboot的版本信息。 VERSION = 1 PATCHLEVEL = 3 SUBLEVEL = 4 EXTRAVERSION = U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) VERSION_FILE = $(obj)include/version_autogenerated.h 2、主机的环境信息(比如:我现在是虚拟机的Ubuntu10.04下开发的,就是i686,linux。) 3、配置为静默编译的设置(使用方法:m
[单片机]
OK6410启动配置过程(详细信息)
硬件平台:OK6410开发板 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 KK U-Boot 1.1.6 (Sep 19 2014 - 10:00:03) for SMDK6410 **************************************** ** u-boot 1.1.6
[单片机]
STM32上电启动过程分析
单片机上电后执行的第一段代码 1.初始化堆栈指针 SP=_initial_sp 2.初始化 PC 指针=Reset_Handler 3.初始化中断向量表 4.配置系统时钟 5.调用 C 库函数_main 初始化用户堆栈,然后进入 main 函数。 在正式讲解之前,我们需要了解STM32的启动模式。 STM32的启动模式 手册可以在Keil中跳转查看 STM32的三种启动模式 首先要讲一下STM32的启动模式,因为启动模式决定了向量表的位置,STM32有三种启动模式: 1. 主闪存存储器(Main Flash memor
[单片机]
STM32上电<font color='red'>启动</font><font color='red'>过程</font>分析
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved