当前位置:首页 » 操作系统 » uboot源码分析

uboot源码分析

发布时间: 2022-05-09 21:47:35

‘壹’ 在uboot源码中 CONFIG_NAND_U_BOOT = y是什么意思

uboot的编译控制,具体要看代码才行,字面上面的意思是Nand命令有关。

‘贰’ ARM汇编中的ldr和adr的区别及其在uboot中相关源码的分析

ARM汇编有ldr指令以及ldr、adr伪指令,它们都可以将标号表达式作为操作数,下面通过分析一段代码以及对应的反汇编结果来说明它们的区别。
ldr r0, _start
adr r0, _start
ldr r0, =_start
_start:
b _start
编译的时候设置 RO 为 0x30000000,下面是反汇编的结果:
0x00000000: e59f0004 ldr r0, [pc, #4] ; 0xc
0x00000004: e28f0000 add r0, pc, #0 ; 0x0
0x00000008: e59f0000 ldr r0, [pc, #0] ; 0x10
0x0000000c: eafffffe b 0xc
0x00000010: 3000000c andcc r0, r0, ip
1.ldr r0, _start

这是一条指令,从内存地址 _start 的位置把值读入。在这里_start是一个标号(是一个相对程序的表达式),汇编程序计算相对于 PC 的偏移量,并生成相对于 PC的前索引的指令:ldr r0, [pc, #4]。执行指令后,r0 =0xeafffffe。
ldr r0, _start是根据_start对当前PC的相对位置读取其所在地址的值,因此可以在和_start标号的相对位置不变的情况下移动。
2.adr r0, _start

这是一条伪指令,总是会被汇编程序汇编为一个指令。汇编程序尝试产生单个 ADD或 SUB 指令来装载该地址。如果不能在一个指令中构造该地址,则生成一个错误,并且汇编失败。在这里是取得标号_start 的地址到 r0,因为地址是相对程序的,因此ADR产生依赖于位置的代码,在此例中被汇编成:add r0, pc, #0。因此该代码可以在和标号相对位置不变的情况下移动;假如这段代码在 0x30000000 运行,那么 adr r0, _start 得到 r0 = 0x3000000c;如果在地址 0 运行,就是 0x0000000c 了。
通过这一点可以判断程序在什么地方运行。U-boot中那段relocate代码就是通过adr实现当前程序是在RAM中还是flash中,下面进行简要分析。

‘叁’ 从SD boot还需要注意什么

从网上可以下载到IROM_Fusing_tools的源码,在按下这个软件的start控件后,先是
读取这个SD卡的第一个扇区,也就是这个磁盘的MBR 扇区,判断是不是FAT32格式的
磁盘(这也是为什么用来做启动的SD必须格式化为FAT32格式),接着获取总的扇区
数目TOTAl_SECOTR,并将所要烧写的bin文件烧写到磁盘的这个扇区:TOTAL_SECTOR –
2 - SIZE_OF_IMAGE/512。其中TOTAl_SECTOR是这个磁盘总的扇区数目;
SIZE_OF_IMAGE/512是这个bin文件将要占据的扇区数(这里是以512为扇区大小的,
因此对于扇区更大的SD卡也就没办法使用了,而现在的大容量SD都可能使用了2K甚至
4K的扇区,除非修改这个程序,并同步地在uboot中修改程序);至于2则是保留的2
个扇区,至于为什么要保留这2个扇区,需要分析uboot的源码情况。

‘肆’ source insight怎么查看uboot代码

对于嵌入式学习经常就要和Uboot和内核打交道,Source Insight便是我认为非常好的源码查看工具。对于Uboot和内核源码的查看,它有着非常好的索引方式,且拥有非常方便的快捷键操作方式。对于庞大的源码树最好就是建立一个工程来管理。但当你查找一个关键词的时候,会出现许多与之相关的文件,不同的CPU和单板会有着同名的文件,很明显并不是所有的文件都是我们需要查看的。那么如何建立一个“节约”且合适的工程呢?在这里分享下我的经验。
一、建立工程文件夹
最好建立一个自己的管理Source Insight所有工程文件夹(例如在D:\建立文件夹 D:\SourInProject),然后分别创建单独的工程文件夹。在这里我们建的是Uboot-2010.03工程,那么就建立一个文件夹名为:Uboot-2010.03Pro,在里面放置Uboot-2010.03源码包,和一个准备放置Source Insight所创建的Uboot-2010.03工程包SourInPro。这样就很清晰,源码和工程包单独放在一个命名为Uboot-2010.03Pro下,即不同的工程都带有一个源码包和一个创建后的工程包。

二、如何创建工程
(1)、首先打开Source Insight软件,配置好软件所认识的文件后缀,点击菜单栏上Options->Document Options,在Document Type下拉列表中,选择C Source File,然后在右边File filter:文本框中添加一些重要文件后缀;*.S;*.lds;*defconfig;Makefile等(否则点击Add Tree添加目录树时,一些重要文件不被加入到工程,则要手动一个个加入,当然最简单的办法就是加个 ;*.* 就好)。然后再点击菜单栏上的Project->New Project,在弹出的New Project对话窗口,New project name:(工程名)在这填Uboot-2010.03,Where do you want to store the project data files?(你想把你的工程文件存放在哪里),在这我们填在上一步创建的D:\SourInProject\Uboot-2010.03Pro\SourInPro。然后一路OK,出现一个名为:Add and Remove Project Files对话框,下面我们就针对此对话窗口操作;

‘伍’ uboot源码怎么查看nandflash分区表

你只能通过NandFlash控制器访问NandFlash,即是只要知道Nand控制器的寄存器地址即可。NandFlash 不是一个RamLike的器件。Uboot放入nand中,在nand的0地址开始存放,移植时候需要注意页对齐,这样Uboot才可以可以通过StepingStone引导。

‘陆’ 关于C语言重复定义的问题-uboot

#include 相当于把.h文件的内容原样放到.C文件相应的#include位置,
#define只在定义它的c文件中起作用
多个c文件可以使用#define定义相同名称的宏,
但是,多个C文件定义相同名称的全局变量的话,就会出问题了,全局变量在整个工程中起作用;也就是说:
a.c中定义了全局变量 int memory;
b.c中就不能定义全局变量 int memory;
同样,你下面的做法是不行的
---------------------------------
//ss.h
#ifndef comand
#define comand 1
int memory;
#endif
--------------------------------
一般来讲,.h文件中只能声明变量,而不要定义变量,如果多个c文件公用一个变量的话,可以在其中一个c文件中定义该变量int memory;,并在头文件中使用extern int memory;声明该变量。

----------------------------------------------------------------------------------------------
#ifndef __COMMON_H_
#define __COMMON_H_ 1
这样写只是为了避免同一个c文件中多次引用同一个头文件,
假设有个a.h文件中,#include了common.h
如果c文件同时#include "a.h" 和<common.h>的话,
#ifndef __COMMON_H_
#define __COMMON_H_ 1
就会起作用了

‘柒’ android 源码里有u-boot吗

本人用的android平台用的bootloader用的是uboot,貌似大多数手持设备平台都不用这个,因为功能过于强大用不上,反而显得太复杂了。不知道这个平台开发者是怎么想的。既然用了那就来分析一下,顺便修改一下其中的几个小问题,以符合我们的要求。
uboot等同于其他所有的bootloader程序,从根本上讲是一个稍复杂的裸机程序,是最底层的东西,要分析裸机程序我们要从它的连接文件开始。连 接文件(.lds文件)定义了程序编译之后整个连接过程,这样我们就可以找到这个程序的第一句汇编代码,进而来下一步分析。uboot的链接文件代码在 android\bootable\bootloader\uboot-imx\u-boot.lds
[cpp] view plain
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") //文件输出格式
OUTPUT_ARCH(arm)
ENTRY(_start) //首地址标示符
SECTIONS
{
. = 0x00000000; //其实地址0
. = ALIGN(4); //4字节对齐
.text : //代码段
{
board/freescale/mx6q_sabresd/flash_header.o (.text.flasheader) //第一个文件是board/freescale/mx6q_sabresd/flash_header.o
cpu/arm_cortexa8/start.o //第二个cpu/arm_cortexa8/start.o
board/freescale/mx6q_sabresd/libmx6q_sabresd.a (.text)
lib_arm/libarm.a (.text)
net/libnet.a (.text)
drivers/mtd/libmtd.a (.text)
drivers/mmc/libmmc.a (.text)
. = DEFINED(env_offset) ? env_offset : .;
common/env_embedded.o(.text)
*(.text) //剩余的所有代码
}
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } //readonly data 段
. = ALIGN(4);
.data : { *(.data) } //所有的readonly data
. = ALIGN(4);
.got : { *(.got) }
. = .;
__u_boot_cmd_start = .; //u_boot_cmd段,里面是所有uboot命令的一个列表
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
. = ALIGN(4);
_end_of_ = .;
__bss_start = .; //bss段 就是内存数据段
.bss : { *(.bss) }
_end = .;
}

从上面的代码可以看出我们编译生成的二进制应用程序组成是:代码段->rodata段->uboot命令列表->bss段。我们启动这个应用程序时候是从,0地址开始的,因此我们来看
board/freescale/mx6q_sabresd/flash_header.s这个文件。
这个文件中除了分配内存和宏定义的伪汇编指令以外,真正执行的命令有一条

[cpp] view plain
.section ".text.flasheader", "x"
b _start
.org CONFIG_FLASH_HEADER_OFFSET
也就是说,这个文件一执行就直接跳到_start 位置处。_start 在android\bootable\bootloader\uboot-imx\cpu\arm_cortexa8\ start.S中,因此我们来看这个文件代码
[cpp] view plain
.globl _start
_start: b reset
这里直接跳转的reset中接下来看
[csharp] view plain
reset:
/*
* set the cpu to SVC32 mode cpu设置成32位管理模式
*/
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0xd3
msr cpsr,r0

#if (CONFIG_OMAP34XX) //因为我们的cpu不是ompa的 所以这段不会编译
.............................
#endif
/* the mask ROM code should have PLL and others stable */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
这里接下来执行cpu_init_crit
[csharp] view plain
/*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************/
cpu_init_crit:
/*
* Invalidate L1 I/D
*/
mov r0, #0 @ set up for MCR
mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
mcr p15, 0, r0, c7, c5, 0 @ invalidate icache

/*
* disable MMU stuff and caches //关闭mmu
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
orr r0, r0, #0x00000800 @ set bit 12 (Z---) BTB
mcr p15, 0, r0, c1, c0, 0

/*
* Jump to board specific initialization...
* The Mask ROM will have already initialized
* basic memory. Go here to bump up clock rate and handle
* wake up conditions.
*/
mov ip, lr @ persevere link reg across call
bl lowlevel_init @ go setup pll,mux,memory//执行lowlevel_init这个函数代码在
@\bootloader\uboot-imx\board\freescale\mx6q_sabresd\lowlevel_init.S中
@主要对时钟,外部ram,rom等进行了初始化代码不贴了。
mov lr, ip @ restore link
mov pc, lr @ back to my caller
初始化完成后,接下来执行
[csharp] view plain
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate: @ relocate U-Boot to RAM 将uboot重新定位到内存中
adr r0, _start @ r0 <- current position of code
ldr r1, _TEXT_BASE @ test if we run from flash or RAM
cmp r0, r1 @ don't reloc ring debug测试当前代码是否已经在内存中
beq stack_setup @如果在的话就直接跳转到stack_setup

ldr r2, _armboot_start @如果不在的话,加载_armboot_start地址到r2中。_armboot_start是uboot执行的主体c函数。
ldr r3, _bss_start
sub r2, r3, r2 @ r2 <- size of armboot计算bss_start-armboot_start 保存到R2中,也就是uboot的总大小
add r2, r0, r2 @ r2 <- source end address 计算出uboot代码和rodata地址

_loop: @ 32 bytes at a time //开始拷贝
ldmia r0!, {r3 - r10} @ from source address [r0]
stmia r1!, {r3 - r10} @ to target address [r1]
cmp r0, r2 @ until source end addreee [r2]
ble _loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */

‘捌’ 在mini2440中把uboot放到norflash,内核,根文件系统,应用程序放在nandflash,系统如何启动

非常简单,mini2440从Nor启动后,CPU运行在0x00000000地址,这片地址实际对应NorFlash,因为NorFlash是一个Ramlike器件,所以读取数据方法更内存一样,在Uboot的启动文件start.s中,有一个一段代码实现NorFlash复制到SRAM的功能,复制代码完成后,通过指令,使用CPU跳到内存执行。这时候,Uboot通过另外的代码,实际是Nand subsystem部分,把kernel从Nand读到内存上,再通过指令,然后CPU跳到Kernel入口地址执行。
一旦Kernel跑起来,Kernel通过Uboot传递CMDLINE就可发现到根文件系统的分区了。所以根文件再通过一些列复杂的机制,最终把文件系统挂入系统中。
要完全了解这个过程,必须要完完整整地把Uboot和Kernel移植一遍才知道。
最后补充一下,mini2440上使用Uboot、supervivi,vivi之类的Bootloader实际功能都差不多。

热点内容
android局域网视频 发布:2024-10-08 18:35:29 浏览:691
java访问私有变量 发布:2024-10-08 18:34:50 浏览:84
vivo锁屏壁纸缓存在哪 发布:2024-10-08 18:34:49 浏览:535
insta360oner配多大的存储卡 发布:2024-10-08 18:34:40 浏览:212
csgo和永劫无间哪个配置要求高 发布:2024-10-08 18:20:47 浏览:48
43数据库 发布:2024-10-08 18:19:20 浏览:816
svn服务器不能访问 发布:2024-10-08 18:18:36 浏览:984
压缩面膜多少钱 发布:2024-10-08 18:18:01 浏览:539
徐州少儿编程培训机构 发布:2024-10-08 17:52:29 浏览:389
c语言常用函数大全 发布:2024-10-08 17:46:33 浏览:410