Chinaunix首页 | 论坛 | 博客
  • 博客访问: 932867
  • 博文数量: 63
  • 博客积分: 568
  • 博客等级: 中士
  • 技术积分: 3435
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-05 11:44
文章分类
文章存档

2016年(4)

2015年(6)

2014年(3)

2013年(27)

2012年(23)

分类: 嵌入式

2013-08-21 20:25:02

u-boot 懂你并不难

U-boot第一阶段分析

u-boot是在单板刚启动的时候执行的一段程序。其作用是将内核从flash、硬盘等介质上拷贝到内存中,并传递给内核一些启动参数并跳转到内核去执行。

由于u-boot的代码非常的依赖于不同的体系结构。对u-boot的分析也只能提炼出不同体系结构的共性,做相应的总结。总的说来,u-boot所做到工作分为两个阶段。第一个阶段是将u-boot第二阶段的代码拷贝到ram空间,跳转到第二阶段代码执行。第二阶段是将内核代码拷贝到ram并跳转到内核去执行。

具体执行过程中做到操作如下

· 第一阶段的功能

1.  硬件设备初始化

2. 加载U-Boot第二阶段代码到RAM空间

3. 设置好栈

4. 跳转到第二阶段代码入口

· 第二阶段的功能

5. 初始化本阶段使用的硬件设备

6. 检测系统内存映射

7. 将内核从Flash读取到RAM中

8. 为内核设置启动参数

9. 调用内核

下面以ARM9 u-boot执行过程做一个分析,之后如果有时间再继续分析mips架构的u-boot执行过程,由于u-boot中涉及到许多汇编和体系结构的知识,对我们学习不同的体系结构有很大的帮助。如果相关知识不熟悉,阅读代码的时候会遇到很多疑惑。

第一阶段--硬件设备初始

.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

_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

地址 

异常 

进入模式

描述

0x00000000 

复位

管理模式

复位电平效时,产生复位异常,程序跳转到复位处理程序处执行

0x00000004 

未定义指令

未定义模式

遇到不能处理的指令时,产生未定义指令异常

0x00000008

软件中断

管理模式

执行SWI指令产生,用于用户模式下的程序调用特权操作指令

0x0000000c

预存指令

中止模式

处理器预取指令的地址不存在,或该地址不允许当前指令访问,产生指令预取中止异常

0x00000010

数据操作

中止模式

处理器数据访问指令的地址不存在,或该地址不允许当前指令访问时,产生数据中止异常

0x00000014

未使用

未使用

未使用

0x00000018

IRQ

IRQ

外部中断请求效,且CPSR中的I位为0时,产生IRQ异常

0x0000001c

FIQ

FIQ

快速中断请求引脚效,且CPSR中的F位为0时,产生FIQ异常

在之前的文章中曾经提及过arm处理器有8中运行方式,上电后,cpu首先跳转到0x00000000 地址开始执行

reset:

/*

 * set the cpu to SVC32 mode

 */

mrs r0,cpsr

bic r0,r0,#0x1f

orr r0,r0,#0xd3

msr cpsr,r0

mrs r0,cpsr     //将当前cpsr的状态为保存到r0中。

bic r0,r0,#0x1f //bic,位清零指令。0x1f=00011111,相当于清除低5位。  

刚好是模式位。

orr r0,r0,#0xd3 //或指令。置模式位。0xd3=11010011以及设置5,6,7位的

状态位。禁止FIQ,IRQ,处于arm状态。低5位为10011,则对应超级用户态。msr cpsr,r0     //在将r0中的值赋给状态寄存器cps

/* turn off the watchdog */

#if defined(CONFIG_S3C2400)

# define pWTCON 0x15300000

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

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

#elif defined(CONFIG_S3C2410)

# define pWTCON 0x53000000

# define INTMOD     0X4A000004

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

# define INTSUBMSK 0x4A00001C

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

#endif

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

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

关闭禁止各个中断

#ifdef CONFIG_S3C2440

#define MPLLCON 0x4c000004

#define UPLLCON 0x4c000008

ldr r0, =CLKDIVN

mov r1, #5

str r1, [r0]

ldr r0, =MPLLCON

ldr r1, =0x7f021

str r1, [r0]

ldr r0, =UPLLCON

ldr r1, =0x38022

str r1, [r0]

#else

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

/* default FCLK is 120 MHz ! */

ldr r0, =CLKDIVN

mov r1, #3

str r1, [r0]

#endif

设置cpu各个模块的主频大小

#endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */

/*

 * we do sys-critical inits only at reboot,

 * not when booting from ram!

 */

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

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

blne cpu_init_crit

#endif

如果cpu还是在flash或者step stone的内存中运行的话,跳转到cpu_init_crit运行

cpu_init_crit清空I cache和D cache并清空掉TLB表项,暂时关闭MMU,跳转到lowlevel_init对ram控制寄存器进行初始化

#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 */

设置堆栈指针

stack_setup:

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

sub r0, r0, #CFG_MALLOC_LEN

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