uboot第一阶段详细分析

原文:uboot第一阶段详细分析

作者:程老师,华清远见嵌入式学院讲师。

uboot的第一阶段设计的非常巧妙,几乎都是用汇编语言实现的,下面我们一起来看看它的精妙之处吧!

首先我们来看一下它的链接脚本,通过它我们可以知道它整个程序的各个段是怎么存放的。

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm",
"elf32-littlearm")
        OUTPUT_ARCH(arm)
        ENTRY(_start)
        SECTIONS
        {
                .
= 0x00000000;

. =
ALIGN(4);
                .text
:
                {
                        cpu/arm920t/start.o        (.text)
                        *(.text)//所有的其他程序的代码段以四字节对齐放在它后面
                }

. =
ALIGN(4);
                .rodata
: { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }//只读数据段

. =
ALIGN(4);
                .data
: { *(.data) }//指定读/写数据段

. =
ALIGN(4);
                .got
: { *(.got) }//指定got段,got段式是uboot自定义的一个段,非标准段

. =
.;
                __u_boot_cmd_start
=
.;//把__u_boot_cmd_start赋值为当前位置,即起始位置
                .u_boot_cmd
: { *(.u_boot_cmd)
}//指定u_boot_cmd段,uboot把所有的uboot命令放在该段
                __u_boot_cmd_end
= .;//把 __u_boot_cmd_end赋值为当前位置,即结束位置

. =
ALIGN(4);
                __bss_start
=
.;//__bss_start赋值为当前位置,即bss段得开始位置
                .bss
(NOLOAD) : { *(.bss) . = ALIGN(4);
}
                _end
=
.;//把_end赋值为当前位置,即bss段得结束地址
        }

从它我们可以看到,uboot运行的第一个程序是cpu/arm920t/start.S,其他的都有注释,就不多说了。

下面我们来看看在fs2410上通过nor flash启动,u-boot的启动流程:

电源一上电之后,pc指针从0x00000000 地址开始执行,也就是说这个时候程序跑在nor flash里面(别忘记,nor
flash这个时候接在0x00000000地址,它是可以执行程序的只是速度没有在ram里面执行快)

这个时候有人可能会问那s3c2410片内的4kRam映射到哪呢?通过查看芯片手册这个时候它在0x40000000,如下图:


(使用NOR FLASH启动,设备地址映射图)

现在我们知道是那个程序在哪里存储,从哪个地址运行,下面我们来看看这段程序的汇编代码:

在这里我们知道运行的第一条指令是b
start_code,呵呵!看到这段代码的时候许多人都认为_start的值是0x00000000,为什么是这个地址呢?
因为连接脚本上指定了。真的是这样吗?我们来看看我们编译好之后,在u-boot目录下有个System.map,这里面有各个变量的值,如下图:

哈哈,_start的值怎么会是0x33f80000?这是因为在顶层的Makefile里面我们指定了它的连接地址。

看到那个 -o
u-boot了吗,就是通过它生成ELF格式的u-boot的,里面有个LDFLAGS变量,它是什么呢,我们继续往下面看:

(顶层的config.mk里面有这个变量的说明)

看到了没有,LDFLAGS里面除了指定链接脚本,如果TEXT_BASE不等于空,还加上了-Ttext$(TEXT_BASE),TEXT_BASE的值是多少呢?我们可以在board/samsung/smdk2410/config.mk里面有定义,它的值为0x33f80000。这样我就可以知道为什么System.map的地址都是0x33f80000。

好我们来看第一条汇编指令b start_code,从System.map文件我们可以知道,这条指令相当于b
0x33f80050。"0x33f80050"?你是否有疑问,这个时候内存还没有初始化呢,怎么能跳到内存中去了(sdram的起始地址0x30000000)。呵呵,其实不是这样的。还记得b指令是相对跳转指令吗,它和代码的位置是无关的,这种精妙的设计才使得后面的指令能继续的执行。

下面我们继续来看它的汇编指令:

呵呵,这段汇编代码很好理解,就是设置CPU为 管理模式。

这段汇编代码就不分析了,这是跟atmel相关的,我不管它,继续下面:

这段汇编代码也很好理解,就是关掉看门狗,然后关掉所有中断。

哦哦,设置时钟,还记得一上电FCLK是多少吗,只有12MHZ。

呵呵!跳转指令,我们来看看它做了什么,这样我们先从名字上来猜猜它是什么意思?cpu初始化,初始化什么呢?继续向下看:

呵呵,有英文注释,清cache,关闭MMU。都是用协处理指令实现的,如果看不懂,可以看看协处理器指令。多了解一点就多知道一点,不是吗?

从上面可以看到,还有一次跳转bl
lowlevel_init。这里面有干了一些什么呢,我们可以到board/samsung/smdk2410/
lowlevel_init.S去看。呵呵,这里我就不截图了,其实我们只有知道,它在这里面干了初始化内存操作。

继续往下面看:

呵呵,终于到重点部分了,代码重定向。下面我们来看看它到底是怎么重定向的:

Adr r0,_start

这条汇编指令的意思就是把_start当前代码存储的地址赋给r0,假如这段代码存储在SDRAM里面,那么r0的值就是0x30000000。现在这段代码存储在NOR
Flash里面,所以r0的值就是

0x0000000
        Ldr
r1,_TEXT_BASE

这条汇编指令的意思是把_TEXT_BASE的值作为地址,把这个地址的内容赋给r1,从下面可以知道:

_TEXT_BASE里面存储的内容是TEXT_BASE,也就是0x33f80000,所以r1的值就是0x33f80000

Cmp r0,r1

将r0和r1做比较,此时r0 = 0x0000000,r1 =
0x33f80000,显然不相等,那么执行的就是下面的汇编指令:

ldr r2, _armboot_start

由此可以知道r2的值是_start,也就是0x33f80000,也是整个代码的起始地址。

Ldr r3, _bss_start

由u-boot.lds的链接脚本可以知道,r3的值是整个代码得结尾.

Sub r2,r3,r2

这条指令的意思是r2 = r3 -r2,即r2 = 代码结束 - 代码开始,这样得到的是r2 = 代码的大小。

Add r2,r0,r2

这条指令的意思是r2 = r0 + r3,即 r2 = 代码开始 + 代码大小,这样得到的是r2 = nor falsh
里面代码的结尾

此时我们得到r0 = nor flash 代码的起始位置,r1 = 0x33f80000(sdram :0x300000000
~ 0x34000000)

呵呵,这个时候代码就被从nor flash里面拷贝到sdram里面了。

这段代码的意思是设置一些堆栈

这段代码的意思是清bss段,

呵呵,终于看到pc指针的值被改变了。也就是这个时候,pc指针开始跳到sdram里面执行代码,这也就到了第二阶段(从语言阶段),后面的代码都是用C语言写得了。先分析到这里,下次我们看第二阶段。

时间: 2024-12-11 13:05:04

uboot第一阶段详细分析的相关文章

U-BOOT第一阶段程序分析(1)

分析移植之前先介绍下我的软硬件环境: 开发板:JZ2440v2板 CPU   :ARM920T SOC   :S3C2440 晶振freq:12MHz NorFlash:2MB => Am29LV160DB NandFlash:256MB => K9F2G08U0A SDRAM:32MB X 2pieces => K4S561632H-T(U)C(16M X 16bit) U-BOOT版本:u-boot-1.1.6.tar.bz2 我移植的uboot是基于nand启动的,所以代码的分析过

U-Boot Makefile 文件详细分析

1. Makefile到底做了什么 之前看了网上许多牛人写的关于Makefile的解析的文章,在这里,我也结合我个人的理解,去分析U-Boot的Makefile. 首先,我们大致了解一下,Makefile到底做了些什么工作?其实,顶层Makefile的主要任务就是组织整个U-Boot工程的编译,概括可以分为以下几个步骤: 首先通过执行make *_config传入$(@:_config=), ARCH, CPU, BOARD, VENDOR, SOC参数(一共六个参数但不一定同时存在),给mkc

2.uboot和系统移植-第5部分-2.5.uboot源码分析1-启动第一阶段

第一部分.章节目录 2.5.1.start.S引入 2.5.2.start.S解析1 2.5.3.start.S解析2 2.5.4.start.S解析3 2.5.5.start.S解析4 2.5.6.start.S解析5 2.5.7.start.S解析6 2.5.8.start.S解析7 2.5.9.uboot重定位详解 2.5.10.start.S解析8 2.5.11.start.S解析9 2.5.12.start.S解析10 2.5.13.start.S解析11 第二部分.章节介绍 2.5.

U-Boot启动过程--详细版的完全分析2

一.初识u-boot 3 1,Bootloader介绍 3 2,Bootloader的启动方式 3 (1)网络启动方式 4 (2)磁盘启动方式 4 (3)Flash启动方式 4 3,U-boot的定义 4 4,u-boot源代码的目录结构 4 5,U-boot中的地址 5 (1)什么是编译地址?什么是运行地址? 5 (2)编译地址和运行地址如何来算呢? 5 (3)为什么要分配编译地址?这样做有什么好处,有什么作用? 5 (4)什么是相对地址? 6 (5)如何去做呢? 6 二.U-Boot总体分析

uboot移植(四)——uboot启动第一阶段

1:BL0 BL1 BL2分别是什么 (1)BL0:s5pv210的iROM中固化的代码 作用:初始化系统时钟,设置看门狗,初始化栈,加载BL1 (2)BL1:从外部启动介质(nand/SD卡)中加载的uboot.bin的前16K代码 作用:初始化RAM,关闭Cache,初始化DDR,设置栈,加载BL2 (3)BL2:是指在代码完成重定位后在DDR中运行的完整的uboot代码 作用:初始化其他外设,加载OS内核 三者的关系:开机上电自动运行BL0的代码,然后加载BL1到SDRAM中,接着通过重定

U-Boot之启动第一阶段

基于samsung的Exynos 4412 从链接脚本u-boot.lds中我们知道u-boot是从start.s这个汇编文件开始的,所以u-boot启动的第一阶段肯定也是从这里开始的,这个文件在cpu/arm_cortexa9/文件夹下,下面我们依照这个文件一步一步分析u-boot启动的第一阶段. #include <config.h> #include <version.h> #if defined(CONFIG_ENABLE_MMU) #include <asm/pro

U-Boot移植之前期分析(下)

接U-Boot移植之前期分析(上): 2. 顶层目录下mkconfig的分析过程 在上面的分析中知道了语句:"@$(MKCONFIG) $(@:_config=) arm arm920t MY_JZ2440 sumsung s3c24x0"对应于执行顶层目录下的mkconfig文件并传递了六个参数 ($0-$6):100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0.下面分析这句话的到底做了什么事情,具体可以阅读源码,由于比较简单这里直接列出具体

u_boot启动流程详细分析(1)

闭上眼睛,仔细的回忆一下从NAND FLASH 启动的整个流程,首先,当我们打开板子的时候,先运行的就是嵌入在芯片上的iROM,它的作用就是为了把,NAND Flash 中的bootloader的一部分代码拷贝到芯片上面的sRAM中,之后,程序在sRAM中运行,它的主要任务就是初始化我们的内存,时钟,以及存储设备,当然更重要的就是从存储设备NAND Flash上拷贝剩下的bootloader到我们的内存的相关位置,之后,运行接下来的bootloader程序,加载运行我们的OS,以及挂在根文件系统

16.U-boot的工作流程分析-2440

16.U-boot的工作流程分析-2440 分析的流程: 程序入口 第一阶段程序分析 第二阶段程序分析 2440开发板: 1.uboot的入口: 要看uboot工程的入口,首先打开顶层目录的Makefile: Uboot所支持的开发板,在顶层的Makefile中都会有一个配置选项.比如2440,在Makefile中的配置选项是smdk2440_config:在vim的命令模式按下/,然后输入smdk6410_config回车会定位到这里: 这是Makefile里的一个目标.这是来配置2440开发