;/*******************************************************************************
; * bla.bla.bla
; ******************************************************************************/
//开始,列出了ARM处理器各种工作模式
.set Mode_USR, 0x10 // 用户模式
.set Mode_FIQ, 0x11 // 快速中断模式
.set Mode_IRQ, 0x12 // 中断模式
.set Mode_SVC, 0x13 // 管理模式
.set Mode_ABT, 0x17 // 中止模式
.set Mode_UND, 0x1B // 未定义模式
.set Mode_SYS, 0x1F // 系统模式
.set I_Bit, 0x80 //中断位, 这两位操作可以用来禁止或允许中断
.set F_Bit, 0x40 //快速中断位
;/*****************************************************************************/
.text
.code 32
.global _start //程序开始处,从这里开始运行
_start:
//接着是各种异常处理子程序,ARM有以下几种类型异常处理
//b 是跳转指令,这里跳转到reset处理子程序
b Reset_Handler //复位异常,处理器复位时,产生复位异常,程序跳转到复位异常处理处执行
b Undefined_Handler //未定义指令异常,当ARM处理器遇到不能处理指令时,产生未定义指令异常
b SWI_Handler //软件中断异常,由SWI指令产生
b Prefetch_Handler //指令预取异常,处理器预取指令不存在,或预取地址不允许当前指令访问,就会发生该异常
b Abort_Handler //数据中止异常,处理器指令访问数据的地址不存在,产生数据中止异常
nop
b IRQ_Handler //外部中断请求,CPSR 的I位为0, 才能产生IRQ异常
b FIQ_Handler //快速中断请求,CPSR 的F位为0,才能产生FIQ异常
.string "Copyright (c) STMicroelectronics. All Rights Reserved." //描述性字符串
.align 4 //4字节对齐
;/*****************************************************************************/
Reset_Handler: //复位处理子程序
mrc p15, 0, r1, c1, c0, 0 ; /* Get coprocessor special register */ //把协处理器p15的寄存器C0,C1中数据传入 ARM寄存器R1。
bic r1, r1, #0x1 ; /* MMU disable */ //清除R1的0x1位
orr r1, r1, #(0x1 << 12) ; /* Icache enable */ //R1的0x1<<12 位设置1,其它位不变,结果放入R1
orr r1, r1, #(0x1 << 2) ; /* Dcache enable */
bic r1, r1, #(0x1 << 3) ; /* Write buffer disable */ //R1的0x1<<3位清0
mcr p15, 0, r1, c1, c0, 0 ; /* Store processor special register */ //把R1的数据传回给协处理器P15的C0,C1寄存器
; /* Fill stack with pattern */
ldr r1,=__SP_START //将__SP_START加载到R1, __SP_START --- 栈STACK的起始地址
ldr r2,=__SP_END //将__SP_END加载到R2, __SP_END --- 栈STACK的结束地址
ldr r3,StackFill //将StackFill加载到R3,StackFill = 0xAAAAAAAA, 下面有定义
1:
cmp r1,r2 //比较R1和R2
stmltia r1!,{r3} //lt 表示前面比较r1 < r2 时,也就是__SP_START < __SP_END时,将R3的值保存到R1所指向的存储单元中,R1自动加1
blt 1b //r1 < r2时,跳转到前面的cmp,继续比较r1和r2, 因为R1不断+1,所以栈的每个位都会被初始化为StackFill
; /* Check to see if the backup RAM has our magic key. */
ldr r2, BackupRAM //将BackupRRAM 载入R2
ldr r1, MagicKey //将MagicKey 载入R1
ldr r0, [r2] //将BackupRAM地址中的数据载入R0
cmp r0, r1 //比较R0和R1
beq InitStacks //如果相等则跳转到InitStacks
str r1, [r2] //将R1中的值写入到R2寄存器值所指的存储器地址上,也就是BackupRAM所指的地址上
; /* Clear uninitialized data segment */
ldr r1,=__BSS_START //BSS起始地址
ldr r2,=__BSS_END //BSS末尾地址
mov r3,#0 //这R3用来实现清0 BSS区
1:
cmp r1,r2 //比较R1,R2
stmltia r1!,{r3} //如果R1<R2, 则把R3中的值写入R1值所指的存储单元, R1中的值+1
blt 1b //如果R1<R2, 跳转到前面最近的1处
;/***************************************************************************/
InitStacks:
msr CPSR_c, #(Mode_IRQ | I_Bit | F_Bit) //将 0x12 | 0x80 | 0x40 = 0xD2 写入CPSR_c,CPSR_c 是指CPSR的控制域部分
ldr sp,=__IRQ_STACK_INIT //跳入__IRQ_STACK_INIT
msr CPSR_c, #(Mode_FIQ | I_Bit | F_Bit)
ldr sp,=__FIQ_STACK_INIT
msr CPSR_c, #(Mode_SVC | I_Bit | F_Bit)
ldr sp,=__SVC_STACK_INIT
msr CPSR_c, #(Mode_ABT | I_Bit | F_Bit)
ldr sp,=__ABT_STACK_INIT
msr CPSR_c, #(Mode_UND| I_Bit | F_Bit)
ldr sp,=__UND_STACK_INIT
msr CPSR_c,#(Mode_SYS | I_Bit | F_Bit)
ldr sp,=__SP_END
.extern main //调用外部函数
b main
swi 0xFFFFFF //产生软中断指令,
Undefined_Handler:
mov r0,#'U' //字符U送入R0
b uart_out //跳转到UART 打印输出子程序
SWI_Handler:
mov pc, lr //跳转到链接寄存器,当之前执行BL调用时,LR得到PC的备份。
Prefetch_Handler:
mov r0,#'P'
b uart_out
Abort_Handler:
mov r0,#'A'
b uart_out
IRQ_Handler:
mov r0,#'I'
b uart_out
FIQ_Handler:
mov r0,#'F'
b uart_out
uart_out:
ldr r1,uart //uart 值是0x101FB000, 是UART1的数据寄存器地址,数据送到这个地址,就会打印到串口输出上
1:
str r0,[r1] //把R0的值,发送到R1的值所指的存储单元上,也就是0x101FB000 = R0.
b 1b
.global MagicKey //全局变量
BackupRAM: .word 0x80010000
MagicKey: .word 0x5aa555aa
StackFill: .word 0xAAAAAAAA
uart: .word 0x101FB000
.size _start, . - _start
.end