Chinaunix首页 | 论坛 | 博客
  • 博客访问: 268830
  • 博文数量: 91
  • 博客积分: 2105
  • 博客等级: 大尉
  • 技术积分: 1050
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-14 19:30
文章分类
文章存档

2011年(11)

2010年(64)

2009年(16)

我的朋友

分类: LINUX

2010-09-02 10:47:57

为什么要分析源代码?分析优秀的源代码本身就是一个学习的过程,也是进行深入研究的必经之路。不过在此我们的主要目的并非要研究U-bootBootloader技术本身,而仅仅是为了成功的并且恰当的将U-Boot移植到我们的开发板上。只有结合源代码了解了U-boot的系统引导过程,才能在移植和调试过程中保持清晰的思路,才能在碰到困难和问题时从根本上加以解决。

在动手分析之前,至少应该对U-Boot的源代码结构有基本的了解,很多参考书都有这方面的介绍,华清远见的《嵌入式Linux系统开发技术详解——基于ARM》的讲解就比较清晰。

本文以lubbock开发板为例,以系统启动的流程为线索进行纵向分析:后续的移植工作也将以此开发板为模板。Lubbock使用PXA255处理器。

首先要找到程序入口点。从board/lubbock/u-boot.lds可以发现,u-boot的程序入口为_start,在cpu/pxa/start.o当中。因此首先要分析start.S程序,U-Boot中所有的PXA系列的处理器都从这里开始执行第一条语句。

.globl _start

_start: b reset

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

0x0地址开始是ARM异常向量表,学过ARM体系结构与编程的都明白,非常简单,不多废话。一上电的第一条指令是跳转到reset复位处理程序:

reset:

/* 进入SVC模式 */

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

bl cpu_init_crit /* we do sys-critical inits */

#endif

#ifndef CONFIG_SKIP_RELOCATE_UBOOT

relocate:

......

一般不要定义CONFIG_SKIP_LOWLEVEL_INIT,因此,接下来跳转到cpu_init_crit处开始执行:

cpu_init_crit:

/* 屏蔽所有中断 */

/* 设置时钟源,关闭除FFUART,SRAM,SDRAM,FLASH以外的外设时钟 */

......

#ifdef CFG_CPUSPEED

ldr r0, CC_BASE /* 时钟控制寄存器基址 */

ldr r1, cpuspeed

/* cpuspeed: .word CFG_CPUSPEED */

str r1, [r0, #CCCR]

mov r0, #2

mcr p14, 0, r0, c6, c0, 0


setspeed_done:

#endif /* CFG_CPUSPEED */

/* 跳转到lowlevel_init,这里ipr12,用作暂存寄存器 */

mov ip, lr

bl lowlevel_init

mov lr, ip

/* Memory interfaces are working. Disable MMU and enable I-cache. */

ldr r0, =0x2001

......

/* 关闭MMU,使能I-Cache(可选) */

mov pc, lr /* 这里是从cpu_init_crit返回到relocate标号 */


可见,在cpu_init_crit中的主要工作是设置时钟,配置处理器主频(这时CPU的工作频率还没有改变),调用lowlevel_init函数进行底层初始化(包括调整处理器工作频率、系统总线频率、存储器时钟频率以及存储系统的初始化等工作),随后关闭MMU并使能I-Cache,再返回。

lowlevel_init函数在board/lubbock/lowlevel_init.S中定义,其流程都是按照PXA27X的开发手册来的,所以不再赘述。仅指出,其中的寄存器在include/asm-arm/arch-pxa/pxa-regs.h头文件中定义,寄存器初始化值在include/configs/lubbock.h中定义。另外,在后面的实际移植工作中,由于目标板XSBASE270使用的PXA270处理器,可使用adsvix开发板的lowlevel_init.S文件(lubbock中没有开启turbo模式)

接着程序的执行线索进行分析。从cpu_init_crit返回后就开始relocate(重定位),即将U-bootFLASH存储器搬运到SDRAMTEXT_BASE开始的存储空间(TEXT_BASEboard/lubbock/config.mk中定义),并初始化堆栈(清零.bss),以在SDRAM中开始进入到Bootloader stage 2C程序入口。Relocate部分开始的代码如下:

/* 之前已定义的部分变量有:

_TEXT_BASE: .word TEXT_BASE

_armboot_start: .word _start

_bss_start: .word __bss_start

_bss_end: .word _end */

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 /* 读入_startr2 */

ldr r3, _bss_start /* 读入__bss_startr3 */

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


/* Set up the stack */

stack_setup:

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

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

sub r0, r0, #CFG_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

这是很经典的一段代码,相信学习凡是过ARM编程的,都分析过这段代码,所以也不再赘述。之所以列出这段代码,一是为了找到C程序入口start_armboot,二是为了给出U-Boot的一个存储器映射图:

这个图可以帮助我们更好地理解后续的C语言代码以及U-Boot对内存的分配与使用情况。

阅读(414) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2011-04-13 16:37:11

学习了,多谢楼主分享哦!也欢迎广大linux爱好者来我的论坛一起讨论arm哦!www.lt-net.cn

chinaunix网友2010-09-04 14:37:01

Download More than 1000 free IT eBooks: http://free-ebooks.appspot.com