uboot源码 start.S文件详解

来源:本站
导读:目前正在解读《uboot源码 start.S文件详解》的相关信息,《uboot源码 start.S文件详解》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《uboot源码 start.S文件详解》的详细说明。
简介:花了一个下午的时间一行一行看完的,结合了和下面这个人的blog的内容.虽然啃的吃力,不过受益菲浅.

#include <common.h> /*在文件 /include */

#include <config.h> /*在文件 /include/linux */

/*

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

*

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

*

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

*/

.globl _start /*系统复位位置,整个程序入口*/

_start: b start_code /* 跳转到start_code所在位置,并且不会返回 ,此处的代码地址是 0x0000 0000 */

ldr pc, _undefined_instruction /* 0x0000 0000 undefined */

ldr pc, _software_interrupt /* 0x0000 0004 supervisor */

ldr pc, _prefetch_abort /* 0x0000 0008 abort(prefetch)*/

ldr pc, _data_abort /* 0x0000 000C abort(data) */

ldr pc, _not_used /* 0x0000 0010 Reserved */

ldr pc, _irq /* 0x0000 0014 IRQ */

ldr pc, _fiq /* 0X0000 001C FIQ */

/*以上7个就是异常中断的初始地址,把每个地址对应的标号写进去*/

_undefined_instruction: .word undefined_instruction /* variable define*/

_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 /*定义fiq变量到_fiq地址里面去,_fiq地址就是上面所对应的,比如_fiq是0x0000 001C */

.balignl 16,0xdeadbeef

/*上面这个.balignl请参看http://hi.baidu.com/esta_pessoa/blog/item/7e519301e6e810131c9583db.html*/

/*

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

*

* 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 /*_TEXT_BASE 定义在文件/board/smdk2410/config.mk,值是0x33F80000*/

.globl _armboot_start

_armboot_start:

.word _start /* 用 _start 定义 _armboot_start,也就是_start 地址和_armboot_start 相同了*/

/*

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

*/

.globl _bss_start

_bss_start:

.word __bss_start /* 在文件 u-boot.lds 中定义 */

.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: /*注意是IRQ!!*/

.word 0x0badc0de

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

.globl FIQ_STACK_START

FIQ_STACK_START: /*注意是FIQ!!*/

.word 0x0badc0de

#endif

/*

* the actual start code

*/

start_code: /*如果启动的话,真正算作启动的操作从这里开始!! */

/*

* set the cpu to SVC32 mode svc为操作系统保护模式

*/

mrs r0, cpsr /*初始化cpsr*/

bic r0, r0, #0x1f /*0x1f = 0001 1111 ~0x1f= 1110 0000 r0[0:5] = 0, bic=位清零*/

orr r0, r0, #0xd3 /*0xd3 = 1101 0011 <--这个是cpsr的最终值,其中 中断关闭, 模式设置为SVC模式 */

msr cpsr, r0 /* FIQ =1 , IRQ = 1, T = 1,SVC mode. */

bl coloured_LED_init /*这两个函数定义在别的位置,如果移植的话,应该会去掉,只是一个测试LED的程序*/

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) 2440和2410大致相同,所以这里会被执行到

/* turn off the watchdog */

# if defined(CONFIG_S3C2400)

# define pWTCON 0x15300000 /* watch dog address*/

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

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

#else/* 注意我们要执行的是这里 s3c2410 or s3c2440 */

# define pWTCON 0x53000000 /* 看门狗地址,我查过手册了,正确*/

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

# define INTSUBMSK 0x4A00001C

# define CLKDIVN 0x4C000014 /* clock pisor 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

/*对于S3C2410的INTMSK寄存器的32位和INTSUBMSK寄存器的低11位每一位对应一个中断,相应位置“1”为不响应相应的中断。对于S3C2440的INTSUBMSK有15位可用,所以应该为0x7fff了。*/

/*

*设置时钟 FCLK!!

*/

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

/* default FCLK is 120 MHz ! */

ldr r0, =CLKDIVN

mov r1, #3 /*0x0=1:1:1,0x1= 1:1:2,0x3=1:2:4,0x4= 1:4:4,0x5= 1:4:8,0x6=1:3:3,0x7=1:3:6*/

str r1, [r0]

/*

*s3c2440时钟的计算公式 : Mpll=(2*m*Fin)/(p*2^s)

*/

#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 /*跳转到cpu_init_crit函数, 会返回的!*/

/* 在第 265行(如果你用vi的话)*/

#endif

/*

* 将代码从flash拷贝到RAM中

*/

#ifndef CONFIG_SKIP_RELOCATE_UBOOT

relocate: /* relocate U-Boot to RAM */

adr r0, _start /* r0 <- current position of code */

/* adr r0, _start 这个代码将会计算标记 "_start"的位置

*

*如果是在flash中运行则 _start的值就是0,

*如果是在RAM中运行,则 _start=_TEXT_BASE=TEXT_BASE= 0x33F80000

*(_TEXT_BASE 在 board/smdk2410/config.mk 中定义)

*/

ldr r1, _TEXT_BASE /* 测试是在 flash 还是在RAM */

cmp r0, r1 /* don't reloc during debug */

beq stack_setup /* BEQ,相等就跳转 ,若r0=r1,则 Z=1,说明运行在ram中,那么直接跳转到堆栈初始化 */

/*stack_setup 在 222行*/

/*

*如果代码运行在flash中,那么拷贝自身代码从flash到ram去

*/

ldr r2, _armboot_start /*找到代码的起始地址*/

ldr r3, _bss_start

sub r2, r3, r2 /* r2 <- 代码长度size */

add r2, r0, r2 /*r2 <- 找到结束地址 */

/*

*代码循环复制

*/

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

/* 初始化堆栈,为第二阶段的C语言做准备 */

stack_setup:

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

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

/*CFG_MALLOC_LEN=128*1024+CFG_ENV_SIZE=128*1024+0X10000=192K*/

sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo<--save board info (128) */

#ifdef CONFIG_USE_IRQ

sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

#endif

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

/*数据段 _bss_start <----> _bss_end 的初始化*/

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... 初始化直接使用双字,一次就是64个位 */

add r0, r0, #4 /*address + 4*/

cmp r0, r1 /* is the end ?*/

ble clbss_l /*ble 的含义: "<="*/

ldr pc, _start_armboot /*跳转到stage2*/

/*stage1 到此结束 ,然后开始stage2

*

*above is the cross of stage1

*

*/

_start_armboot: .word start_armboot

/*

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

*

* CPU_init_critical registers

*

* setup important registers

* setup memory timing

*

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

*/

/*cpu_init_crit is 是前面所调用的函数,运行在stage1结束以前*/

#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 /* 函数返回操作!*/

/*

*init the RAM ,in file /board/smdk2410/lowlevel_init.S

*/

bl lowlevel_init

/*

*RETURN to the line number 182

*/

mov lr, ip

mov pc, lr

/*

*cpu init 至此结束

*/

#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

/*

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

*

* Interrupt handling

*

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

*/

这个包括下面的部分都不会涉及到,所以跳过了.stage2在lib_arm/board.c 中.

可知start.S的流程为:异常向量——上电复位后进入复位异常向量——跳到启动代码处——设置处理器进入管理模式——关闭看门狗——关闭中断——设置时钟分频——关闭MMU和CACHE——进入lowlever_init.S——检查当前代码所处的位置,如果在FLASH中就将代码搬移到RAM中

提醒:《uboot源码 start.S文件详解》最后刷新时间 2024-03-14 01:03:11,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《uboot源码 start.S文件详解》该内容的真实性请自行鉴别。