Chinaunix首页 | 论坛 | 博客
  • 博客访问: 34227
  • 博文数量: 17
  • 博客积分: 770
  • 博客等级: 军士长
  • 技术积分: 190
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-29 10:18
文章分类

全部博文(17)

文章存档

2010年(1)

2009年(6)

2008年(10)

我的朋友
最近访客

分类: LINUX

2008-11-14 17:50:27

#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_startuboot 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   关闭MMUCACHE

  #endif

// 进行重定位 首先要判断是不是ram启动,相等就是在ram运行就不用重新定位

_start当前代码的首地址  _TEXT_BASE是代码在ram中的位置

#ifndef CONFIG_SKIP_RELOCATE_UBOOT

/*这里要说下adr 和ldr 有什么不同adr 是sub r0, pc, #offset 
是利用pc值和偏移地址相减得到,所以在flash运行为0
在ram运行就为_TEXT_BASE的地址如果用ldr则两次的结果
是一样的ldr 是从内存中读取取数据并赋值给r1*/

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

       adr       r0, _start        /* r0 <- current position of code   当前运行代码的起始地址*/

       ldr       r1, _TEXT_BASE        

/* BOOTRAM中运行地址 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_startuboot bss段起始地址

       sub  r2, r3, r2        /* r2 <- size of armboot     uboot的大小       */

       add  r2, r0, r2        /* r2 <- source end address    大小加上开始地址就是结束的地址     */

 

 

// 汇编中的代码复制主要掌握

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

//IRQFIQ模式的栈 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

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