最近在学习Uboot,对其结构不清楚所以这篇文章还不错。
1、红色为汇编命令;棕色为gnu汇编命令;
蓝色
为寄存器;黑色为变量、常量、数字等;绿色为注释。
2、部分比较繁琐的注释用白色标出。
.globl _start
@将_start声明为“全局变量”,且可以被外部引用。globl: makes the symbol visible to ld,在别的程序中出现:ldr pc._star时,程序将跳转到这个地方执行
_start:
b
reset
@在_start行写入b reset语句
。
b指令就是无条件地跳到reset的地方运行
ldr
pc
,
_undefined_instruction
@LDR 指令用于从存储器中将一个32 位的字数据传送到目的寄存器中。该指令通常用于从存储器中读取32 位的字数据到通用寄存器,然后对数据进行处理。当程序计数器PC 作为目的寄存器时,指令从存储器中读取的数据被当作目的地址,从而可以实现程序流程的跳转。
@
当
发生中断
时
程序跳转到此行,程序将继续跳转到中断处理程序中执行。以下类同。我想一定是放在存储器0x00的位置,这样就可以系统可以根据中断向量的标号来找到跳转到对应的行。如中断向量是2,则会跳到
ldr pc, _prefetch_abort。
@ldr:load from memory into a register.
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
_undefined_instruction是一个标号,处理到这里时,as会把undefined_instruction的值按32bit(arm中的word指32位)的形式放在此标号处。
ldr pc, _undefined_instruction 就是从_undefined_instruction处取值,即undefined_instruction,并放入pc中。
*/
_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
/*上面这句,就是填充多少字节在后面。*/
.......
reset: //复位启动子程序
/* 设置CPU为SVC32模式 */
//ARM 微处理器支持程序状态寄存器访问指令,用于在程序状态寄存器
//和通用寄存器之间传送数据,程序状态寄存器访问指令包括以下两条:
//MRS 程序状态寄存器到通用寄存器的数据传送指令
//MRS{条件} 通用寄存器,程序状态寄存器(CPSR 或SPSR)
/*
MSR 通用寄存器到程序状态寄存器的数据传送指令
MSR{条件} 程序状态寄存器(CPSR 或SPSR)_<域>,操作数
MSR 指令用于将操作数的内容传送到程序状态寄存器的特定域中。其中,操作数可以为通用寄存器或立即数。<域>用于设置程序状态寄存器中需要操作的位,32 位的程序状态寄存器可分为4 个域:
位[31:24]为条件标志位域,用f 表示;
位[23:16]为状态位域,用s 表示;
位[15:8]为扩展位域,用x 表示;
位[7:0]为控制位域,用c 表示;
MSR CPSR_c , R0 ;传送 R0 的内容到 SPSR ,但仅仅修改 CPSR 中的控制位域
*/
mrs r0,cpsr
/*
BIC{条件}{S} 目的寄存器,操作数1,操作数2
BIC 指令用于清除操作数1 的某些位,并把结果放置到目的寄存器中。操作数 1 应是一个寄存器,操作数 2可以是一个寄存器,被移位的寄存器,或一个立即数。操作数 2 为 32位的掩码,如果在掩码中设置了某一位,则清除这一位。未设置的掩码位保持不变。
指令示例:
BIC R0 , R0 ,#% 1011 ;该指令清除 R0 中的位 0 、 1 、和 3 ,其余的位保持不变。
*/
bic r0,r0,#0x1f // 清除r0的低五位。
/*
ORR 指令的格式为:
ORR{条件}{S} 目的寄存器,操作数1,操作数2
ORR 指令用于 在两个操作数上进行逻辑或运算,并把结果放置到目的寄存器中。操作数 1应是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即数。该指令常用于设置操作数 1 的某些位。
指令示例:
ORR R0 , R0 ,# 3 ; 该指令设置 R0 的 0 、 1 位,其余位保持不变。
*/
orr r0,r0,#0xd3 // r0置位 d3=11010011
msr cpsr,r0 // r0写回cpsr
/*
COUNT EQU 0x40003100
LDR R1,=COUNT是将COUNT这个变量的地址,也就是0x40003100放到R1中。
*/
# define pWTCON 0x53000000
# define INTMSK 0x4A000008
# define CLKDIVN 0x4C000014
/* clock divisor register 此值来自于用户手册 */
//关闭看门狗
ldr r0, =pWTCON //把pWTCON的值装载到r0
mov r1, #0x0 // 0装载到r1
str r1, [r0] // 将0赋给r0指向的地址
// 禁止所有中断
//禁止主中断控制器
mov r1, #0xffffffff
//把
0xffffffff
装载到
r1
ldr r0, =INTMSK
//把
INTMSK
的值装载到r0
str r1, [r0]
// 将
0xffffffff
赋给
INTMSK
指向的地址
# if defined(CONFIG_S3C2410)
//禁止子中断控制器
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
设置CPU的频率
CLKDIVN寄存器的reset默认值是0x00000000,
第0位=0,PCLK=HCLK;第0位=1,PCLK=HCLK/2;
第1位=0,HCLK=FCLK;第1位=1,HCLK=FCLK/2;
这里 HCLK=FCLK/2,PCLK=HCLK/2;
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
MCR 指令的格式为:
MCR{条件} 协处理器编码,协处理器操作码1,源寄存器,目的寄存器1,目的寄存器2,协处
理器操作码2。
MCR 指令用于将ARM处理器寄存器中的数据传送到协处理器寄存器中,若协处理器不能成功完成操作,则产生未定义指令异常。其中协处理器操作码1 和协处理器操作码2为协处理器将要执行的操作,源寄存器为ARM 处理器的寄存器,目的寄存器1 和目的寄存器2 均为协处理器的寄存器。
指令示例:
MCR P3 , 3 , R0 , C4 , C5 , 6 ;该指令将 ARM 处理器寄存器 R0 中的数据传送到协处理器 P3 的寄存器 C4 和 C5 中。
5、MRC 指令
MRC 指令的格式为:
MRC{条件} 协处理器编码,协处理器操作码1,目的寄存器,源寄存器1,源寄存器2,协处理
器操作码2。
MRC 指令用于将协处理器寄存器中的数据传送到ARM处理器寄存器中,若协处理器不能成功完成操作,则产生未定义指令异常。其中协处理器操作码1 和协处理器操作码2为协处理器将要执行的操作,目的寄存器为ARM 处理器的寄存器,源寄存器1 和源寄存器2 均为协处理器的寄存器。
指令示例:
MRC P3 , 3 , R0 , C4 , C5 , 6 ;该指令将协处理器 P3 的寄存器中的数据传送到 ARM 处理器寄存器中.
cpu_init_crit:
/*
* flush v4 I/D caches
*/
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
mov lr, ip
mov pc, lr