Chinaunix首页 | 论坛 | 博客
  • 博客访问: 183595
  • 博文数量: 82
  • 博客积分: 3005
  • 博客等级: 少校
  • 技术积分: 785
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-08 16:05
文章分类

全部博文(82)

文章存档

2012年(5)

2011年(18)

2010年(59)

我的朋友

分类: LINUX

2010-03-01 13:54:23

/*
 *  armboot - Startup Code for ARM920 CPU-core
 *
 *  Copyright (c) 2001 Marius Gr�ger <>
 *  Copyright (c) 2002 Alex Z�pke <>
 *  Copyright (c) 2002 Gary Jennejohn <>
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include
#include
#include
/*
 *************************************************************************
 *
 * Jump vector table as in table 3.1 in [1]
 *
 *************************************************************************
 */

.globl _start           //定义全局的标识符_start                           
_start: b       start_code     //无条件跳转指令,跳转到start_code 
 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

/*
 *************************************************************************
 *
 * Startup Code (called from the ARM reset exception vector)
 *
 * do important init only if we don't start from memory!
 * relocate armboot to ram
 * setup stack
 * jump to second stage
 *
 *************************************************************************
 */
_TEXT_BASE:
 .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
#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 start code
 */
start_code:
 /*
  * set the cpu to SVC32 mode
  */
 mrs r0,cpsr      //将程序状态寄存器cpsr的值放入寄存器r0
 bic r0,r0,#0x1f     //清除r0的低5位
 orr r0,r0,#0xd3     //将r0置位,0xd3=1101 0011,使cpsr为SVC模式
 msr cpsr,r0      //将r0写回到cpsr程序状态寄存器中
 bl coloured_LED_init
 bl red_LED_on
#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
 /*
  * relocate exception table
  */
 ldr r0, =_start
 ldr r1, =0x0
 mov r2, #16
copyex:
 subs r2, r2, #1
 ldr r3, [r0], #4
 str r3, [r1], #4
 bne copyex
#endif
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)   //CONFIG_S3C2410在fs2410.h中定义
 /* turn off the watchdog */
# if defined(CONFIG_S3C2400)
#  define pWTCON  0x15300000
#  define INTMSK  0x14400008 /* Interupt-Controller base addresses */
#  define CLKDIVN 0x14800014 /* clock divisor register */
#else
#  define pWTCON  0x53000000  //查看cpu芯片手册,查找相应的地址
#  define INTMSK  0x4A000008 /* Interupt-Controller base addresses */
#  define INTSUBMSK 0x4A00001C
#  define CLKDIVN 0x4C000014 /* clock divisor register */
# endif
 ldr     r0, =pWTCON    //将pWTCON这个变量的值所代表的地址装在到r0寄存器中
 mov     r1, #0x0    //将立即数0放到r1
 str     r1, [r0]    //将r1的值装入到r0所指定的地址,其实就是关闭看门狗     
 /*
  * mask all IRQs by setting all bits in the INTMR - default
  */
 mov r1, #0xffffffff    //将立即数0xffffffff放入到r1
 ldr r0, =INTMSK     //将INTMSK这个变量的值所代表的地址装载到r0寄存器中
 str r1, [r0]     //将r1的值装入到r0所指定的地址,其实就是屏蔽中断
# if defined(CONFIG_S3C2410)
 ldr r1, =0x7ff
 ldr r0, =INTSUBMSK
 str r1, [r0]     //和上面得过程一样,INTSUBMSK是一个11位的中断寄存器
 //add by farsight
 ldr r1,=0x50     //0x50=01010000 将GPF4 GPF6设置为1,点亮D12和D10
 ldr r0,=0x56000054
 str r1,[r0]      //将r1的值放到r0代表的地址,查数据手册可知0x56000054为GPFDAT
# endif
 /* FCLK:HCLK:PCLK = 1:2:4 */
 /* default FCLK is 120 MHz ! */
 ldr r0, =CLKDIVN    //将CLKDIVN这个变量的值所代表的地址装载到r0寄存器中
 mov r1, #3      //将立即数0x3=11放入r1寄存器
 str r1, [r0]     //对CLKDIVN寄存器的最低两位置位,查看数据手册可知HCLK=FCLK/2,PCLK=HCLK/2
         //HCLK->为AHB总线服务,应用于内存控制器、中断、LCD、DMA和USB
         //PCLK->为APB总线服务,应用于I2C、UART、GPIO、SPI和RTC
#endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */
 /*
  * we do sys-critical inits only at reboot,
  * not when booting from ram!
  */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
 bl cpu_init_crit
#endif
#ifdef CONFIG_AT91RM9200
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:    /* relocate U-Boot to RAM     */
 adr r0, _start  /* r0 <- current position of code   */
 ldr r1, _TEXT_BASE  /* test if we run from flash or RAM, _TEXT_BASE是代码在内存中的地址*/
 cmp     r0, r1                  /* don't reloc during debug         */
 beq     stack_setup   //如果从RAM启动,则直接跳到stack_etup代码执行
 ldr r2, _armboot_start  //r2既是uboot开始的地方
 ldr r3, _bss_start
 sub r2, r3, r2  /* r2 <- size of armboot            */
 add r2, r0, r2  /* r2 <- source end address         */
copy_loop:    //将ROM中的程序复制到RAM
 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 */
#endif
#ifdef CONFIG_S3C2440_NAND_BOOT
    @ reset NAND
    mov r1, #NAND_CTL_BASE
    ldr r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )
    str r2, [r1, #oNFCONF]
    ldr r2, [r1, #oNFCONF]
    ldr r2, =( (1<<4)|(0<<1)|(1<<0) ) @ Active low CE Control
    str r2, [r1, #oNFCONT]
    ldr r2, [r1, #oNFCONT]
    ldr r2, =(0x6) @ RnB Clear
    str r2, [r1, #oNFSTAT]
    ldr r2, [r1, #oNFSTAT]
   
    mov r2, #0xff @ RESET command
    strb r2, [r1, #oNFCMD]
  mov r3, #0 @ wait
nand1:
  add r3, r3, #0x1
  cmp r3, #0xa
  blt nand1
nand2:
  ldr r2, [r1, #oNFSTAT] @ wait ready
  tst r2, #0x4
  beq nand2

    ldr r2, [r1, #oNFCONT]
    orr r2, r2, #0x2 @ Flash Memory Chip Disable
    str r2, [r1, #oNFCONT]
@ get read to call C functions (for nand_read())
  ldr sp, DW_STACK_START @ setup stack pointer
  mov fp, #0 @ no previous frame, so fp=0
@ copy U-Boot to RAM
  ldr r0, =TEXT_BASE
  mov r1, #0x0
  mov r2, #0x30000
  bl nand_read_ll
  tst r0, #0x0
  beq ok_nand_read
bad_nand_read:
loop2: b loop2 @ infinite loop

ok_nand_read:
@ verify
  mov r0, #0
  ldr r1, =TEXT_BASE
  mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes
go_next:
  ldr r3, [r0], #4
  ldr r4, [r1], #4
  teq r3, r4
  bne notmatch
  subs r2, r2, #4
  beq stack_setup
  bne go_next
notmatch:
loop3: b loop3 @ infinite loop
#endif @ CONFIG_S3C2440_NAND_BOOT
#ifdef CONFIG_S3C2410_NAND_BOOT
@ reset NAND
  mov r1, #NAND_CTL_BASE
  ldr r2, =0xf830 @ initial value
  str r2, [r1, #oNFCONF]
  ldr r2, [r1, #oNFCONF]
  bic r2, r2, #0x800 @ enable chip
  str r2, [r1, #oNFCONF]
  mov r2, #0xff @ RESET command
  strb r2, [r1, #oNFCMD]

  mov r3, #0 @ wait
nand1:
  add r3, r3, #0x1
  cmp r3, #0xa
  blt nand1
nand2:
  ldr r2, [r1, #oNFSTAT] @ wait ready
  tst r2, #0x1
  beq nand2
  ldr r2, [r1, #oNFCONF]
  orr r2, r2, #0x800 @ disable chip
  str r2, [r1, #oNFCONF]
@ get read to call C functions (for nand_read())
  ldr sp, DW_STACK_START @ setup stack pointer
  mov fp, #0 @ no previous frame, so fp=0
@ copy U-Boot to RAM
  ldr r0, =TEXT_BASE
  mov r1, #0x0
  mov r2, #0x30000
  bl nand_read_ll
  tst r0, #0x0
  beq ok_nand_read
bad_nand_read:
loop2: b loop2 @ infinite loop

ok_nand_read:
@ verify
  mov r0, #0
  ldr r1, =TEXT_BASE
  mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes
go_next:
  ldr r3, [r0], #4
  ldr r4, [r1], #4
  teq r3, r4
  bne notmatch
  subs r2, r2, #4
  beq stack_setup
  bne go_next
notmatch:
loop3: b loop3 @ infinite loop
#endif @ CONFIG_S3C2410_NAND_BOOT

 /* Set up the stack          */
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    */
clear_bss:       
 ldr r0, _bss_start  /* find start of bss segment        */
 ldr r1, _bss_end  /* stop here                        */
 mov  r2, #0x00000000  /* clear                            */
//ARM的数据段包括初始化数据段data和未初始化数据段bss,这里是对未初始化数据段清零,从_bss_start开始
//不断往里充0,直到_bss_end为止
clbss_l:str r2, [r0]  /* clear loop...                    */
 add r0, r0, #4
 cmp r0, r1
 ble clbss_l
 ldr pc, _start_armboot     //将_start_armboot的地址放入PC寄存器,使程序跳转到_start_armboot执行,进入stage2 C语言部分
_start_armboot: .word start_armboot
.align 2
DW_STACK_START: .word STACK_BASE+STACK_SIZE-4
/*
 *************************************************************************
 *
 * CPU_init_critical registers
 *
 * setup important registers
 * setup memory timing
 *
 *************************************************************************
 */

#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 使无效ICaches和DCaches */
 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB 使无效指令、数据TLB */
 /*
  * disable MMU stuff and caches
  */
 mrc p15, 0, r0, c1, c0, 0   //读c1寄存器的值到r0寄存器,禁用MMU
 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   //写r0寄存器的值到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.
  */
 mov ip, lr  //LR(r14)存放的是但前程序的返回地址,把它放到IP寄存器(r12)临时保存一下,以后可以返回
#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
#else
 bl lowlevel_init  //跳转指令,保存当前的PC的内用到LR寄存器。跳转到board/fs2410/lowlevel_init.s
#endif
 mov lr, ip    //将刚才临时保存在IP寄存器中的地址返回,到LR中
 mov pc, lr    //将LR寄存器的值放到PC,子程序返回,接着前面的执行 
#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
阅读(583) | 评论(0) | 转发(0) |
0

上一篇:uboot board.c分析

下一篇:uboot 启动过程

给主人留下些什么吧!~~