1 .text 2 .global _start 3 4 _start: 5 b reset /* vector 0 : reset */ 6 ldr pc, und_addr /* vector 4 : und 此时又跳回到4k flash中 */ 7 8 /* 这个操作是为了防止start.S超过4K内存 */ 9 und_addr: 10 .word do_und 11 12 do_und: 13 /* 执行到这里之前: 14 * 1. lr_und保存有被中断模式中的下一条即将执行的指令的地址 15 * 2. SPSR_und保存有被中断模式的CPSR 16 * 3. CPSR中的M4-M0被设置为11011, 进入到und模式 17 * 4. 跳到0x4的地方执行程序 18 */ 19 20 /* sp_und未设置, 先设置它 这个sp是und特有的sp*/ 21 ldr sp, =0x34000000 22 23 /* 在und异常处理函数中有可能会修改r0-r12, 所以先保存 */ 24 /* lr是异常处理完后的返回地址, 也要保存 */ 25 stmdb sp!, {r0-r12, lr} 26 27 /* 保存现场 */ 28 /* 处理und异常 */ 29 mrs r0, cpsr 30 ldr r1, =und_string 31 bl printException 32 33 /* 恢复现场 */ 34 ldmia sp!, {r0-r12, pc}^ /* ^会把spsr的值恢复到cpsr里 */ 35 36 und_string: 37 .string "undefined instruction exception" 38 39 .align 4 40 41 reset: 42 /* 关闭看门狗 */ 43 ldr r0, =0x53000000 44 ldr r1, =0 45 str r1, [r0] 46 47 /* 设置MPLL, FCLK : HCLK : PCLK = 400m : 100m : 50m */ 48 /* LOCKTIME(0x4C000000) = 0xFFFFFFFF */ 49 ldr r0, =0x4C000000 50 ldr r1, =0xFFFFFFFF 51 str r1, [r0] 52 53 /* CLKDIVN(0x4C000014) = 0X5, tFCLK:tHCLK:tPCLK = 1:4:8 */ 54 ldr r0, =0x4C000014 55 ldr r1, =0x5 56 str r1, [r0] 57 58 /* 设置CPU工作于异步模式 */ 59 mrc p15,0,r0,c1,c0,0 60 orr r0,r0,#0xc0000000 //R1_nF:OR:R1_iA 61 mcr p15,0,r0,c1,c0,0 62 63 /* 设置MPLLCON(0x4C000004) = (92<<12)|(1<<4)|(1<<0) 64 * m = MDIV+8 = 92+8=100 65 * p = PDIV+2 = 1+2 = 3 66 * s = SDIV = 1 67 * FCLK = 2*m*Fin/(p*2^s) = 2*100*12/(3*2^1)=400M 68 */ 69 ldr r0, =0x4C000004 70 ldr r1, =(92<<12)|(1<<4)|(1<<0) 71 str r1, [r0] 72 73 /* 一旦设置PLL, 就会锁定lock time直到PLL输出稳定 74 * 然后CPU工作于新的频率FCLK 75 */ 76 77 78 79 /* 设置内存: sp 栈 */ 80 /* 分辨是nor/nand启动 81 * 写0到0地址, 再读出来 82 * 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动 83 * 否则就是nor启动 84 */ 85 mov r1, #0 86 ldr r0, [r1] /* 读出原来的值备份 */ 87 str r1, [r1] /* 0->[0] */ 88 ldr r2, [r1] /* r2=[0] */ 89 cmp r1, r2 /* r1==r2? 如果相等表示是NAND启动 */ 90 ldr sp, =0x40000000+4096 /* 先假设是nor启动 */ 91 moveq sp, #4096 /* nand启动 */ 92 streq r0, [r1] /* 恢复原来的值 */ 93 94 bl sdram_init 95 //bl sdram_init2 /* 用到有初始值的数组, 不是位置无关码 */ 96 97 /* 重定位text, rodata, data段整个程序 */ 98 bl copy2sdram 99 100 /* 清除BSS段 */ 101 bl clean_bss 102 103 104 ldr pc, =sdram 105 sdram: 106 bl uart0_init 107 108 bl print1 109 /* 故意加入一条未定义指令 */ 110 und_code: 111 .word 0xdeadc0de /* 未定义指令 */ 112 bl print2 113 114 //bl main /* 使用BL命令相对跳转, 程序仍然在NOR/sram执行 */ 115 ldr pc, =main /* 绝对跳转, 跳到SDRAM */ 116 117 halt: 118 b halt
代码整体跳转框图:
跳转过程:
1、一上电,CPU从0地址执行,执行 b reset(进行初始化操作)
2、重定位程序
3、跳转到sdram去继续执行
4、执行到 0xdeadc0de,发生未定义指令异常
5、跳转到异常向量表的 0x4 地址去执行
6、跳转到sdram上执行异常处理函数(do_und)
7、异常返回,继续执行