对ARM的异常处理
来源:互联网 发布:cad面积计算软件 编辑:程序博客网 时间:2024/05/21 19:29
对ARM的异常处理
对ARM异常处理的研究务必要弄清楚以下几个方面: 异常类型,异常类型及处理该异常时CPU的执行模式,异常向量地址,异常处理过程 。
1、异常类型
(1)、复位(RESET)
a、当处理器复位引脚有效时,系统产生复位异常中断,程序跳转到复位异常中断处理程序处执行,包括系统加电和系统复位。
b、通过设置PC跳转到复位中断向量处执行称为软复位。
(2)、未定义的指令
当ARM处理器或者是系统中的协处理器认为当前指令未定义时,产生未定义的指令异常中断,可以通过改异常中断机制仿真浮点向量运算。
(3)、软件中断(SWI)
这是一个由用户定义的中断指令(SWI)。可用于用户模式下的程序调用特权操作指令。在实时操作系统中可以通过该机制实现系统功能调用。
(4)、指令与取终止(PrefechAbort)
如果处理器预取的指令的地址不存在,或者该地址不允许当前指令访问,当被预取的指令执行时,处理器产生指令预取终止异常中断。
(5)、数据访问终止(DATAABORT)
如果数据访问指令的目标地址不存在,或者该地址不允许当前指令访问,处理器产生数据访问终止异常中断。
(6)、外部中断请求(IRQ)
当处理器的外部中断请求引脚有效,而且CPSR的寄存器的I控制位被清除时,处理器产生外部中断请求异常中断。系统中个外设通过该异常中断请求处理服务。
(7)、快速中断请求(FIQ)
当处理器的外部快速中断请求引脚有效,而且CPSR的F控制位被清除时,处理器产生外部中断请求异常中断。
2、执行模式及向量地址
ARM的异常向量地址可以处于4G物理空间的低端(0x00000000起),也可以处于高端(0xffff0000起),具体是哪种情况,根据具体的CPU及其配置而定。ARMv4及其以上的版本,ARM异常向量表的地址受协处理器CP15的c1寄存器(controlregister)中V位的控制,如果V=1,则异常向量表的地址为0x00000000~0x0000001c;如果V=0,则为:0xffff0000~0xffff001c。表1是7种异常的执行模式及向量地址:
表1
异常类型
执行模式
向量地址
RESET异常
Supervisor模式
0x00000000 (0xffff0000)
未定义的指令
Undefined模式
0x00000004(0xffff0004)
软件中断
Supervisor模式
0x00000008(0xffff0008)
PrefechAbort
Abort模式
0x0000000c(0xffff000c)
DATA Abort
Abort模式
0x00000010(0xffff0010)
IRQ
IRQ模式
0x00000018(0xffff0018)
FIQ
FIQ模式
0x0000001c(0xffff001c)
3、处理过程
处理过程包括两个部分:
进入:这个过程由CPU负责
退出:这个过程由OS负责
在捕获到某个异常后,启动“进入”过程,该过程内CPU执行如下动作:
(1)将当前PC的值(或PC+ 4,或PC+ 8)保存到R14的某个寄存器中。到底选择哪个寄存器由该异常的执行模式而定;另外R14影子寄存器的值同异常类型相关。比如DataAbort异常,对应的影子寄存器就是Abort模式的影子寄存器R14_abt,R14_abt的值为异常产生时PC值+ 8。
(2)将CPSR保存到CPSR的某个寄存器SPSR中,同样,具体选择哪个寄存器由该异常的执行模式而定。
(3)改写CPSR以切换到相应的异常模式和处理器状态(ARM状态);
(4)禁止IRQ(如果进入FIQ则禁止FIQ);
(5)跳转到相应异常向量表入口(例如IRQ跳转到IRQ_Handler入口);
【注】复位异常处理会禁止所有中断,另外由于不用返回,因此不需要作(1)(2)步。
4、示例异常处理程序
Example 4.1说明了一个自定义异常处理程序。假定将某些Fortran代码转换为C代码。Fortran数值标准要求0除以0 得1,而IEEE754 规定 0 除以0 是“无效运算”,因此,缺省返回无提示NaN。Fortran代码可能会依赖于这种行为,让0除以0 返回1可能更方便一些,而不是对代码进行修改。
进行编译时,必须选择一种支持异常的浮点模型,例如--fpmode=ieee_full或--fpmode=ieee_fixed。
安装处理程序之后,0.0除以0.0返回1.0。
Example 4.1. 自定义异常处理程序
#include<fenv.h>
#include<signal.h>
#include<stdio.h>
__softfp__ieee_value_t myhandler(__ieee_value_t op1, __ieee_value_t op2,
__ieee_edata_t edata)
{
__ieee_value_tret;
if((edata & FE_EX_FN_MASK) == FE_EX_FN_DIV)
{
if((edata & FE_EX_INTYPE_MASK) == FE_EX_INTYPE_FLOAT)
{
if(op1.f == 0.0 && op2.f == 0.0)
{
ret.f= 1.0;
returnret;
}
}
if((edata&FE_EX_INTYPE_MASK)== FE_EX_INTYPE_DOUBLE)
{
if(op1.d == 0.0 && op2.d == 0.0)
{
ret.d= 1.0;
returnret;
}
}
}
/*For all other invalid operations, raise SIGFPE as usual */
raise(SIGFPE);
}
intmain(void)
{
floati, j, k;
fenv_tenv;
fegetenv(&env);
env.statusword|= FE_IEEE_MASK_INVALID;
env.invalid_handler= myhandler;
fesetenv(&env);
i= 0.0;
j= 0.0;
k= i/j;
printf(“kis %f\n“, k);
}
5.linux下的异常捕获和处理
清单 1.在异常对象构造函数中生成一个堆栈跟踪
//Sample Program:
// Compiler: gcc 3.2.3 20030502
// Linux:Red Hat
#include<execinfo.h>
#include <signal.h>
#include<exception>
#include <iostream>
usingnamespace std;
/////////////////////////////////////////////
classExceptionTracer
{
public:
ExceptionTracer()
{
void* array[25];
intnSize = backtrace(array, 25);
char** symbols = backtrace_symbols(array, nSize);
for(int i = 0; i < nSize; i++)
{
cout<< symbols[i] << endl;
}
free(symbols);
}
};
清单 2中定义的SignalExceptionClass,提供了表示内核可能发出信号的C++异常的抽象。SignalTranslator是一个基于SignalExceptionClass的模板类,它通常用来实现到C++异常的转换。在任何瞬间,只能有一个信号处理程序处理一个活动进程的一个信号。因此,SignalTranslator采用了singleton设计模式。整体概念通过用于SIGSEGV的SegmentationFault类和用于SIGFPE的FloatingPointException类得到了展示。
清单 2.将信号转换成异常
template<class SignalExceptionClass> classSignalTranslator
{
private:
classSingleTonTranslator
{
public:
SingleTonTranslator()
{
signal(SignalExceptionClass::GetSignalNumber(),SignalHandler);
}
staticvoid SignalHandler(int)
{
throwSignalExceptionClass();
}
};
public:
SignalTranslator()
{
staticSingleTonTranslator s_objTranslator;
}
};
//An example for SIGSEGV
class SegmentationFault : publicExceptionTracer, public exception
{
public:
staticint GetSignalNumber() {return SIGSEGV;}
};
SignalTranslator<SegmentationFault>g_objSegmentationFaultTranslator;
//An example for SIGFPE
class FloatingPointException : publicExceptionTracer, public exception
{
public:
staticint GetSignalNumber() {return SIGFPE;}
};
SignalTranslator<FloatingPointException>g_objFloatingPointExceptionTranslator
清单 3.处理构造函数中的异常
classExceptionHandler
{
private:
classSingleTonHandler
{
public:
SingleTonHandler()
{
set_terminate(Handler);
}
staticvoid Handler()
{
//Exception from construction/destruction of globalvariables
try
{
//re-throw
throw;
}
catch(SegmentationFault &)
{
cout<< SegmentationFault << endl;
}
catch(FloatingPointException &)
{
cout<< FloatingPointException << endl;
}
catch(...)
{
cout<< Unknown Exception << endl;
}
//ifthis is a thread performing some coreactivity
abort();
//else if this is a thread used to service requests
//pthread_exit();
}
};
public:
ExceptionHandler()
{
staticSingleTonHandler s_objHandler;
}
};
//////////////////////////////////////////////////////////////////////////
classA
{
public:
A()
{
//inti = 0, j = 1/i;
*(int*)0 = 0;
}
};
//Before defining any global variable, we define a dummyinstance
//of ExceptionHandler object to make sure that
//ExceptionHandler::SingleTonHandler::SingleTonHandler() isinvoked
ExceptionHandlerg_objExceptionHandler;
Ag_a;
//////////////////////////////////////////////////////////////////////////
intmain(int argc, char* argv[])
{
return0;
}
- 对ARM的异常处理
- ARM的异常处理
- ARM的异常处理
- ARM的异常处理
- ARM 的异常处理
- ARM的异常处理
- ARM:ARM中断异常的处理流程
- 二、ARM 的异常处理
- 对异常的处理
- 对ARM异常(Exceptions)的理解
- 对ARM异常(Exceptions)的理解
- ARM中断异常处理的返回
- Arm异常中断返回时的处理
- ARM中断异常处理的返回
- ARM的异常处理过程分析
- ARM中断异常处理的返回
- ARM中断异常处理的返回
- ARM中断异常处理的返回
- 十个利用矩阵乘法解决的经典题目
- Redhat Linux网卡配置与绑定
- POJ 1837 Balance DP
- Mysql 事务隔离级别
- 计算器是如何计算sin、cos等科学函数的值呢?
- 对ARM的异常处理
- 初谈单调队列...POJ 2823
- Webfocus Flex 之间通讯
- 文件读写函数的使用方法
- 【博客文章索引】
- virtualbox 安装时Kernel driver not installed (rc=-1908) 错误的解决方法
- ext checkbox,box赋值问题
- 第一篇试试
- [提供源码下载]在大型软件中用Word做报表:书签的应用(提供一种思路)