Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1071545
  • 博文数量: 277
  • 博客积分: 8313
  • 博客等级: 中将
  • 技术积分: 2976
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-22 11:25
文章分类

全部博文(277)

文章存档

2013年(17)

2012年(66)

2011年(104)

2010年(90)

我的朋友

分类: LINUX

2011-07-04 16:35:23

Uboot启动分析
uboot\cpu\s3c44b0\start.S

.globl _start //这个伪操作将这个symbol作为全局符号暴露给连接器(linker),这个符号可以是定义的一个独立的模块。

_start:     b       reset

       add  pc, pc, #0x0c000000

       add  pc, pc, #0x0c000000

       add  pc, pc, #0x0c000000

       add  pc, pc, #0x0c000000

       add  pc, pc, #0x0c000000

       add  pc, pc, #0x0c000000

       add  pc, pc, #0x0c000000

    (仅仅处理7个中断)

       .balignl 16,0xdeadbeef //填充标志位0xdeadbeef

 

/*

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

 *

 * Startup Code (reset vector)

 *

 * do important init only if we don't start from memory!

 * relocate u-boot to ram

 * setup stack

 * jump to second stage

 *

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

 */

 

_TEXT_BASE:// _TEXT_BASE是编译器连接过来的值,原型是board/mrtos/config.mk里定义的TEXT_BASE = 0x0C700000

       .word      TEXT_BASE// /*TEXT_BASE这个值存储在当前位置,_TEXT_BASE是换在c中理解得话,就是一个指针,指向TEXT_BASE存储的位置,在汇编的准确定义是叫标号,标志TEXT_BASE的存储位置 */

 

.globl _armboot_start

_armboot_start:

       .word _start //_start存储到当前位置,并且用标号_armboot_start标记,也就是定义_armboot_start指针指向词值,并且这个指针值可以冰编译器引用。

 

 

/*

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

 */

.globl _bss_start

_bss_start:

       .word __bss_start  //这个值__2个下划线)bss_start 是编译器编译uboot的时候产生的,用_(一个下划线)bss_start标记,引用。

 

.globl _bss_end

_bss_end:

       .word _end //这个值_end 是编译器编译uboot的时候产生的,用_bss_end标记,引用。

 

 

#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:  //reset代码段

       /*

        * set the cpu to SVC32 mode

        */

       mrs  r0,cpsr

       bic   r0,r0,#0x1f

       orr   r0,r0,#0x13

       msr  cpsr,r0

       /*

        * we do sys-critical inits only at reboot,

        * not when booting from ram!

        */

//判断是否要初始化CPU等,区分调试运行还是XIP

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

       bl    cpu_init_crit

       /*

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

        */

       bl    lowlevel_init

#endif

 

 

//重载uboot,将uboot拷贝到ram区间执行,为什么要怎么做,有一个重要原因因为,在uboot运行过程中,用户需要烧写参数到flash,所以必须将程序运行在ram区,这样才能控制flash区间的擦写。

#ifndef CONFIG_SKIP_RELOCATE_UBOOT

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

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

           //如果程序从flash启动,_start值为0

           //如果程序被用户以调试方式加载,如用户设定0x0c000800,则_start值为0x0c000800          

       ldr   r1, _TEXT_BASE         /* test if we run from flash or RAM */

           //重载代码的目标位置

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

           //比较程序的实际开始位置与重载目标位置,如果一致,则无需copy,否则执行stack_setup

       beq     stack_setup   //相等直接跳到设置堆栈代码段,忽略代码重载部分

 

 

       ldr   r2, _armboot_start  //不相等

       ldr   r3, _bss_start

       sub  r2, r3, r2        /* r2 <- size of armboot            */

       add  r2, r0, r2        /* r2 <- source end address         */

    //计算uboot代码的实际结束地址,_start+_bss_start-_armboot_start   

copy_loop:

       ldmia      r0!, {r3-r10}         /* copy from source address [r0]    */

    //r0的位置copy n个数据到 r3 -r10这几个寄存器,r0自动加n

       stmia       r1!, {r3-r10}         /* copy to   target address [r1]    */

   //r3 -r10这几个寄存器 copy n个数据到 r1指向的开始的位置r1自动加n.

       cmp r0, r2                    /* until source end addreee [r2]    */

   //判断r0 是否copy完成

       ble   copy_loop  //循环

 

//中断矢量重载

//将中断重定义到0x0c000000的位置,也就是RAM的起始位置

/*

       now copy to sram the interrupt vector

*/

       adr   r0, real_vectors

       add  r2, r0, #1024

       ldr   r1, =0x0c000000

       add  r1, r1, #0x08 //注意,这里的地址变为0x0c000008咯

vector_copy_loop:

       ldmia      r0!, {r3-r10}

       stmia       r1!, {r3-r10}

       cmp r0, r2

       ble   vector_copy_loop

#endif     /* CONFIG_SKIP_RELOCATE_UBOOT */

//参考上一段

 

 

       /* Set up the stack                                         */

stack_setup:

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

    //堆栈的结束地址_TEXT_BASE   

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

//分配CONFIG_SYS_MALLOC_LEN 区间。

 

       sub  r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo                        */

    //分配CONFIG_SYS_GBL_DATA_SIZE 区间。

#ifdef CONFIG_USE_IRQ

       sub  r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

     //分配CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ区间

#endif

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

    // 12bytes冗余区间,赋值堆栈的起始位置   

       ldr   pc, _start_armboot

   // 跳转到start_armboot c代码)

_start_armboot:      .word start_armboot

 

 

/******************************************************************** CPU_init_critical临界区寄存器
设置一些重要的寄存器,并进行内存测试。
*******************************************************************/

#define INTCON (0x01c00000+0x200000) /* 中断控制器 */
#define INTMSK (0x01c00000+0x20000c) 
/* 
中断控制屏蔽寄存器 */
#define LOCKTIME (0x01c00000+0x18000c)
#define PLLCON (0x01c00000+0x180000)
#define CLKCON (0x01c00000+0x180004)
#define WTCON (0x01c00000+0x130000)

cpu_init_crit:

          /* 关闭看门狗 */
          ldr           r0, =WTCON
          ldr          r1, =0x0

          str          r1, [r0]

          /** 清除所有中断位,设置INTMRs实现。*/
          ldr          r1,=INTMSK
          ldr          r0, =0x03fffeff
          str          r0, [r1]
          ldr          r1, =INTCON
          ldr          r0, =0x05
          str          r0, [r1]

          /* 设置时钟控制寄存器 */
          ldr          r1, =LOCKTIME
          ldrb          r0, =800
          strb          r0, [r1]

          /* 设置锁相环,控制CPU运行速度。 */
          ldr          r1, =PLLCON

#if CONFIG_S3C44B0_CLOCK_SPEED==60

       ldr   r0, =0x88042 /* 60MHz (Quartz=10MHz) */

#elif CONFIG_S3C44B0_CLOCK_SPEED==75

       ldr   r0, =0xac042  /* 75MHz  */

#else

# error CONFIG_S3C44B0_CLOCK_SPEED undefined

#endif
          str          r0, [r1]
          ldr          r1,=CLKCON
          ldr          r0, =0x7ff8
          str          r0, [r1]

          /* 调用子函数返回 */
          mov          pc, lr

/*************************************************/
/*          
实际的中断向量表          */
/*************************************************/

real_vectors:
          b          reset
          b          undefined_instruction
          b          software_interrupt
          b          prefetch_abort
          b          data_abort
          b          not_used
          b          irq
          b          fiq
/*************************************************/

undefined_instruction:
          mov          r6, #3
          b          reset

software_interrupt:
          mov          r6, #4
          b          reset

prefetch_abort:
          mov          r6, #5
          b          reset

data_abort:
          mov          r6, #6
          b          reset

not_used:
 
         /* we *should* never reach this */
          mov          r6, #7
          b          reset
irq:
          mov          r6, #8
          b          reset
fiq:
          mov          r6, #9
          b          reset

 

总结:uboot这样挑来跳去,确实不好懂,不过可以画一个图,就很明了了

 

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