历史上的今天
今天是:2025年02月06日(星期四)
2020年02月06日 | ARM4412中SWI中断
2020-02-06 来源:eefocus
在ARM中的流水线分为:取值,译码,执行,仿存,回写。这五步详细如下:

而主要发生异常情况主要集中在译码以及执行阶段。此次的SWI(软中断)和上次的UND中断都出现在译码阶段,而其他5种中断都发生在执行阶段。
在异常向量表中可以看见对应异常的模式以及SWI异常的描述如图,详细参考ARM架构手册第54以及58页


如下代码,当发生SWI中断异常
1 2 3 4 5 6 7 8 9 10 11 | 2 int (*printf)(char *, ...) = 0xc3e114d8; 3 4 int main() 5 { 6 __asm__ __volatile__( 7 "swi #88n" 8 ); 9 10 printf("welcome backn"); 11 } 12 |
此时,对应地异常向量表。ARM就会到0x00000008这个地址去取指令来处理软异常,和处理UND异常一样,实现跳转模式,处理异常(在这里,我们打印“hello swi”).然后再跳转回来。我们把这处理的指令存到SOURCE地址中,由MEMCOPY函数拷贝到0X60000008地址。然后触发异常,最后打印一句话,如果能打印“welcome back”则代表测试成功。
1
2 int (*printf)(char *, ...) = 0xc3e114d8;
3
4 void init_ttb(unsigned long *addr);
5 void enable_mmu(void);
6 unsigned long swi_init();
7 void memcopy(unsigned long* dest,unsigned long* source,int len);
8
9 int main()
10 {
11 //发生异常时会进入异常模式跳转到0000 0004地址处理异常事件
12 unsigned long source_addr=swi_init();
13 //异常事件处理函数
14 printf("swi_souce addr is %xn",source_addr);
15 //将异常处理地址的值放到0x60000004
16 memcopy(0x60000008,source_addr,0x100);
17
18 enable_mmu();
19 //内存映射将0x00000004映射到0x6000000004
20 __asm__ __volatile__(
21 "swi #88n"
22 );
23 printf("welcome back! n");
24
25
26 }
27
28 void memcopy(unsigned long* dest,unsigned long* source,int len)
29 {
30 int i=0;;
31 for(i=0;i 33 } 34 35 unsigned long swi_init() 36 { 37 unsigned long source; 38 __asm__ __volatile__( 39 "ldr %0, =swi_startn" 40 : "=r" (source) 41 ); 42 43 44 return source; 45 46 } 47 __asm__( 48 "swi_start:n" 49 50 51 //跳转要分三部: 52 //1:将PC保存到新模式下的lr中; 53 //2:将CPSR保存在SPSR中 54 //3:初始化SP 55 //前两步由硬件完成,而第三部需要手动完成 56 "mov sp, #0x66000000n"//初始化SP 57 "stmfd sp!, {r0-r12, lr}n"//初始化sp,入栈保护寄存器 58 59 //打印一句话 60 "ldr r0, =stringn" 61 "ldr r2, shown" 62 "blx r2n" 63 64 //跳回来分两部 65 //1:将CPSR保存在SPSR中 66 //2:将PC保存到新模式下的lr中; 67 "mov sp, #0x66000000n"// 68 "ldmea sp, {r0-r12, pc}^n"// 69 70 71 "loop:n" 72 "b loopn" 73 74 75 "show:n" 76 ".word 0xc3e114d8n" 77 78 "string:n" 79 ".asciz "hello SWI\n" n" 80 ".align 2n" 81 ); 82 83 void init_ttb(unsigned long *addr) 84 { 85 unsigned long va = 0;//定义虚拟地址 86 unsigned long pa = 0;//定义物理地址 87 88 //40000000-------80000000 ==== 40000000------80000000 89 for(va=0x40000000; va<=0x80000000; va+=0x100000){ 90 pa = va; 91 addr[va >> 20] = pa | 2; 92 //|2的目的是将0-2位置为10此时将是小页模式4K 93 } 94 95 //00000000-------10000000 ==== 60000000------70000000 96 for(va=0x00000000; va<=0x10000000; va+=0x100000){ 97 pa = va+0x60000000; 98 addr[va >> 20] = pa | 2; 99 } 100 101 //10000000-------14000000 ==== 10000000------14000000 102 for(va=0x10000000; va<=0x14000000; va+=0x100000){ 103 pa = va; 104 addr[va >> 20] = pa | 2; 105 } 106 107 //30000000-------40000000 ==== 50000000------60000000 108 for(va=0x30000000; va<0x40000000; va+=0x100000){ 109 pa = va + 0x20000000; 110 addr[va >> 20] = pa | 2; 111 } 112 } 113 114 void enable_mmu(void) 115 116 { 117 unsigned long addr = 0x70000000; 118 init_ttb(addr); 119 //step:初始化页表 120 121 unsigned long mmu = 1 | (1 << 1) | (1 << 8); 122 //将MMU的第0,1,8位置1 123 __asm__ __volatile__( 124 "mov r0, #3n" 125 "MCR p15, 0, r0, c3, c0, 0n"//manager 126 "MCR p15, 0, %0, c2, c0, 0n"//addr 127 "MCR p15, 0, %1, c1, c0, 0n"// enable mmu 128 : 129 : "r" (addr), "r" (mmu) 130 : "r0" 131 ); 132 printf("MMU is enable!n"); 133 } vim Makefile: 1 2 all: 3 arm-none-linux-gnueabi-gcc -c mmu.c -o mmu.o 4 arm-none-linux-gnueabi-ld -Ttext=0x41000000 mmu.o -o mmu 5 arm-none-linux-gnueabi-objcopy -Ielf32-littlearm -Obinary mmu mmu.bin 6 make 在minicom中dnw 41000000, 在终端中下载dnw 到板子,go 41000000 可以思考一下:怎么将SWI立即数打印出来?
上一篇:ARM多种异常的处理
史海拾趣
|
变频器是把工频电源(50Hz或60Hz)变换成各种频率的交流电源,以实现电机的变速运行的设备。如图1所示,其中控制电路完成对主电路的控制,整流电路将交流电变换成直流电,直流中间电路对整流电路的输出进行平滑滤波,逆变电路将直流电再逆变成交流电 ...… 查看全部问答> |
|
本帖最后由 paulhyde 于 2014-9-15 09:13 编辑 题记: 我平时懒于BBS的灌水,属于潜水一族,也看到很多人在毕业之际写一些心得 体会之类,我本不想写这些东东,自我感觉有点哗众取宠,但终究是写下了。文中 所述,仁者见仁,智者见智,同意或 ...… 查看全部问答> |
|
#include //51芯片管脚定义头文件 #include //内部包含延时函数 _nop_(); #define uchar unsigned char #define uint unsigned int uchar code FFW[8]={0xf1,0x ...… 查看全部问答> |
|
需求,一次信号周期20ms内采200个点,多路信号,需要把采来的数据存到ram里,一个信号大概需要1m左右的空间,我是初学单片机,刚学完51,现在会用ad采数据,和能过通串口上传数据,但不知道怎么选大点的ram,想用eeprom了,但又感觉他不是太适合,所 ...… 查看全部问答> |
|
你好,一家公司出了道面试题,用的是三星的128S64AA1显示模块, 要求把输出给这模块的中文显示信号转化成英文显示信号。 我不太了解,比如这模块的中文字库是怎么调用的, 谁了解这方面的内容吗,能谈下吗,有这方面的资料吗… 查看全部问答> |
|
这是射频与数模混合类PCB设计教程课件,希望对做高频电路的人们有所帮助 里面主要包括: 射频PCB布局与数模混合类PCB布局 无线终端PCB常用HDI工艺介绍 信号完整性(SI)的基础概念 射频PCB与数模 ...… 查看全部问答> |




