学习 uboot 之二启动代码start.S分析

下面我们正式开始讲解Uboot的启动代码,由uboot的链接脚本能够知道uboot链接时放在代码最开头的是CPU/$(CPUDIR)/start.S

在正式看代码之前,我们需要了解S3C2440的stepping stone机制,即NAND FLASH启动时,S3C2440会利用自己内部的控制器将NAND FLASH前4K的内容拷贝到片内的RAM中并将片内RAM映射到0地址开始的地方。

下面我们就来看下cpu\arm920t目录下的start.S

#include <config.h> /*包含板子的配置文件这里是100ask24x0.h*/
#include <version.h>

/*中断向量表,存放跳转到各个中断处理的指令*/
.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


_TEXT_BASE:             /*在链接脚本中定义的,值也在链接过程中制定值为0x33F80000*/
    .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

.globl FREE_RAM_END
FREE_RAM_END:
    .word   0x0badc0de

.globl FREE_RAM_SIZE
FREE_RAM_SIZE:
    .word   0x0badc0de

.globl PreLoadedONRAM
PreLoadedONRAM:
    .word   0

/*如果使用中断或者快中断需要定义栈空间*/
#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


/*
    正式开始reset中断向量代码讲解
    当软件重启或者硬件重启后从reset开始执行
*/
reset:
    /*
     * set the cpu to SVC32 mode
     */
    mrs r0,cpsr         /*将cpsr读入到r0*/
    bic r0,r0,#0x1f     /*将低5位全部清0*/
    orr r0,r0,#0xd3     /*0xd3= 11010011关闭IRQ,FIQ,置CPU为ARM状态,CPU为SVC模式*/
    msr cpsr,r0         /将修改后的r0存入cpsr

/* 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) /*宏定义了相关的相关寄存器的地址,具体请查看S3C2440的手册*/
·   #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         /*将看门狗的寄存器地址放到r0中*/
    mov     r1, #0x0            /*将r1置0*/
    str     r1, [r0]            /*将看门狗寄存器置全0*/

    mov r1, #0xffffffff
    ldr r0, =INTMSK
    str r1, [r0]                /*设置中断屏蔽寄存器,屏蔽所有中断*/

#if defined(CONFIG_S3C2410)
    ldr r1, =0x3ff
    ldr r0, =INTSUBMSK         /*同上,屏蔽一些次级中断*/
    str r1, [r0]
#endif

#endif  /* CONFIG_S3C2400 || CONFIG_S3C2410 */


/*对于从FLASH启动,下面代码会执行*/

    /* r0 <- current position of code   */ /*根据当前PC的值计算出_start代表的地址,相对寻址,与位置无关*/
    adr r0, _start          
    ldr r1, _TEXT_BASE  /*操作后r1=0X33F80000*/    
    /* test if we run from flash or RAM */ 
    cmp     r0, r1    
    /*从flash启动,跳转到cpu_init_crit,具体操作在下面介绍*/      
    blne    cpu_init_crit   /*cpu_init_crit     在下面分析*/



/*在将完整uboot从NAND FLASH复制到RAM之前,留出一些空间做其它功能之用*/
stack_setup:
    ldr r0, _TEXT_BASE              /*在_TEXT_BASE下方预留出其它功能的区域*/
    sub r0, r0, #CFG_MALLOC_LEN    /* malloc area留出malloc区域*/

    /* 留出128字节空间存放global data 和board info*/
    sub r0, r0, #CFG_GBL_DATA_SIZE  

#ifdef CONFIG_USE_IRQ
    /*留出IRQ和FIQ栈的地址*/
    sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
    sub sp, r0, #12     /* leave 3 words for abort-stack    */

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    /*进行FCLK:HCLK:PCLK时钟设置,函数在boot_init.c中这里不介绍*/
    bl clock_init      
#endif    

/*开始复制uboot到RAM中*/
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:               /* relocate U-Boot to RAM       */

   /* r0 <- current position of code   */
   /*前面解释过adr是相对寻址,实现位置无关,目前代码开始执行的起始位置,这里为0*/
    adr r0, _start      
    ldr r1, _TEXT_BASE      

    /* test if we run from flash or RAM *//*需要重新定位到的地址*/
    cmp     r0, r1                 
    /* dont reloc during debug         */
    beq     clear_bss

    ldr r2, _armboot_start
    ldr r3, _bss_start

    /* r2 <- size of armboot  计算得到除了BSS段外整个uboot的大小 */
    sub r2, r3, r2      

    /*调用NAND FLASH的read函数,将代码从FLASH写入到SDRAM _TEXT_BASE处*/
    /* r0: source, r1: dest, r2: size */ 
    bl  CopyCode2Ram    

#endif  /* CONFIG_SKIP_RELOCATE_UBOOT */

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             /*将bss段的内容全部清零*/

SetLoadFlag:
    /* Set a global flag, PreLoadedONRAM */
    adr r0, _start          /* r0 <- current position of code   */
    ldr r1, _TEXT_BASE      /* test if we run from flash or RAM */
    cmp     r0, r1          /* dont reloc during debug         */
    ldr r2, =PreLoadedONRAM /*r2中是PreLoadedONRAM全局变量的地址*/
    mov r3, #1

    /*如果相等,设置PreLoadedONRAM为1,表示从RAM中启动*/
    streq r3, [r2]        

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

_start_armboot: .word start_armboot
cpu_init_crit:
    /*
     * flush v4 I/D caches
     */
    mov r0, #0
    mcr p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache *//*清除I-cache,D-cache*/
    mcr p15, 0, r0, c8, c7, 0   /* flush v4 TLB */     /*清除所有的TLB*/

    /*
     * disable MMU stuff and caches
     */

    mrc p15, 0, r0, c1, c0, 0           /*先从协处理器中,读出C1寄存器的值*/

    /*设置中断向量的从0x00000000,关闭MMU*/
    bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)

    /*disable MMU,DCACHE,ALIGNMENT*/
    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    /*使能I-cache*/
    mcr p15, 0, r0, c1, c0, 0                           /*将r0的值写C1*/

    mov ip, lr         /*暂存lr*/
    bl  lowlevel_init  /*配置SDRAM*/
    mov lr, ip
    mov pc, lr

以上关于协处理器的操作,如果有不明白的地方请参考 ARM920T TRM,里面有详细的描述,这里不再展开叙述。

.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
    ldr r1, _TEXT_BASE
    sub r0, r0, r1  /*计算出SMRDATA和_TEXT_BASE之间的偏移,因为现在是从0地址开始运行,所以偏移就是目前SMRDATA的地址*/
    ldr r1, =BWSCON /* Bus Width Status Controller */
    add     r2, r0, #13*4 /*跟SDRAM相关的寄存器共13个,每个4字节*/
0:
    ldr     r3, [r0], #4  /*r0中存放配置放置的地址*/
    str     r3, [r1], #4   /*r1中存放的是BWSCON寄存器的地址*/
    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 0xb1
    .word 0x30
    .word 0x30

上面大致介绍了uboot的启动过程的汇编代码分析,主要做了如下的几件事情

  1. 设置CPU 工作模式为SVC,关闭IRQ和FIQ
  2. 关闭看门狗,置位中断屏蔽寄存器器关闭所有中断
  3. 清除I-cache,D-cache,TLB,关闭MMU等
  4. 配置RAM,为后面复制FLASH中uboot到RAM做准备
  5. uboot代码重定位
  6. 重定位后,赋值PC指针,直接跳转到搬移后的位置开始执行

分析了start.S以后,下一篇接着分析start_armboot

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值