现在的位置: 首页 > 综合 > 正文

u-boot启动文件start.S分析

2013年10月19日 ⁄ 综合 ⁄ 共 10123字 ⁄ 字号 评论关闭

start.S的分析很多人也都写过了.这里只是重新整理了一下,加了点自己的理解,如果有不对的地方还希望大家指正

下面以u-boot-1.2.0源码分析arm920t的start.S

1.首先看一下./board/smdk2410/U-Boot.lds文件,对后面理解start.S有很大好处

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")/*指定输出格式为elf, 小端模式*/
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
OUTPUT_ARCH(arm)/*指定输入目标系统为arm*/
ENTRY(_start)/*指定程序入口点,其中_start在/u-boot-1.2.0/cpu/arm920t/start.S里定义*/
SECTIONS
{
. = 0x00000000;/*从0地址开始*/

/*text段,其中start.o位于最前端,即0x0位置*/
. = ALIGN(4);/*4字节对齐*/
.text      :
{
  cpu/arm920t/start.o(.text)
  *(.text)
}

/*rodata段*/
. = ALIGN(4);
.rodata : { *(.rodata) }

/*data段*/
. = ALIGN(4);
.data : { *(.data) }

/*got段*/
. = ALIGN(4);
.got : { *(.got) }

/*u_boot_cmd段(存放u-boot所有命令的段).指定_u_boot_cmd_start及__u_boot_cmd_end位置*/
. = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;

/*bss段.指定__bss_start及end的位置*/
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss) }
_end = .;
}

/*
从高到低依次是:
_end
            bss段
_bss_start
__u_boot_cmd_end
            u_boot_cmd段
__u_boot_cmd_start
            got段
            data段
            rodata段
            text段
            (start.o)
_start
0x00000000

记住这些信息,对往后分析start.S有好处
*/

/*全局入口点,同时_start在U-boot.lds里被指定为程序的第一个入口点,这里也可以看出首先会运行reset*/
.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

/以这个地方往后为16倍数的地址的地方插入0xdeadbeef标志*/
.balignl 16,0xdeadbeef

/*
 *************************************************************************
 *
 * Startup Code (reset vector)
 *
 * do important init only if we don't start from memory!
 * relocate armboot to ram
 * setup stack
 * jump to second stage
 *
 *************************************************************************
 */
/*指定_TEXT_BASE的位置,其中TEXT_BASE在/board/smdk210/config.mk里定义,为u-boot的加载地址*/
_TEXT_BASE:
.word TEXT_BASE

/*指定_armboot_start的位置,其中_start在/board/smdk210/U-boot.lds里定义*/
.globl _armboot_start
_armboot_start:
.word _start

/*
 * These are defined in the board-specific linker script.
 */
/*指定_bss_start的位置,其中__bss_start在/board/smdk210/U-boot.lds里定义*/
.globl _bss_start
_bss_start:
.word __bss_start

/*指定_bss_end的位置,其中_end在/board/smdk210/U-boot.lds里定义*/
.globl _bss_end
_bss_end:
.word _end

/*指定IRQ_STACK_START和FIQ_STACK_START的位置*/
#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 reset code
 */

reset:
/*
 * set the cpu to SVC32 mode
 */
mrs r0,cpsr /*读cpsr寄存器到ro*/
bic r0,r0,#0x1f /*清除低5位*/
orr r0,r0,#0xd3 /*把低5位置为10011,即设为svc模式*/
msr cpsr,r0/*写回cpsr*/

/*定义pWTCON(喂狗寄存器),INTMSK(中断掩码寄存器),CLKDIVN(时钟除数寄存器),这个需要根据相关芯片的datasheet配置*/
/* 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 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

/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
/*CLKDIVN的值决定了FCLK:HCLK:PCLK的值,这里默认设为3*/
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
#endif /* CONFIG_S3C2400 || CONFIG_S3C2410 2氏*/

/*
 * we do sys-critical inits only at reboot,
 * not when booting from ram!
 */
 /* 一些*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif

这里会先跳到cpu_init_cut,代码如下:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>cpu_init_crit>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

#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 无效数据cache和指令cache*/
mcr p15, 0, r0, c8, c7, 0/* flush v4 TLB 无效TLB(什么是TLB?)*/

/*
 * disable MMU stuff and caches
 */
mrc p15, 0, r0, c1, c0, 0/*读c1的值到r0*/
bic r0, r0, #0x00002300@ clear bits 13, 9:8 (--V- --RS)/*V控制中断向量表的位置,R和S控制MMU的一些保护位*/
bic r0, r0, #0x00000087@ clear bits 7, 2:0 (B--- -CAM)/*B为0是little-endian, C为0是禁止数据cache,A为0是地址对齐检查,M为0是禁止MMU*/
orr r0, r0, #0x00000002@ set bit 2 (A) Align/*使能地址对齐检查*/
orr r0, r0, #0x00001000@ set bit 12 (I) I-Cache/*使能指令cache*/
mcr p15, 0, r0, c1, c0, 0/*写回c1*/

/*
 * 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.
 */
/*执行/board/smdk210/lowlevel_init.S的lowlevel_init部分*/
mov ip, lr
bl lowlevel_init
mov lr, ip
mov pc, lr/*跳回程序调用处*/
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

这里会跳到./board/smdk2410/lowlevel_init.S,我们再跳过去看一下

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>lowlevel_init.S>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define BWSCON 0x48000000

/* BWSCON */
#define DW8  
(0x0)
#define DW16  (0x1)
#define DW32  (0x2)
#define WAIT  (0x1<<2)
#define UBLB  (0x1<<3)

#define B1_BWSCON   (DW32)
#define B2_BWSCON   (DW16)
#define B3_BWSCON   (DW16 + WAIT + UBLB)
#define B4_BWSCON   (DW16)
#define B5_BWSCON   (DW16)
#define B6_BWSCON   (DW32)
#define B7_BWSCON   (DW32)

/* BANK0CON */
#define B0_Tacs  0x0
/*  0clk */
#define B0_Tcos  0x0
/*  0clk */
#define B0_Tacc  0x7
/* 14clk */
#define B0_Tcoh  0x0
/*  0clk */
#define B0_Tah  0x0
/*  0clk */
#define B0_Tacp  0x0
#define B0_PMC  0x0
/* normal */

/* BANK1CON */
#define B1_Tacs  0x0
/*  0clk */
#define B1_Tcos  0x0
/*  0clk */
#define B1_Tacc  0x7
/* 14clk */
#define B1_Tcoh  0x0
/*  0clk */
#define B1_Tah  0x0
/*  0clk */
#define B1_Tacp  0x0
#define B1_PMC  0x0

#define B2_Tacs  0x0
#define B2_Tcos  0x0
#define B2_Tacc  0x7
#define B2_Tcoh  0x0
#define B2_Tah  0x0
#define B2_Tacp  0x0
#define B2_PMC  0x0

#define B3_Tacs  0x0
/*  0clk */
#define B3_Tcos  0x3
/*  4clk */
#define B3_Tacc  0x7
/* 14clk */
#define B3_Tcoh  0x1
/*  1clk */
#define B3_Tah  0x0
/*  0clk */
#define B3_Tacp  0x3     /*  6clk */
#define B3_PMC  0x0
/* normal */

#define B4_Tacs  0x0
/*  0clk */
#define B4_Tcos  0x0
/*  0clk */
#define B4_Tacc  0x7
/* 14clk */
#define B4_Tcoh  0x0
/*  0clk */
#define B4_Tah  0x0
/*  0clk */
#define B4_Tacp  0x0
#define B4_PMC  0x0
/* normal */

#define B5_Tacs  0x0
/*  0clk */
#define B5_Tcos  0x0
/*  0clk */
#define B5_Tacc  0x7
/* 14clk */
#define B5_Tcoh  0x0
/*  0clk */
#define B5_Tah  0x0
/*  0clk */
#define B5_Tacp  0x0
#define B5_PMC  0x0
/* normal */

#define B6_MT  0x3
/* SDRAM */
#define B6_Trcd   
0x1
#define B6_SCAN  0x1
/* 9bit */

#define B7_MT  0x3
/* SDRAM */
#define B7_Trcd  0x1
/* 3clk */
#define B7_SCAN  0x1
/* 9bit */

/* REFRESH parameter */
#define REFEN  0x1
/* Refresh enable */
#define TREFMD  0x0
/* CBR(CAS before RAS)/Auto refresh */
#define Trp  
0x0 /* 2clk */
#define Trc  
0x3 /* 7clk */
#define Tchr  0x2
/* 3clk */
#define REFCNT  1113
/* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */
/**************************************/

_TEXT_BASE:
.word TEXT_BASE

.globl lowlevel_init
lowlevel_init:
/* memory control configuration */
/* make r0 relative the current location so that it */
/* reads SMRDATA out of FLASH rather than memory ! */
ldr     r0, =SMRDATA/*把SMRDATA的地址赋给r0*/
ldr r1, _TEXT_BASE/*把_TEXT_BASE地址赋给r1*/
sub r0, r0, r1/*SMRDATA-_TEXT_BASE的值表示在SMRDATA标签的相对位置
ldr r1, =BWSCON/* Bus Width Status Controller *//*SDRAM控制寄存器起始地址*/
add     r2, r0, #13*4/*r0是SMRDATA的相对起始位置,r2是SMRDATA的结束位置*/

/*从SMRDATA段循环赋13个寄存器的值到BWSCON寄存器,完成SDRAM控制寄存器初始化*/
0:
ldr     r3, [r0], #4
str     r3, [r1], #4
cmp     r2, r0
bne     0b

/* everything is fine now */
/*跳回去这段代码的调用处*/
mov pc, lr

.ltorg
/* the literal pools origin */

SMRDATA:
    .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
    .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
    .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
    .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
    .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
    .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
    .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
    .word 0x32
    .word 0x30
    .word 0x30

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<lowlevel_init.S<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<cpu_init_crit<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

从lowlevel_init跳回, 再从cpu_init_crit跳回来之后继续运行:

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate: /* relocate U-Boot to RAM    */
/*比较_start和_TEXT_BASE,如果相等就直接跳到stack_setup,如果不相等的话要把u-boot搬到_TEXT_BASE去*/
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

/*起始:_start,结束_bss_start*/
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操作*/
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    */
/*分配空间,从上到下依次是:
_TEXT_BASE
                        CFG_MALLOC_LEN,堆
                        CFG_GBL_DATA_SIZE,全局数据区
                        CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ,中断及快速中断栈区
*/
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    */

/*清除bss段*/
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

#if 0
/* try doing this stuff after the relocation */
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, =INTMR
str r1, [r0]

/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
/* END stuff after relocation */
#endif
/*跳转到Uboot-1.2.0/lib_arm/board.c里的_start_armboot,也就是C程序入口*/
ldr pc, _start_armboot
_start_armboot: .word start_armboot

搞定.睡觉了.明天再看start_armboot

抱歉!评论已关闭.