SWI软中断

时间:2020-10-16
本文章向大家介绍SWI软中断,主要包括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地址中的数值

 

 观察下面的反汇编代码:

 

 此时就可以输出正确的结果:

 

$flag 上一页 下一页