SWI软中断
1 .text 2 .global _start 3 4 _start: 5 b reset /* vector 0 : reset */ 6 ldr pc, und_addr /* vector 4 : und */ 7 ldr pc, swi_addr /* vector 8 : swi */ 8 9 und_addr: 10 .word do_und 11 12 swi_addr: 13 .word do_swi 14 15 do_und: 16 /* 执行到这里之前: 17 * 1. lr_und保存有被中断模式中的下一条即将执行的指令的地址 18 * 2. SPSR_und保存有被中断模式的CPSR 19 * 3. CPSR中的M4-M0被设置为11011, 进入到und模式 20 * 4. 跳到0x4的地方执行程序 21 */ 22 23 /* sp_und未设置, 先设置它 */ 24 ldr sp, =0x34000000 25 26 /* 在und异常处理函数中有可能会修改r0-r12, 所以先保存 */ 27 /* lr是异常处理完后的返回地址, 也要保存 */ 28 stmdb sp!, {r0-r12, lr} 29 30 /* 保存现场 */ 31 /* 处理und异常 */ 32 mrs r0, cpsr 33 ldr r1, =und_string 34 bl printException 35 36 /* 恢复现场 */ 37 ldmia sp!, {r0-r12, pc}^ /* ^会把spsr的值恢复到cpsr里 */ 38 39 und_string: 40 .string "undefined instruction exception" 41 42 .align 4 43 44 do_swi: 45 /* 执行到这里之前: 46 * 1. lr_svc保存有被中断模式中的下一条即将执行的指令的地址 47 * 2. SPSR_svc保存有被中断模式的CPSR 48 * 3. CPSR中的M4-M0被设置为10011, 进入到svc模式 49 * 4. 跳到0x08的地方执行程序 50 */ 51 52 /* sp_svc未设置, 先设置它 */ 53 ldr sp, =0x33e00000 54 55 /* 保存现场 */ 56 /* 在swi异常处理函数中有可能会修改r0-r12, 所以先保存 */ 57 /* lr是异常处理完后的返回地址, 也要保存 */ 58 stmdb sp!, {r0-r12, lr} 59 60 mov r4, lr 61 62 /* 处理swi异常 */ 63 mrs r0, cpsr 64 ldr r1, =swi_string 65 bl printException 66 67 sub r0, r4, #4 /* 此时r0中存放的只是地址,地址指向swi 0x123 */ 68 bl printSWIVal 69 70 /* 恢复现场 */ 71 ldmia sp!, {r0-r12, pc}^ /* ^会把spsr的值恢复到cpsr里 */ 72 73 swi_string: 74 .string "swi exception" 75 76 .align 4 77 78 reset: 79 /* 关闭看门狗 */ 80 ldr r0, =0x53000000 81 ldr r1, =0 82 str r1, [r0] 83 84 /* 设置MPLL, FCLK : HCLK : PCLK = 400m : 100m : 50m */ 85 /* LOCKTIME(0x4C000000) = 0xFFFFFFFF */ 86 ldr r0, =0x4C000000 87 ldr r1, =0xFFFFFFFF 88 str r1, [r0] 89 90 /* CLKDIVN(0x4C000014) = 0X5, tFCLK:tHCLK:tPCLK = 1:4:8 */ 91 ldr r0, =0x4C000014 92 ldr r1, =0x5 93 str r1, [r0] 94 95 /* 设置CPU工作于异步模式 */ 96 mrc p15,0,r0,c1,c0,0 97 orr r0,r0,#0xc0000000 //R1_nF:OR:R1_iA 98 mcr p15,0,r0,c1,c0,0 99 100 /* 设置MPLLCON(0x4C000004) = (92<<12)|(1<<4)|(1<<0) 101 * m = MDIV+8 = 92+8=100 102 * p = PDIV+2 = 1+2 = 3 103 * s = SDIV = 1 104 * FCLK = 2*m*Fin/(p*2^s) = 2*100*12/(3*2^1)=400M 105 */ 106 ldr r0, =0x4C000004 107 ldr r1, =(92<<12)|(1<<4)|(1<<0) 108 str r1, [r0] 109 110 /* 一旦设置PLL, 就会锁定lock time直到PLL输出稳定 111 * 然后CPU工作于新的频率FCLK 112 */ 113 114 115 116 /* 设置内存: sp 栈 */ 117 /* 分辨是nor/nand启动 118 * 写0到0地址, 再读出来 119 * 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动 120 * 否则就是nor启动 121 */ 122 mov r1, #0 123 ldr r0, [r1] /* 读出原来的值备份 */ 124 str r1, [r1] /* 0->[0] */ 125 ldr r2, [r1] /* r2=[0] */ 126 cmp r1, r2 /* r1==r2? 如果相等表示是NAND启动 */ 127 ldr sp, =0x40000000+4096 /* 先假设是nor启动 */ 128 moveq sp, #4096 /* nand启动 */ 129 streq r0, [r1] /* 恢复原来的值 */ 130 131 bl sdram_init 132 //bl sdram_init2 /* 用到有初始值的数组, 不是位置无关码 */ 133 134 /* 重定位text, rodata, data段整个程序 */ 135 bl copy2sdram 136 137 /* 清除BSS段 */ 138 bl clean_bss 139 140 /* 复位之后, cpu处于svc模式 141 * 现在, 切换到usr模式 142 */ 143 mrs r0, cpsr /* 读出cpsr */ 144 bic r0, r0, #0xf /* 修改M4-M0为0b10000, 进入usr模式 */ 145 msr cpsr, r0 146 147 /* 设置 sp_usr */ 148 ldr sp, =0x33f00000 149 150 ldr pc, =sdram 151 sdram: 152 bl uart0_init 153 154 bl print1 155 /* 故意加入一条未定义指令 */ 156 und_code: 157 .word 0xdeadc0de /* 未定义指令 */ 158 bl print2 159 160 swi 0x123 /* 执行此命令, 触发SWI异常, 进入0x8执行 */ 161 162 //bl main /* 使用BL命令相对跳转, 程序仍然在NOR/sram执行 */ 163 ldr pc, =main /* 绝对跳转, 跳到SDRAM */ 164 165 halt: 166 b halt
注意第67行,其中r0中存放的只是地址,地址指向第160,所有r0中存放的不是0x123
因此,对于下面的两个函数:
向printHex函数传入的是整型数,实则传入的是r0的地址
此时打印出来的数值 (printHex)是r0的地址,
如果,printHex函数传入的参量是 指针的话,输出的就是r0地址中的数值
观察下面的反汇编代码:
此时就可以输出正确的结果: