今天犯了一个小错误,调试了几个小时;最后重新分析了几遍反汇编才发现。万丈高楼平地起、勿以浮沙驻高台。
.text
.global _start
_start:
b reset
ldr pc,=und_addr
ldr pc,=swi_addr
und_addr:
.word undef
swi_addr:
.word swi_handle
undef:
ldr sp,=0x32000000 //处理异常调用C函数,设置und模式下的栈,以前是usr模式
//保存现场
stmdb sp!,{r0-r12,lr}
bl print2
//处理异常
mrs r0,cpsr //und模式下的cpsr寄存器,也可以改为输出spsr低5位和usr模式的cpsr相同
ldr r1,=und_string
bl printException
//恢复现场
ldmia sp!,{r0-r12,pc}^
und_string:
.string "undefined instruction exception"
.align 4
swi_handle:
ldr sp,=0x33000000 //处理异常调用C函数,设置svc模式下的栈,以前是usr模式
//保存现场
stmdb sp!,{r0-r12,lr}
//处理异常
mrs r0,cpsr //und模式下的cpsr寄存器,也可以改为输出spsr低5位和svc模式的cpsr相同
ldr r1,=swi_string
bl printException
//恢复现场
ldmia sp!,{r0-r12,pc}^
swi_string:
.string "swi exception"
.align 4
reset:
//关看门狗
ldr r1,=0x53000000
ldr r0,=0
str r0,[r1]
//设置时钟
//① 设置锁定时间LOCKTIME
ldr r1,=0x4C000000
ldr r0,=0xFFFFFFFF
str r0,[r1]
//② 设置分频系数,使得FCLK:HCLK:PCLK = 8:4:1
ldr r1,=0x4C000014
ldr r0,=0x5
str r0,[r1]
//③ 根据2440规则,由于②中HDIVN!=0 -> CPU总线模式从快速总线模式到异步模式
mrc p15,0,r0,c1,c0,0
orr r0,r0,#0xc0000000 //R1_nF:OR:R1_iA
mcr p15,0,r0,c1,c0,0
//④ 设置PLL,设置完PLL后,PLL开始工作,锁定时间内CPU停止工作
/* 设置FCLK = 400MHZ,HCLK = 100MHZ, PCLK = 100MHZ
* Mpll(FCLK) = (2*m * Fin) / (p * 2^s)
* m = M(MDIV) (the value for divider M)+ 8,
* p = P(PDIV) (the value for divider P) + 2, s = SDIV
* MDIV = 92(0x5c), PDIV = 1 , SDIV = 1
* FCLK = (2*100*12MHZ) / (3*2^1) = 400MHZ */
ldr r1,=0x4C000004
ldr r0,= ((92<<12) | (1<<4) | (1<<0))
str r0,[r1]
//判断启动方式
mov r1,#0 // r1 = 0;
ldr r0,[r1] // r0 = [0];将0地址的值备份
str r1,[r1] // 将0写入0地址
ldr r2,[r1] // 再将0地址的值读出来给r2
cmp r1,r2 // 比较r1和r2,即比较0地址原来的值和写入的值
ldr sp,= 0x40000000 + 4096 // 先假设为nor启动
ldreq sp,= 4096 //如果r1==r2,假设不成立为Nand启动
streq r0,[r1] // 还原0地址以前的值
bl sdram_init
//bl sdram_init2 //用到有初始值的数组,不是位置无关码
bl copy2sdram
bl clean_bss
//从复位后的SVC模式切换到USR模式
//M[4:0] SVC:10011 USR:10000
mrs r0,cpsr
bic r0,r0,#0xf //修改低四位,进入usr模式
msr cpsr,r0
//设置usr模式下的栈,sp_usr
ldr sp,=0x34000000;
ldr pc,=sdram_next
sdram_next:
bl uart0_init
mrs r0,cpsr //SVC模式下的cpsr寄存器
bl print1
bl print2
swi 0x1 /* 执行此命令, 触发SWI异常, 进入0x8执行 */
und_code:
.word 0xeeadc0de /* 未定义指令 */
bl main /* 使用BL命令相对跳转, 程序仍然在NOR/sram执行 */
//ldr pc, =main /* 绝对跳转, 跳到SDRAM */
halt:
b halt
sdram.elf: file format elf32-littlearm
Disassembly of section .text:
30000000 <_start>:
30000000: ea00001e b 30000080
30000004: e59ff110 ldr pc, [pc, #272] ; 3000011c <.text+0x11c>
30000008: e59ff110 ldr pc, [pc, #272] ; 30000120 <.text+0x120>
3000000c :
3000000c: 30000014 andcc r0, r0, r4, lsl r0
30000010 :
30000010: 30000050 andcc r0, r0, r0, asr r0
*************************************************
3000011c: 3000000c andcc r0, r0, ip
30000120: 30000010 andcc r0, r0, r0, lsl r0
*************************************************
30000014 :
30000014: e3a0d432 mov sp, #838860800 ; 0x32000000
30000018: e92d5fff stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
3000001c: eb000103 bl 30000430
30000020: e10f0000 mrs r0, CPSR
30000024: e59f10f8 ldr r1, [pc, #248] ; 30000124 <.text+0x124>
30000028: eb000216 bl 30000888
3000002c: e8fd9fff ldmia sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}^
30000030 :
30000030: 65646e75 strvsb r6, [r4, #-3701]!
........
发生异常的时候,异常向量表中pc没有跳转到相应的执行函数地址,因为我采用了间接的赋值。两次异常都是跳转到und_addr或者swi_addr开始往后面执行,所以两次都执行了undef处理函数。
①直接赋值到对应执行函数处
.text
.global _start
_start:
b reset
ldr pc,=undef
ldr pc,=swi_handle
反汇编:
sdram.elf: file format elf32-littlearm
Disassembly of section .text:
***************************************
3000011c: 30000014 andcc r0, r0, r4, lsl r0
30000120: 30000050 andcc r0, r0, r0, asr r0
***************************************
30000000 <_start>:
30000000: ea00001e b 30000080
30000004: e59ff110 ldr pc, [pc, #272] ; 3000011c <.text+0x11c>
30000008: e59ff110 ldr pc, [pc, #272] ; 30000120 <.text+0x120>
3000000c :
3000000c: 30000014 andcc r0, r0, r4, lsl r0
30000010 :
30000010: 30000050 andcc r0, r0, r0, asr r0
30000014 :
30000014: e3a0d432 mov sp, #838860800 ; 0x32000000
30000018: e92d5fff stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
3000001c: eb000103 bl 30000430
30000020: e10f0000 mrs r0, CPSR
30000024: e59f10f8 ldr r1, [pc, #248] ; 30000124 <.text+0x124>
30000028: eb000216 bl 30000888
3000002c: e8fd9fff ldmia sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}^
30000030 :
...
30000050 :
30000050: e3a0d433 mov sp, #855638016 ; 0x33000000
...
② 间接赋值
.text
.global _start
_start:
b reset
ldr pc,und_addr
ldr pc,swi_addr
反汇编:
sdram.elf: file format elf32-littlearm
Disassembly of section .text:
30000000 <_start>:
30000000: ea00001e b 30000080
30000004: e59ff110 ldr pc, [pc, #272] ; 3000011c <.text+0x11c>
30000008: e59ff110 ldr pc, [pc, #272] ; 30000120 <.text+0x120>
*********************
3000011c: 30000014 andcc r0, r0, r4, lsl r0
30000120: 30000050 andcc r0, r0, r0, asr r0
*********************
3000000c :
3000000c: 30000014 andcc r0, r0, r4, lsl r0
30000010 :
30000010: 30000050 andcc r0, r0, r0, asr r0
30000014 :
30000014: e3a0d432 mov sp, #838860800 ; 0x32000000
30000018: e92d5fff stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
3000001c: eb000103 bl 30000430
30000020: e10f0000 mrs r0, CPSR
30000024: e59f10f8 ldr r1, [pc, #248] ; 30000124 <.text+0x124>
30000028: eb000216 bl 30000888
3000002c: e8fd9fff ldmia sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}^
30000030 :
...
30000050 :
30000050: e3a0d433 mov sp, #855638016 ; 0x33000000
...
注意ldr pc,=czg
与ldr pc,czg
用法:
① ldr pc,=czg
=》 pc = czg (就是czg标号的地址)
② ldr pc,czg
=》 pc = *(czg) (czg标号地址中放的值)