#include <config.h>
#include <version.h>
.globl _start //定义全局变量
_start: b reset ; //跳转到reset标号处,现在到那个地方look
//中断时候使用,产生中断时,跳到指定位置
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 //实现16位字节对齐,不对其用0xdeadbeef 补齐
/*跳过,由与上面那个指令跳到reset,我们就到那个位置看看,据了解,下面是定义一些变量之类的*/
_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
// 使得CPU进入管理模式,也就是cprs=****10011
reset:
mrs r0,cpsr ;/*cpsr-->r0*/
bic r0,r0,#0x1f ;/*r0=ro&&(~0x1f)*/
orr r0,r0,#0xd3 ;/*r0=r0|0xd3 */
msr cpsr,r0 ;/*ro-->cpsr*/
//没用到的信息,跳过,是针对S3C2400
#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
//关闭看门狗,等同于C语言的pWTCON =0x0
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
ldr r0, =pWTCON ;
mov r1, #0x0 ;
str r1, [r0] ; //pWTCON=0x0
//屏蔽所有中断,包括主中断屏蔽寄存器INTMSK,副中断屏蔽寄存器INTSUBMSK
mov r1, #0xffffffff
ldr r0, =INTMSK
str r1, [r0] ;// INTMSK=0xffffffff 主中断屏蔽寄存器共32位,置1表示屏蔽改为对应的中断
# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0] ;//INTSUBMSK=0x3ff 副中断有效位10,置1表示屏蔽改为对应的中断
# endif
//设置CPU与总线时钟的速度,一共有三个时钟源:FCLK,HCLK,PCLK,三者关系有CLKDIVN[1-0]位决定
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0] ; //CLKDIVN=x03------->>HCLK=FCLK/2 PCLK=HCLK/2
#endif
//主要对临界关键寄存器初始化,在重启时候才用到,如果从RAM中启动 则不执行
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit //调转到cpu_init_crit标号处
#endif
//重定向代码,实现的功能就是吧uboot代码搬到地址为 _TEXT_BASE地方
//也就是复制Uboot的整个代码都复制到SDRAM
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:
adr r0, _start //r0存放_start标号地址,也就是最上面的全局变量,程序开始的地方,表示当前运行代码起始地址,flash
ldr r1, _TEXT_BASE //将_TEXT_BASE 标号地址放到r1,0x33f80000
cmp r0, r1 // 判断r0和r1的值来看是否运行的代码是从flash开始的(0x00)
beq stack_setup //是从flash开始的,0x0
ldr r2, _armboot_start //r2=0x33f80000
ldr r3, _bss_start //r3=bss段起始地址
sub r2, r3, r2 /* r2 <- size of armboot */
add r2, r0, r2 /* r2 <- source end address */
//把0x0(r0)的代码全部复制到0x33f80000(r2)
copy_loop:
ldmia r0!, {r3-r10}
stmia r1!, {r3-r10}
cmp r0, r2
ble copy_loop
#endif /*
//设置堆栈
stack_setup:
ldr r0, _TEXT_BASE
sub r0, r0, #CFG_MALLOC_LEN //预留 #CFG_MALLOC_LEN-r0大小的堆为malloc()函数备用
sub r0, r0, #CFG_GBL_DATA_SIZE //为glabol_data数据结构预留,board.c
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) //为中断预留空间
#endif
sub sp, r0, #12 //将堆栈指针指向上面开辟的堆栈的下一个空间,作为栈顶指针
//将bss段用0清空
clear_bss:
ldr r0, _bss_start
ldr r1, _bss_end
mov r2, #0x00000000
//清空循环
clbss_l:str r2, [r0] */
add r0, r0, #4
cmp r0, r1
ble clbss_l
#if 0
//if0----endif为注销操作,可跳过
if 0
ldr r0, =pWTCON
mov r1, #0x0
str r1, [r0]
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
//设置好堆栈,可以跳到Uboot启动第二阶段,即C语言那边去啦。
ldr pc, _start_armboot
_start_armboot: .word start_armboot
/*
*************************************************************************
* 关于协处理器方面的
*还有缓冲
*************************************************************************
*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
/*
* 清除指令和数据缓存
*/
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
/*
*禁用MMU和缓存
*/
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 //13个控制器寄存器赋值,使得RAM空间可用,也是为uboot的第二阶段准备RAM空间,代码位于board/smdk2410/lowlevel.c
mov lr, ip
mov pc, lr //返回
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
uboot的作用:
1.设置CPU的工作模式为管理模式
2.关闭看门狗
3.屏蔽中断
4.设置CPU和总线的时钟FCLK相对于ARN929T而言,HCLK相对于AHB总线(ARM920T,内存控制器,中断控制器,LCD控制器,DMA和USB主模块使用),而PCLK相对于APB总线(外设:IIC\RTC\SPI\UART\GPIO)。
5.为加载uboot第二阶段准备ram空间
6.赋值uboot所有代码到RAM中