ARM多种异常的处理

发布者:CuriousObserver最新更新时间:2020-02-06 来源: eefocus关键字:ARM  多种异常 手机看文章 扫描二维码
随时随地手机看文章

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 

[1] [2]
关键字:ARM  多种异常 引用地址:ARM多种异常的处理

上一篇:qemu+chroot构建arm aarch64虚拟机
下一篇:ARM4412中SWI中断

推荐阅读最新更新时间:2024-11-12 16:57

Arm Tech Symposia 年度技术大会现已开放报名
作为 Arm® 最重要、规模最盛大的技术活动之一,Arm Tech Symposia 年度技术大会即将于 11 月 27 日、29 日及 12 月 1 日分别在深圳、北京、上海三城隆重举行。今年的技术大会回归线下,以“Arm 正在构建计算的未来”为主题,诚邀业内厂商、生态伙伴与开发者亲临现场,相互交流与学习,携手构建基于 Arm 技术的未来。 Arm Tech Symposia 将在三城带来超过 80 场主题演讲、技术分享与生态对话,并呈现丰富多样的现场演示。大会上午将由Arm高级副总裁及热门行业合作伙伴高管针对科技创新、产业发展带来主题演讲,共同畅谈产业趋势、技术洞察及前沿发展。 在 11 月 27 日的深圳场和 11
[嵌入式]
软银收购ARM 2018年7月前完成
   Softbank、ARM共同发出声明,确认将由Sofbank以240亿英镑价格收购ARM,预计最快将在2018年7月13日以前完成此项收购案。 ARM释出更具体说明内容,强调此次收购将促使Softbank、ARM加速双方在科技技术发展,同时也确认Softbank将以每股17英镑现金收购ARM,同时也预计在未来5年内于英国地区新增1500个工作职缺,海外市场也计画增加更多工作机会。 根据Softbank、ARM共同释出声明,确定将自2017年7月15日起由Softbank以240亿英镑收购ARM,预计最快将在2018年7月13日以前完成此笔收购。而根据Softbank说明表示,未来将协助ARM持续推动全球晶片事业发
[手机便携]
ARM JLINK与JTAG的不同
有以下两种做法: 1.在电脑上写一个服务程序,把IAR、KEIL和ADS中的RDI命令解析成相关的JTAG协议, 然后通后一个物理转换接口(注意,这个转换只是电气 物理层上的转换,就像RS232那样的作用)发送你的的目标板。H-JTAG就是这样的。H-JTAG的硬件就仅是一个物理电平的转换接口,所以很简单。 而电脑中装的h-JTAG软件就是前面说到的服务程序,负责协议转换的。 2.做一个板,用此板直接接收来自IAR、KEIL和ADS等软件的调试命令,由此板做RDI- JTAG协议的转换。然后与目标板通信,这就是JLINK的工作原理。 由上可以看出H-JTAG由于是软件作协议转换的,所以速度较慢,但是硬件简单。而第二种方
[单片机]
ARM-linux s3c2440 之时钟分析
S3c2440 时钟 & 电源管理时钟由三部分组成: Clock control ,USB control, 和 Power control Clock control 部分可以产生时钟FCLK,提供ARM内核,HCLK 提供 AHB 总线外设,还有 PLCK APB 总线外设。 s3c2440 有两个内置的PLLS 锁相环,一个提供给 FCLK,HCLK,和PCLK,另一个提供给USB时钟(48MHZ)。Clock control 可以不使用PLL,而降低的时钟,通过软件设置,时能各中种外设,从而可以降低功耗。 Power control部分,用于电能管理,有四种工作模式:Normal mode, Slow mode, Id
[单片机]
<font color='red'>ARM</font>-linux s3c2440 之时钟分析
英国与欧盟将对英伟达收购Arm展开深入调查
欧盟和英国市场监管机构正着手对英伟达以400亿美元并购Arm的交易展开深入调查。 据英国《金融时报》2月4日报道,布鲁塞尔和英国的官员均向媒体表示,鉴于Arm在芯片设计和制造领域极为重要的地位,对该交易进行详细审查是必要的。 一位了解该并购交易的直接相关者认为:“这笔交易的所有细节都将被一一审查,最终结果很可能是阻止这笔收购。”不过也有其他评论认为,该交易仍可以无条件通过或者有条件通过。 英伟达在去年9月宣布了这则巨额并购,全球半导体行业为之震动。目前这笔交易也面临着美国和中国监管机构的审查。英伟达和Arm的现持有者日本软银设定了18个月的交易期限。 目前来自英国和欧盟的调查仍处于初步阶段。 英国竞争与市场管理局(UK Com
[手机便携]
ARM7入门1,跑马灯实验
用keil uvision3和proteus做的程序。 主程序: /******************************************************************************/ /* This file is part of the uVision/ARM development tools */ /* Copyright KEIL ELEKTRONIK GmbH 2002-2004 */ /********************************************************************
[单片机]
<font color='red'>ARM</font>7入门1,跑马灯实验
软银巨亏7000亿日元,被迫贱卖arm?苹果、三星都是买家
日本首富孙正义持有的软银公司这几年因为投资不慎,巨亏了7000亿日元,日前传闻他准备卖掉收购来的ARM公司回血。作为全球最重要的移动CPU授权公司,谁来接手ARM是个难题,绯闻对象除了苹果之外,现在有消息称三星也在考虑。 苹果不仅是ARM早期的投资者之一,目前也可以说是ARM授权CPU界的一哥,不仅销量遥遥领先,自研的A系列处理器在性能上也是ARM阵营中最强的,再加上苹果本身富可敌国的资金,收购ARM是万事俱备,只欠东风,就看苹果自己愿意不愿意了。 除了苹果之外,日前韩国媒体报道称三星也是潜在的卖家,三星也不差钱,而且有先进的芯片代工技术,配合ARM的CPU授权也是如虎添翼。 对三星来说, 其半导体业务多年来过于
[嵌入式]
软银巨亏7000亿日元,被迫贱卖<font color='red'>arm</font>?苹果、三星都是买家
ARM下浮点数Middle-Endian问题的处理
摘要:本文描述了嵌入式GIS软件从X86平台移植到ARM体系结构平台的过程中遇到的浮点数存储字节顺序问题,并对该问题进行了详细分析,最终确定是ARM体系结构下浮点数的Middle-Endian存储问题,并提供了解决方案。   随着嵌入式微处理器芯片性能的日益提高,嵌入式设备也得到了广泛的应用。随着应用的扩展,嵌入式软件的开发也呈现出功能多样化、平台多样化和体系结构多样化等特点。   由于可移植性好,相当一部分嵌入式软件都是用C/C++语言开发的,而C/C++语言编写的程序中数据存储字节顺序是与编译平台所用的CPU相关的,所以嵌入式软件移植过程中,数据存储字节顺序是需要重点处理的地方。   在嵌入式GIS软件从X86体系结构下
[模拟电子]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved