免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 879 | 回复: 0
打印 上一主题 下一主题

u-boot启动代码start.S(s3c2410)详解 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-11-14 17:50 |只看该作者 |倒序浏览

#include
#include
/*
*************************************************************************
*
* Jump vector table as in table 3.1 in [1]
*
*************************************************************************
//这段代码实现建立异常处理向量表,地址范围为0x0000 0000 ~ 0x0000 0020
.globl _start  /* b指令就是无条件地跳到reset的地方运行中断处理*/
_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
// .word就是把undefined_instruction 所在的地址给_undefined_instruction
_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
/*
*************************************************************************
*
* 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
*
*************************************************************************
// uboot映像在SDRAM中的重定位地址假设
_TEXT_BASE:
       .word      TEXT_BASE


// _start是程序入口链接完毕它的值应该是
这句话的意思应该是在_armboot_start标号处,保存了_start的值,
也就是说_armboot_start是存放_start的地址,_start 就是前面的定义的一个全局变量 取这个标号的地址    .word 符号只是符号的地址而不是值
.globl _armboot_start
          _armboot_start:
                 .word _start   
/* __bss_start是uboot 的bss段起始地址,uboot映像的大小就是__bss_start - _start
  __bss_start -_armboot_start*/
.globl _bss_start
          _bss_start:
                    .word __bss_start
.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:
           .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
       bic   r0,r0,#0x1f
       orr   r0,r0,#0xd3
       msr  cpsr,r0
/* 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 ! */
       ldr   r0, =CLKDIVN
       mov r1, #3
       str   r1, [r0]
#endif     /* CONFIG_S3C2400 || CONFIG_S3C2410 */
       //当是从FLASH启动时,就要进行内存测试,当是从RAM启动时,就可以跳过。
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
       bl     cpu_init_crit // 调用cpu_init_crit   关闭MMU和CACHE
  #endif
// 进行重定位 首先要判断是不是ram启动,相等就是在ram运行就不用重新定位
_start当前代码的首地址  _TEXT_BASE是代码在ram中的位置
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:                       /* relocate U-Boot to RAM        */
       adr       r0, _start        /* r0    当前运行代码的起始地址*/
       ldr       r1, _TEXT_BASE         
/* BOOT在RAM中运行地址 test if we run from flash or RAM */
       cmp     r0, r1                  /* don't reloc during debug         */
//比较两个地址是否相同,如果相同,就已经在RAM运行,否则就是FLASH中运行
       beq     stack_setup

       ldr   r2, _armboot_start  //_armboot_start   uboot的起始地址
       ldr   r3, _bss_start  //   __bss_start是uboot 的bss段起始地址
       sub  r2, r3, r2        /* r2      uboot的大小       */
       add  r2, r0, r2        /* r2     大小加上开始地址就是结束的地址     */


// 汇编中的代码复制主要掌握
copy_loop:
       ldmia       r0!, {r3-r10}         /* copy from source address [r0]  自动加1   */
       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  */
////设置栈,栈的设置灵活性较大,只要让SP寄存器指向一段没有使用的内存即可。
stack_setup:
       ldr   r0, _TEXT_BASE         
//* upper 128 KiB: relocated uboot   将_TEXT_BASE标号地址里的内容装载到r0中,这个是代码段的开始地址。
       sub  r0, r0, #CFG_MALLOC_LEN      
/* malloc area  代码段下面,留出一段内存以实现malloc                    */
       sub  r0, r0, #CFG_GBL_DATA_SIZE
/* bdinfo    留出一段内存,存一些全局参数。                 */
#ifdef CONFIG_USE_IRQ
//IRQ,FIQ模式的栈 CPU.c中才是真正的位IRQ FIQ划分栈
       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...                    */
       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
//通过该语句跳转到C代码执行
       ldr   pc, _start_armboot
// start_armboot位于 lib_arm/board.c 中,是一个系统初始化的接口函数
_start_armboot:      .word start_armboot


/*
*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************
*/
////cpu的初始化,如果没有定义CONFIG_SKIP_LOWLEVEL_INIT这个宏,则进行cpu,内存控制器,这个在调试阶段很有用,如果用已有的u-boot调试u-boot就可以用此方法,主要在include/configs/smdk2410.h定义这个宏,那么cpu,内存控制器就可以不被初始化了,直接跳转我们的C语言部分。

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
       /*
        * flush v4 I/D caches
MRC指令用于将协处理器寄存器中的数据传送到ARM处理器寄存器中
        */
       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  //准备RAM空间
       mov lr, ip
       mov pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

/*
*************************************************************************
*
* Interrupt handling
*
*************************************************************************
*/

@
@ IRQ stack frame.
@
#define S_FRAME_SIZE       72

#define S_OLD_R0       68
#define S_PSR       64
#define S_PC         60
#define S_LR         56
#define S_SP         52

#define S_IP          48
#define S_FP         44
#define S_R10       40
#define S_R9         36
#define S_R8         32
#define S_R7         28
#define S_R6         24
#define S_R5         20
#define S_R4         16
#define S_R3         12
#define S_R2         8
#define S_R1         4
#define S_R0         0

#define MODE_SVC 0x13
#define I_BIT 0x80

/*
* use bad_save_user_regs for abort/prefetch/undef/swi ...
* use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
*/

       .macro    bad_save_user_regs
       sub  sp, sp, #S_FRAME_SIZE
       stmia       sp, {r0 - r12}               @ Calling r0-r12
       ldr   r2, _armboot_start
       sub  r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
       sub  r2, r2, #(CFG_GBL_DATA_SIZE+8)  @ set base 2 words into abort stack
       ldmia       r2, {r2 - r3}                 @ get pc, cpsr
       add  r0, sp, #S_FRAME_SIZE             @ restore sp_SVC

       add  r5, sp, #S_SP
       mov r1, lr
       stmia       r5, {r0 - r3}                 @ save sp_SVC, lr_SVC, pc, cpsr
       mov r0, sp
       .endm

       .macro    irq_save_user_regs
       sub  sp, sp, #S_FRAME_SIZE
       stmia       sp, {r0 - r12}               @ Calling r0-r12
       add     r8, sp, #S_PC
       stmdb   r8, {sp, lr}^                   @ Calling SP, LR
       str     lr, [r8, #0]                    @ Save calling PC
       mrs     r6, spsr
       str     r6, [r8, #4]                    @ Save CPSR
       str     r0, [r8, #8]                    @ Save OLD_R0
       mov r0, sp
       .endm

       .macro    irq_restore_user_regs
       ldmia       sp, {r0 - lr}^                 @ Calling r0 - lr
       mov r0, r0
       ldr   lr, [sp, #S_PC]                     @ Get PC
       add  sp, sp, #S_FRAME_SIZE
       subs pc, lr, #4               @ return & move spsr_svc into cpsr
       .endm

       .macro get_bad_stack
       ldr   r13, _armboot_start              @ setup our mode stack
       sub  r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
       sub  r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack

       str   lr, [r13]                 @ save caller lr / spsr
       mrs  lr, spsr
       str     lr, [r13, #4]

       mov r13, #MODE_SVC               @ prepare SVC-Mode
       @ msr    spsr_c, r13
       msr  spsr, r13
       mov lr, pc
       movs      pc, lr
       .endm

       .macro get_irq_stack                   @ setup IRQ stack
       ldr   sp, IRQ_STACK_START
       .endm

       .macro get_fiq_stack                   @ setup FIQ stack
       ldr   sp, FIQ_STACK_START
       .endm

/*
* exception handlers
*/
       .align  5
undefined_instruction:
       get_bad_stack
       bad_save_user_regs
       bl    do_undefined_instruction

       .align       5
software_interrupt:
       get_bad_stack
       bad_save_user_regs
       bl    do_software_interrupt

       .align       5
prefetch_abort:
       get_bad_stack
       bad_save_user_regs
       bl    do_prefetch_abort

       .align       5
data_abort:
       get_bad_stack
       bad_save_user_regs
       bl    do_data_abort

       .align       5
not_used:
       get_bad_stack
       bad_save_user_regs
       bl    do_not_used

#ifdef CONFIG_USE_IRQ

       .align       5
irq:
       get_irq_stack
       irq_save_user_regs
       bl    do_irq
       irq_restore_user_regs

       .align       5
fiq:
       get_fiq_stack
       /* someone ought to write a more effiction fiq_save_user_regs */
       irq_save_user_regs
       bl    do_fiq
       irq_restore_user_regs

#else

       .align       5
irq:
       get_bad_stack
       bad_save_user_regs
       bl    do_irq

       .align       5
fiq:
       get_bad_stack
       bad_save_user_regs
       bl    do_fiq

#endif


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/83682/showart_1415123.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP