历史上的今天
返回首页

历史上的今天

今天是:2025年02月06日(星期四)

正在发生

2020年02月06日 | ARM多种异常的处理

2020-02-06 来源:eefocus

ARM中的流水线分为:取值,译码,执行,仿存,回写这五步,SWI(软中断)和UND中断都出现在译码阶段,而其他5种中断都发生在执行阶段。SWI和UND异常两种处理方法步骤都差不多,但是如果是异常出现在执行阶段要怎么样处理呢?


int main()

 10 { 

 11     //发生异常时会进入异常模式跳转到0000 0004地址处理异常事件   

 12     unsigned long source_addr=data_abort_init();

 13     //异常事件处理函数

 14     printf("swi_souce addr is %xn",source_addr);

 15     //将异常处理地址的值放到0x60000004

 16     memcopy(0x60000010,source_addr,0x1000);

 17     

 18     enable_mmu();

 19     //内存映射将0x00000004映射到0x6000000004    

 20     __asm__ __volatile__( 

 21         "mov r0, #1n"

 22         "ldr r1, [r0]n"

 23      );

 24     printf("welcome back! n"); 

 25 

 26 

 27 }


如果代码中的汇编语言执行的时候将会发生DATA Abrot异常,将会到0x0000010地址区执行处理代码其中,处理执行的时候发生异常和处理译码时候的异常都大同小异。但是需要注意的是:

 1 

  2 int (*printf)(char *, ...) = 0xc3e114d8;

  3 

  4 void init_ttb(unsigned long *addr);

  5 void enable_mmu(void);

  6 unsigned long data_abort_init();

  7 void memcopy(unsigned long* dest,unsigned long* source,int len);

  8 

  9 int main()

 10 {

 11     //发生OBORT异常时会进入异常模式跳转到0000 0010地址处理异常事件  

 12     unsigned long source_addr=data_abort_init();

 13     //异常事件处理函数

 14     printf("swi_souce addr is %xn",source_addr);

 15     //将异常处理地址的值放到0x600000010

 16     memcopy(0x60000010,source_addr,0x1000);

 17 

 18     enable_mmu();

 19     //内存映射将0x00000004映射到0x6000000004    

 20     __asm__ __volatile__(

 21         "mov r0, #1n"

 22         "ldr r1, [r0]n"

 23      );

 24     printf("welcome back! n");

 25 

 26 

 27 }

 28 

 29 void memcopy(unsigned long* dest,unsigned long* source,int len)

 30 {

 31     int i=0;;

 32     for(i=0;i 33         dest[i]=source[i];

 34 }

 35 

 36 unsigned long  data_abort_init()

 37 {

 38     unsigned long source;

 39     __asm__ __volatile__(

 40 

 41          "ldr %0, =voliate_startn"

 42          : "=r" (source)

 43      );

 44 

 45 

 46     return source;

 47 

 48 }

 49 

 50 __asm__(

 51 

 52 "voliate_start:n"

 53     //跳转要分三部:

 54     //1:将PC保存到新模式下的lr中;

 55     //2:将CPSR保存在SPSR中

 56     //3:初始化SP

 57     //前两步由硬件完成,而第三部需要手动完成

 58      "sub lr, lr, #4n"

 59      "mov sp, #0x66000000n"//初始化SP

 60      "stmfd sp!, {r0-r12, lr}n"//初始化sp,入栈保护寄存器 

 61     //打印一句话 

 62      "ldr r0, =data_stringn"

 63      "ldr r2, shown"

 64      "blx r2n"

 65     //跳回来分两部

 66     //1:将CPSR保存在SPSR中

 67     //2:将PC保存到新模式下的lr中;

 68      "mov sp, #0x66000000n"//

 69      "ldmea sp, {r0-r12, pc}^n"// 

 70 

 71     "show:n"

 72      ".word 0xc3e114d8n"

 73 

 74      "data_string:n"

 75      ".asciz "hello DATA_ABORT!\n" n"

 76 

 77         );

 78 

 79 void init_ttb(unsigned long *addr)

 80 {

 81     unsigned long va = 0;//定义虚拟地址

 82     unsigned long pa = 0;//定义物理地址

 83 

 84     //40000000-------80000000   ====  40000000------80000000

 85     for(va=0x40000000; va<=0x80000000; va+=0x100000){

 86         pa = va;

 87         addr[va >> 20] = pa | 2;

 88         //|2的目的是将0-2位置为10此时将是小页模式4K

 89     }

 90 

 91     //00000000-------10000000   ====  60000000------70000000

 92     for(va=0x00000000; va<=0x10000000; va+=0x100000){

 93         pa = va+0x60000000;

94         addr[va >> 20] = pa | 2;

 95     }

 96 

 97     //10000000-------14000000   ====  10000000------14000000

 98     for(va=0x10000000; va<=0x30000000; va+=0x100000){

 99         pa = va;

100         addr[va >> 20] = pa | 2;

101     }

102 

103     //30000000-------40000000   ====  50000000------60000000

104     for(va=0x30000000; va<0x40000000; va+=0x100000){

105         pa = va + 0x20000000;

106         addr[va >> 20] = pa | 2;

107     }

108 }

109 

110 void enable_mmu(void)

111 

112 {

113     unsigned long addr = 0x70000000;

114     init_ttb(addr);

115     //step:初始化页表

116 

117     unsigned long mmu = 1 | (1 << 1) | (1 << 8);

118     //将MMU的第0,1,8位置1

119     __asm__ __volatile__(

120         "mov r0, #3n"

121         "MCR p15, 0, r0, c3, c0, 0n"//manager

122         "MCR p15, 0, %0, c2, c0, 0n"//addr  

123         "MCR p15, 0, %1, c1, c0, 0n"// enable mmu

124         :

125         : "r" (addr), "r" (mmu)

126         : "r0"

127     );

128     printf("MMU is enable!n");

129 }

观察处理模块中58行有一句   "sub lr, lr, #4n"特别要注意这句的重要性,是因为当程序执行发生错误的时候,调用PC-->LR   CPSR-->SPSR   LR--->PC   SPSR--->CPSR。而回来的时候PC却跑到了下一条指令去了。

如果很难理解的话,不妨先记得除了UND和SWI模式,其他的异常模式都需要在处理前将PC的指令前移动一位好了。


接下来是处理多种异常了,因为在实际中,只出现一种异常的情况很少,一般都是几种异常同时出现,假如是出现的是UND和DATAABORT异常,寄存器先会到04地址去处理UND,但是问题来了,假如处理处理UND异常的指令很长(因为一般不止6个字节),这时候又遇到了ABORT异常当到10地址取处理ABORT异常的时候,取到的却不是想要的值。


为了解决这个问题,在处理的时候我们对应构建一张异常向量表,当到对应地址去寻找解决异常的时候,B到对应的解决方法里去!实现一个二级的跳转,这样,多种异常同时来我也不怕不怕啦!

  1 

  2 int (*printf)(char *, ...) = 0xc3e114d8;

  3 

  4 void init_ttb(unsigned long *addr);

  5 void enable_mmu(void);

  6 unsigned long data_abort_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=data_abort_init();

 13     //异常事件处理函数

 14     printf("swi_souce addr is %xn",source_addr);

 15     //将异常处理地址的值放到0x60000004

 16     memcopy(0x60000000,source_addr,0x1000);

 17 

 18     enable_mmu();

 19     //内存映射将0x00000004映射到0x6000000004    

 20     __asm__ __volatile__(

 21         ".word 0x77777777n"

 22         "mov r0, #1n"

 23         "ldr r1, [r0]n"

 24      );

 25     printf("welcome back! n");

 26 

 27 

 28 }

 29 

 30 void memcopy(unsigned long* dest,unsigned long* source,int len)

 31 {

 32     int i=0;;

 33     for(i=0;i 34         dest[i]=source[i];

 35 }

 36 

 37 unsigned long  data_abort_init()

 38 {

 39     unsigned long source;

 40     __asm__ __volatile__(

 41          "ldr %0, =voliate_startn"

 42          : "=r" (source)

 43      );

 44 

 45 

 46     return source;

 47 

 48 }

 49 

 50 __asm__(

 51 

 52 "voliate_start:n"

 53     //跳转目录

 54     " b resetn"

 55     " b undefinedn"

 56     " b swin"

 57     " b pre_abtn"

 58     " b data_abtn"

 59     " .word 0n"//占位符号,一个位占4个字节

 60     " b irqn"

 61     " b fiqn"

 62 "n"

 63 

 64     //跳转要分三部:

 65     //1:将PC保存到新模式下的lr中;

 66     //2:将CPSR保存在SPSR中

 67     //3:初始化SP

 68     //前两步由硬件完成,而第三部需要手动完成

 69 "reset:n"

 70 

推荐阅读

史海拾趣

American Technical Ceramics (ATC)公司的发展小趣事

美国技术陶瓷公司(ATC,American Technical Ceramics)是一家专注于设计、制造和销售高性能技术陶瓷产品的公司。以下是关于ATC公司发展的五个相关故事:

  1. 公司成立与初期发展:美国技术陶瓷公司成立于1967年,总部位于美国纽约州的Huntington。公司最初以生产高质量的多层陶瓷电容器而闻名。在成立初期,ATC专注于开发陶瓷材料和制造工艺,确保产品具有优异的电气性能和可靠性,满足客户的需求。

  2. 技术创新与产品扩展:随着技术的发展和市场需求的变化,ATC不断进行技术创新,并扩展产品线。公司推出了一系列新产品,包括陶瓷电感器、滤波器、天线以及定制陶瓷元件等。这些产品在通信、航空航天、医疗、汽车等领域得到广泛应用。

  3. 国际业务拓展:为了满足全球客户的需求,ATC逐步拓展了国际业务。公司在亚洲、欧洲和其他地区设立了销售办事处和分支机构,建立了全球销售网络。通过与国际客户和合作伙伴的合作,ATC不断拓展市场份额,并加强了在全球市场的竞争力。

  4. 质量控制与认证:作为一家专注于高性能技术陶瓷产品的公司,ATC始终将质量放在首位。公司实施严格的质量控制措施,从原材料采购到生产制造、产品测试和交付都严格把关,确保产品符合客户的要求和行业标准。ATC的质量管理体系获得了ISO 9001认证,为客户提供了信心和保障。

  5. 持续创新与发展:随着电子行业的不断发展和技术的进步,ATC致力于持续创新和发展。公司不断投入研发,并与客户合作开发定制化的解决方案,以满足不断变化的市场需求。同时,ATC也积极关注可持续发展和环保责任,努力降低对环境的影响,并致力于推动绿色技术的发展。

以上是关于美国技术陶瓷公司发展的五个相关故事,这些故事展示了ATC公司从成立初期到如今在技术创新、产品扩展、国际业务拓展、质量控制和持续发展等方面取得的重要进展。

Daykin Electric Corp公司的发展小趣事

1969年,大金成功开发了一台室外机连接多台室内机的家用多联系统空调。这一创新产品不仅提高了空调的能效比,还满足了大型住宅和办公场所的多样化需求。多联系统空调的诞生,使得大金在家用中央空调领域取得了领先地位。

Goodwork Semiconductor ( GW )公司的发展小趣事
在通信基站、数据中心等场合,可控硅交流稳压器能够保护通信设备免受电压波动的影响,提高通信系统的稳定性和可靠性。
DCD [Digital Core Design]公司的发展小趣事

在快速变化的市场环境中,创新成为DCD公司持续发展的关键。公司不断加大研发投入,鼓励员工提出创新性的想法和建议。同时,公司还积极引进国内外先进的技术和管理经验,为公司的发展注入了新的活力。在创新驱动下,DCD公司不断推出具有竞争力的新产品和解决方案,赢得了客户的广泛赞誉和市场的持续认可。

Brite-Led Optoelectronics Inc公司的发展小趣事

随着市场竞争的加剧,Brite-Led意识到单凭自身力量难以持续保持领先。于是,公司积极寻求与其他企业和研究机构的合作研发机会。通过与一家知名高校的合作,Brite-Led成功开发出一种新型的LED封装技术,大幅提高了产品的可靠性和耐用性。这一合作不仅加强了Brite-Led的技术实力,也为其带来了更多的商业机会和合作伙伴。

Golledge Electronics公司的发展小趣事

随着市场竞争的加剧,Brite-Led意识到单凭自身力量难以持续保持领先。于是,公司积极寻求与其他企业和研究机构的合作研发机会。通过与一家知名高校的合作,Brite-Led成功开发出一种新型的LED封装技术,大幅提高了产品的可靠性和耐用性。这一合作不仅加强了Brite-Led的技术实力,也为其带来了更多的商业机会和合作伙伴。

问答坊 | AI 解惑

华为公司PCB设计规范

华为公司PCB设计规范…

查看全部问答>

关于09竞赛题目

本帖最后由 paulhyde 于 2014-9-15 09:15 编辑 各位兄弟姐妹们,09年全国电子设计大赛即将开始,大家都准备的如何了?这次大赛听说有重大改革?有没有人指导今年的出题方向啊?  …

查看全部问答>

成功将foonas-EM刷入ST Chip的LS2(转)

参考了“给我的Linkstation HDHLAN-120G换了硬盘刷了uboot(ST芯片)\"一文中31楼idhly的方法很有启发,一时手潮在我的ST Chip的LS2也成功地刷上了foonas-EM。具体方法如下 0) 首先备份原厂的flash:cat /dev/mtd1 > mtd1_kernel_initrd.bin 1) 准 ...…

查看全部问答>

pspice讲义

本帖最后由 paulhyde 于 2014-9-15 09:38 编辑 所用教材: 很可惜,这本书已经停印了,不过看本PPT应该可以入个门,现在很多只教画图,仿真,我觉得熟悉一下PSPICE的文本程序,还是很有用的,许多芯片公司提供PSPICE模型都是给文本模型的,才好看 ...…

查看全部问答>

走出选购门禁控制器的四误区

门禁控制器是门禁系统的核心部分,是门禁系统的灵魂。门禁控制器的质量和性能优劣直接影响着门禁系统的稳定性,而系统的稳定性会直接影响着门禁系统使用者的工作和生活秩序,甚至影响到生命和财产的安全。     目前中国市场上门禁控制 ...…

查看全部问答>

【分享帖】超详尽WinCE 6.0环境搭建过程图解

前段时间有朋友问wince的环境搭建方法,由于安装有一些需要注意的地方,直接用语言描述有诸多不便,今天整理了一个图片集,觉得说的比较明白了,需要的朋友看一看,也希望高手朋友们多完善,谢谢! PS: [广告,被屏蔽] 了解更多内容可登陆:[广 ...…

查看全部问答>

重烧内核之后初始化失败

正常情况下串口的信息: INFO: CReg2440Uart::CReg2440Uart using processor frequency reported by the OAL (66666666). INFO: CReg2440Uart::CReg2440Uart using processor frequency reported by the OAL (66666666). INFO: WAVEDEV.DLL: Set ...…

查看全部问答>

崩溃啊 求助!

我的毕设课题是基于单片机的红外接口设计,打算用proteus仿真,但是元件库里没有接口芯片max3100和收发芯片hdls3201,怎么办啊? 各位好心的大侠,帮帮忙吧!…

查看全部问答>

linux下中断处理问题

现有一外部中断,中断来临后要求驱动马上读取数据,现在问题是:中断来临后,怎么通知用户主动读取数据,现在我用的是使用了中断上下部,下部处理中断,一产生中断马上进入上半部分处理接收,并传送到用户空间,那么此时的读如果在没有中断时就一直 ...…

查看全部问答>

关于Windows CE实用开发技术 电子档 下载问题

以前的地址我由于更新网站已经改掉了。 Windows CE实用开发技术 电子档下载。 版权说明,本电子档版权归原书作者所有,下载仅供学习,请与下载后24小时删除。 保护合法版权,请购买正版书籍! 请勿多线程,保护本空间的速度! 谢谢!! 下载 ...…

查看全部问答>