您的位置:首页 > 其它

U-boot源码简要分析(一)

2011-03-30 20:03 323 查看
先来看看源码目录结构,再按照代码的执行顺序简单地分析源码

1.U-boot源码整体框架

源码解压以后,我们可以看到以下的文件和文件夹:




cpu



与处理器相关的文件。每个子目录中都包括
cpu.c


interrupt.c


start.S


u-boot.lds



cpu.c


初始化
CPU

、设置指令
Cache

和数据
Cache



interrupt.c


设置系统的各种中断和异常

start.S



U-boot

启动时执行的第一个文件,它主要做最早其的系统初始化,代码重定向和设置系统堆栈,为进入
U-boot

第二阶段的
C

程序奠定基础

u-boot.lds


链接脚本文件,对于代码的最后组装非常重要


board



已经支持的所有开发板相关文件,其中包含
SDRAM

初始化代码、
Flash

底层驱动、板级初始化文件


其中的
config.mk


文件定义了
TEXT_BASE

,也就是代码在内存的其实地址,非常重要。


common



与处理器体系结构无关的通用代码,
U-boot

的命令解析代码
/common/command.c

、所有命令的上层代码
cmd_*.c



U-boot

环境变量处理代码
env_*.c

、等都位于该目录下

drivers



包含几乎所有外围芯片的驱动,网卡

USB

、串口、
LCD


Nand Flash

等等

disk

fs



net



支持的
CPU

无关的重要子系统:

磁盘驱动的分区处理代码

文件系统:
FAT


JFFS2


EXT2



网络协议:
NFS


TFTP


RARP


DHCP

等等

include



头文件,包括各
CPU

的寄存器定义
,文件系统、网络等等

configs

子目录
下的文件是与目标板相关的配置头文件

doc

U-Boot

的说明文档,在修改配置文件的时候可能用得上

lib_arm



处理器体系相关的初始化文件

比较重要的是其中的
board.c

文件,几乎是
U-boot

的所有架构第二阶段代码入口函数和相关初始化函数存放的地方。

lib_avr32

lib_blackfin

lib_generic

lib_i386

lib_m68k

lib_microblaze

lib_mips lib_nios

lib_nios2

lib_ppc

lib_sh

lib_sparc

api

examples

外部扩展应用程序的
API

和范例

nand_spl

onenand_ipl

post

一些特殊构架需要的启动代码和上电自检程序代码

libfdt

支持平坦设备树
(flattened device trees)

的库文件

tools

编译
S-Record


U-Boot

映像等相关工具,***
bootm

引导的内核映像文件工具
mkimage

源码就在此

Makefile



MAKEALL

config.mk

rules.mk

mkconfig

控制整个编译过程的主
Makefile

文件和规则文件

CHANGELOG

CHANGELOG-before-U-Boot-1.1.5

COPYING

CREDITS

MAINTAINERS

README

一些介绍性的文档、版权说明

标为红色
的是移植时比较重要的文件或文件夹。

2. U-boot代码的大致执行流程(以S3C24x0为例)

从链接脚本文件u-boot.lds中可以找到代码的起始:

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

OUTPUT_ARCH(arm)

ENTRY(_start)

SECTIONS

{


. = 0x00000000;




. = ALIGN(4);


.text :


{


cpu/arm920t/start.o
(.text)


*(.text)


}

…...

从中知道程序的入口点是_start,定位于cpu/arm920t /start.S(即u-boot启动的第一阶段)。

下面我们来仔细分析一下 start.S。(请对照数据手册阅读源码):

#include <common.h>

#include <config.h>



/*


*************************************************************************


*


* Jump vector table as in table 3.1 in [1]


*


*************************************************************************


*/





.globl _start

_start:
b
start_code


ldr
pc, _undefined_instruction


ldr
pc, _software_interrupt


ldr
pc, _prefetch_abort


ldr
pc, _data_abort


ldr
pc, _not_used


ldr
pc, _irq


ldr
pc, _fiq



_undefined_instruction:
.word undefined_instruction

_software_interrupt:
.word software_interrupt

_prefetch_abort:
.word prefetch_abort

_data_abort:
.word data_abort

_not_used:
.word not_used

_irq:
.word irq

_fiq:
.word fiq




.balignl 16,0xdeadbeef





/*


*************************************************************************


*


* Startup Code (called from the ARM reset exception vector)


*


* do important init only if we don't start from memory!


* relocate armboot to ram


* setup stack


* jump to second stage


*


*************************************************************************


*/



_TEXT_BASE:


.word
TEXT_BASE



.globl _armboot_start

_armboot_start:


.word _start



/*


* These are defined in the board-specific linker script.


*/

.globl _bss_start

_bss_start:


.word __bss_start



.globl _bss_end

_bss_end:


.word _end



#ifdef CONFIG_USE_IRQ

/* IRQ stack memory (calculated at run-time) */

.globl IRQ_STACK_START

IRQ_STACK_START:


.word
0x0badc0de



/* IRQ stack memory (calculated at run-time) */

.globl FIQ_STACK_START

FIQ_STACK_START:


.word 0x0badc0de

#endif





/*


* the actual start code


*/



start_code:


/*



* set the cpu to SVC32 mode



*/


mrs
r0, cpsr


bic
r0, r0, #0x1f


orr
r0, r0, #0xd3


msr
cpsr, r0




bl
coloured_LED_init


bl
red_LED_on



#if
defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)


/*



* relocate exception table



*/


ldr
r0, =_start


ldr
r1, =0x0


mov
r2, #16

copyex:


subs
r2, r2, #1


ldr
r3, [r0], #4


str
r3, [r1], #4


bne
copyex

#endif



#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)


/* turn off the watchdog */



# if defined(CONFIG_S3C2400)

#
define pWTCON
0x15300000

#
define INTMSK
0x14400008
/* Interupt-Controller base addresses */

#
define CLKDIVN
0x14800014
/* clock divisor register */

#else

#
define pWTCON
0x53000000

#
define INTMSK
0x4A000008
/* Interupt-Controller base addresses */

#
define INTSUBMSK
0x4A00001C

#
define CLKDIVN
0x4C000014
/* clock divisor register */

# endif




ldr
r0, =pWTCON


mov
r1, #0x0


str
r1, [r0]




/*



* mask all IRQs by setting all bits in the INTMR - default



*/


mov
r1, #0xffffffff


ldr
r0, =INTMSK


str
r1, [r0]

# if defined(CONFIG_S3C2410)


ldr
r1, =0x3ff


ldr
r0, =INTSUBMSK


str
r1, [r0]

# endif




/* FCLK:HCLK:PCLK = 1:2:4 */


/* default FCLK is 120 MHz ! */


ldr
r0, =CLKDIVN


mov
r1, #3


str
r1, [r0]

#endif
/* CONFIG_S3C2400 || CONFIG_S3C2410 */




/*



* we do sys-critical inits only at reboot,



* not when booting from ram!



*/

#ifndef CONFIG_SKIP_LOWLEVEL_INIT


bl
cpu_init_crit

#endif



#ifndef CONFIG_SKIP_RELOCATE_UBOOT

relocate:
/* relocate U-Boot to RAM

*/


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 during debug
*/


beq
stack_setup




ldr
r2, _armboot_start


ldr
r3, _bss_start


sub
r2, r3, r2
/* r2 <- size of armboot
*/


add
r2, r0, r2
/* r2 <- source end address
*/



copy_loop:


ldmia
r0!, {r3-r10}
/* copy from source address [r0]
*/


stmia
r1!, {r3-r10}
/* copy to
target address [r1]
*/


cmp
r0, r2
/* until source end addreee [r2]
*/


ble
copy_loop

#endif
/* CONFIG_SKIP_RELOCATE_UBOOT */




/* Set up the stack

*/

stack_setup:


ldr
r0, _TEXT_BASE
/* upper 128 KiB: relocated uboot
*/


sub
r0, r0, #CONFIG_SYS_MALLOC_LEN
/* malloc area
*/


sub
r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo
*/

#ifdef CONFIG_USE_IRQ


sub
r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

#endif


sub
sp, r0, #12
/* leave 3 words for abort-stack
*/



clear_bss:


ldr
r0, _bss_start
/* find start of bss segment
*/


ldr
r1, _bss_end
/* stop here
*/


mov
r2, #0x00000000
/* clear

*/



clbss_l:str
r2, [r0]
/* clear loop...
*/


add
r0, r0, #4


cmp
r0, r1


ble
clbss_l




ldr
pc, _start_armboot



_start_armboot:
.word start_armboot







/*


*************************************************************************


*


* CPU_init_critical registers


*


* setup important registers


* setup memory timing


*


*************************************************************************


*/





#ifndef CONFIG_SKIP_LOWLEVEL_INIT

cpu_init_crit:


/*



* flush v4 I/D caches



*/


mov
r0, #0


mcr
p15, 0, r0, c7, c7, 0
/* flush v3/v4 cache */


mcr
p15, 0, r0, c8, c7, 0
/* flush v4 TLB */




/*



* disable MMU stuff and caches



*/


mrc
p15, 0, r0, c1, c0, 0


bic
r0, r0, #0x00002300
@ clear bits 13, 9:8 (--V- --RS)


bic
r0, r0, #0x00000087
@ clear bits 7, 2:0 (B--- -CAM)


orr
r0, r0, #0x00000002
@ set bit 2 (A) Align


orr
r0, r0, #0x00001000
@ set bit 12 (I) I-Cache


mcr
p15, 0, r0, c1, c0, 0




/*



* before relocating, we have to setup RAM timing



* because memory timing is board-dependend, you will



* find a lowlevel_init.S in your board directory.



*/


mov
ip, lr




bl
lowlevel_init




mov
lr, ip


mov
pc, lr

#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

…...



//

位于
/include

目录下是一个包含其他头文件的头文件

//

位于
/include/linux

目录下























u-boot

的主入口,跳入了后面的
start_code



这些是跳转向量表,和芯片的体系结构有关




ldr

语句的意思是将第二个操作数(如:
_undefined_instruction

)指向的地址数据传给
PC





.word

为定义一个
4

字节的空间

undefined_instruction

为地址,


即后面标号所对的偏移地址数据







16

字节对齐,并以
0xdeadbeef

填充,它是个
Magic number





















这些和上面的一样,定义一个
4

字节的空间存放地址



































































代码从这里开始执行!!







让系统进入

SVC


(管理员模式)








这些都是为
AT91RM9200

写的







































系统时钟的寄存器地址定义



















关闭看门狗










关闭所有中断






















设置时钟的分频比












跳入

cpu_init_crit


,这是一个系统初始化函数,他还会调用

board/*/lowlevel_init.S


中的

lowlevel_init


函数。


主要是对系统总线的初始化,初始化了连接存储器的位宽、速度、刷新率等重要参数。经过这个函数的正确初始化,

Nor Flash




SDRAM


才可以被系统使用。下面的代码重定向就依赖它。


代码重定向

,它首先检测自己是否已经在内存中:

如果是直接跳到下面的堆栈初始化代码
stack_setup



如果不是就将自己从
Nor Flash

中拷贝到内存中







自拷贝循环



请注意看英文注释












堆栈初始化代码(为第二阶段的

C


语言做准备)














BSS


段清零(为第二阶段的

C


语言做准备)


BSS

段(
bss segment

)通常是用来存放程序中未初始化的全局变量的一块内存区域。
BSS

是英文
Block Started by Symbol

的简称。
BSS

段属于静态内存分配。在编译时,编译器已经为他们分配好了空间,只不过他们的值为
0

,为了节省空间,在
bin


ELF

文件中不占空间。

编译器会计算出
_bss_start


_bss_end

的值,不是定义的



跳入第二阶段的

C


语言代码入口

_start_armboot


(已经被重定向到内存)

























前面所说的
cpu_init_crit

系统初始化函数





操作
CP15

协处理器,





































调用
board/*/lowlevel_init.S

中的
lowlevel_init

函数,对系统总线的初始化,初始化了连接存储器的位宽、速度、刷新率等重要参数。经过这个函数的正确初始化,
Nor Flash


SDRAM

才可以被系统使用。

后面的代码略,主要是中断相关代码,但是
U-boot

基本不使用中断所以暂且略过。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: