ARM异常及中断处理实验报告
- 格式:docx
- 大小:948.80 KB
- 文档页数:9
ARM的异常处理过程分析近来翻了翻uC/OS-II官网给出来的ARM7-ARM9移植手册(AN-104),分析了在ARM中移植的问题,想想从来没有认真的学习过ARM的汇编,趁着这个机会复习复习吧。
其实底层的东西才是创造力的心脏。
其中的移植代码中存在的很多问题比如中断的关闭和开启,任务级别的情景切换,中断到任务的情景切换都是我们在平时移植中讲到,我也不在此强调了。
在官网中提供的移植过程中存在异常处理机制,这个本不是在移植过程中考虑的,但是文档中确实提供了一个比较好的处理方式。
我在此对这一段时间的学习做一个总结。
首先需要了解ARM的异常处理机制,异常是每一种处理器都必须考虑的问题之一,关键在于如何让处理,返回地址在什么位置都是需要考虑的,ARM中支持7种异常,其中包括复位、未定义指令异常、软中断异常、预取指令中止、数据中止、IRQ、IFQ。
每一种异常运行在特定的处理器模式下。
我在此逐一的分析。
一般异常发生后,CPU都会进行一系列的操作,这些操作有一部分是CPU自动完成,有一部分是需要我们程序员完成。
首先说明CPU会自动完成的部分,用ARM结构手册中的代码描述如下:R14_; = return link//这个可以参看寄存器的说明,两个作用SPSR_; = CPSRCPSR[4:0] = exception mode numberCPSR[5] = 0 ;//AEM指令If ;==Reset or Fiq then//只有在复位和FIQ模式下才会关闭FIQ中断CPSR[6] = 1 ;CPSR[7] = 1 ;//任何异常模式下都会关闭IRQ中断PC = exception vector address从上面的代码中我们可以发现CPU自动处理的过程包括如下:1、拷贝CPSR到SPSR_;2、设置适当的CPSR位:改变处理器状态进入ARM状态;改变处理器模式进入相应的异常模式;设置中断禁止位禁止相应中断。
ARM的SWI异常中断处理程序设计本节主要介绍编写SWI 处理程序时需要注意的几个问题,包括判断SWI中断号,使用汇编语言编写SWI 异常处理函数,使用C 语言编写SWI 异常处理函数,在特权模式下使用SWI 异常中断处理,从应用程序中调用SWI。
1.判断SWI 中断号当发生SWI 异常,进入异常处理程序时,异常处理程序必须提取SWI 中断号,从而得到用户请求的特定SWI 功能。
在SWI 指令的编码格式中,后24 位称为指令的comment field。
该域保存的24 位数,即为SWI 指令的中断号,如图7-4 所示。
第一级的用LR-4 得到SWI 指令的地址,再通过BIC r0, r0, #0xff000000 指令提取SWI 指令中断号。
2.使用C 语言编写SWI 异常处理函数虽然第一级SWI 处理函数(完成中断向量号的提取)必须用汇编语言完成,但第二级中断处理函数(根据提取的中断向量号,跳转到具体处理函数)却可以使用C 语言来完成。
因为第一级的中断处理函数已经将中断号提取到寄存器r0 中,所以根据AAPCS 函数调用规则,可以直接使用BL 指令跳转到C 语言函数,而且中断向量号作为第一个参数被传递到C 函数。
例如,汇编中使用了BLC_SWI_Handler 跳转到C 语言的第二级处理函数,而第二级的C 语言函数示例如下。
void C_SWI_handler (unsigned number){ switch (number) { case 0 : /* SWI number 0 code */ break; case 1 : /* SWI number 1 code */ break; ... default : /* Unknown SWI - report error */ }}。
ARM中断异常及其处理器模式
ARM 处理器核有七种异常中断:1.复位(包括上电)
2.FIQ(快速中断)
3.IRQ(一般中断)
4.SWI(软件中断)
5.预取址中止
6.数据中止
7.未定义指令异常
ARM 核发生以上异常时,便会进入相应的处理器模式进行相应的异常处理。
其中ARM 的处理器模式有以下7 种:
1.管理模式(SVC):Supervisor 也是处理器上电默认的运行模式,可由复位(包括上电)和SWI(软件中断)触发进入
2.快速中断模式(FIQ):由快速中断异常异常触发进入进行相应的中断处理子程序
3.一般中断模式(IRQ):由一般中断异常触发进入进行相应的中断处理
4.中止模式(abort):由预取址中止异常和数据中止异常触发进入的
5.未定义模式:由未定义指令异常触发进入
6.用户模式(user):用户软件修改CPSR 进入
7.系统模式(system):用户软件修改CPSR 进入
由此可见,处理器模式是相应的处理器异常的处理模式,但是用户模式和系统模式并不能由异常触发进入,而必须是由软件修改CPSR 的值进入的。
此外系统模式和用户模式共用15 个寄存器和CPSR。
总结处理器异常和处理器模式。
实验报告实验题目ARM异常及中断处理实验姓名:学号:课程名称:所在学院:专业班级:任课教师:实验项目名称ARM异常及中断处理实验一、实验目的与要求:利用 Exynos4412 的 K2、K3这2个I/O引脚的中断模式,当被按下时进入相应的中断处理函数处理相应的事件。
二、实验设备:华清远见试验箱,PC机三、实验方法(原理,流程图)1、电路原理电路原理如图所示,K2、K3 分别与 GPX1_1、GPX1_2 相连,在没有按下按键时 GPX1_1、GPX1_2 引脚上一直处于高电平,当把这两个引脚设为中断模式并为下降沿中断,则按键被按下俩引脚就会有高电平变为低电平,因此,产生 GPIO 中断进入相应的中断函数,处理中段事件,从终端上打印出相应的按键信息。
其中K2 对应的是XEINT9 中断源,K3 对应的是 XEINT10 中断源。
2、编程流程(1)设置 GPX1_2、GPX1_2 两个管脚没有内部上下拉属性,然后配置为中断模式;(2)设置中断触发方式;(3)GPIO 控制器中关闭屏蔽、使能中断;(4)在 GIC 中断控制器中使能中断;(5)设置中断优先级;(6)使能 GIC;(7)选择中断发送给 CPU0;(8)等待中断产生,然后进入中断处理器函数;(9)清楚中断源的挂起状态。
四、实验过程、步骤及内容1、寄存器设置为了实现进入中断目的,需要通过配置 GPX1CON 寄存器将 GPX1_1、GPX1_2 设置为中断模式。
设置中断方式、中断处理函数、使能中断。
2、编写相关代码如下:(1)设置异常向量表:.text.global _start_start:b resetldr pc,_undefined_instructionldr pc,_software_interruptldr pc,_prefetch_abortldr pc,_data_abortldr pc,_not_usedldr pc,_irqldr pc,_fiq_undefined_instruction: .word _undefined_instruction_software_interrupt:.word _software_interrupt_prefetch_abort:.word _prefetch_abort_data_abort:.word _data_abort_not_used:.word _not_used_irq:.word irq_handler_fiq:.word _fiqreset:ldr r0,=0x40008000mcr p15,0,r0,c12,c0,0 @ Vector Base Address Registermrs r0,cpsrbic r0,r0,#0x1forr r0,r0,#0xd3msr cpsr,r0 @ Enable svc mode of cpu.text.global _start_start:b resetldr pc,_undefined_instructionldr pc,_software_interruptldr pc,_prefetch_abortldr pc,_data_abortldr pc,_not_usedldr pc,_irqldr pc,_fiq_undefined_instruction: .word _undefined_instruction_software_interrupt:.word _software_interrupt_prefetch_abort:.word _prefetch_abort_data_abort:.word _data_abort_not_used:.word _not_used_irq:.word irq_handler_fiq:.word _fiqreset:ldr r0,=0x40008000mcr p15,0,r0,c12,c0,0 @ Vector Base Address Registermrs r0,cpsrbic r0,r0,#0x1forr r0,r0,#0xd3msr cpsr,r0 @ Enable svc mode of cpuinit_stack:ldr r0,stacktop /*get stack top pointer*//********svc mode stack********/mov sp,r0sub r0,#128*4 /*512 byte for irq mode of stack*/ /****irq mode stack**/msr cpsr,#0xd2mov sp,r0sub r0,#128*4 /*512 byte for irq mode of stack*/ /***fiq mode stack***/msr cpsr,#0xd1mov sp,r0sub r0,#0/***abort mode stack***/msr cpsr,#0xd7mov sp,r0sub r0,#0/***undefine mode stack***/msr cpsr,#0xdbmov sp,r0sub r0,#0/*** sys mode and usr mode stack ***/msr cpsr,#0x10mov sp,r0 /*1024 byte for user mode of stack*/b main.align 4/**** swi_interrupt handler ****//**** irq_handler ****/irq_handler:sub lr,lr,#4stmfd sp!,{r0-r12,lr}bl do_irq //跳转到do_irq 处理器函数ldmfd sp!,{r0-r12,pc}^stacktop: .word stack+4*512.datastack: .space 4*512(2)编写中断处理函数,汇编中的处理/**** irq_handler ****/irq_handler:sub lr,lr,#4stmfd sp!,{r0-r12,lr}bl do_irq //跳转到do_irq 处理器函数ldmfd sp!,{r0-r12,pc}^(3)主程序的初始化:int main(void){//LED2 GPX2_7GPX2.GPX2CON |= 0x1 << 28;//LED3 GPX1_0GPX1.GPX1CON |= 0x1;//Led4 GPF3_4GPF3.GPF3CON |= 0x1 << 16;//Key_2 Interrupt GPX1_1GPX1.GPX1PUD = GPX1.GPX1PUD & ~(0x3 << 2); // Disables Pull-up/Pull-downGPX1.GPX1CON = (GPX1.GPX1CON & ~(0xF << 4)) | (0xF << 4); //GPX1_1:WAKEUP_INT1[1](EXT_INT41[1])EXT_INT41_CON = (EXT_INT41_CON & ~(0x7 << 4)) | 0x2 << 4;EXT_INT41_MASK = (EXT_INT41_MASK & ~(0x1 << 1)); // Bit: 1 = Enables interrupt//Key_3 Interrupt GPX1_2GPX1.GPX1PUD = GPX1.GPX1PUD & ~(0x3 << 4); // Disables Pull-up/Pull-downGPX1.GPX1CON = (GPX1.GPX1CON & ~(0xF << 8)) | (0xF << 8); //GPX1_2:WAKEUP_INT1[2] (EXT_INT41[2])EXT_INT41_CON = (EXT_INT41_CON & ~(0x7 << 8)) | 0x2 << 8;EXT_INT41_MASK = (EXT_INT41_MASK & ~(0x1 << 2)); // Bit: 1 = Enables interrupt/** GIC interrupt controller:* */// Enables the corresponding interrupt SPI25, SPI26 -- Key_2, Key_3ICDISER.ICDISER1 |= (0x1 << 25) | (0x1 << 26);CPU0.ICCICR |= 0x1; //Global enable for signaling of interruptsCPU0.ICCPMR = 0xFF; //The priority mask level.Priority filter. thresholdICDDCR = 1; //Bit1: GIC monitors the peripheral interrupt signals and// forwards pending interrupts to the CPU interfaces2ICDIPTR.ICDIPTR14 = 0x01010101; //SPI25 SPI26 interrupts are sent to processor 0printf("\n ********* GIC test ********\n");while (1){GPF3.GPF3DAT |= 0x1 << 4;mydelay_ms(500);GPF3.GPF3DAT &= ~(0x1 << 4);mydelay_ms(500);}return 0;}(4)中断处理函数:void do_irq(void ){int irq_num;irq_num = (CPU0.ICCIAR & 0x3FF);switch (irq_num) {case 58: //turn on LED2; turn off LED3GPX2.GPX2DAT = 0x1 << 7;GPX1.GPX1DAT &= ~0x1;printf("IRQ interrupt !! turn on LED2; turn off LED3\n");//Clear PendEXT_INT41_PEND |= 0x1 << 2;ICDICPR.ICDICPR1 |= 0x1 << 26;break;case 57: //Turn on Led3; Turn off Led2GPX2.GPX2DAT &= ~(0x1 << 7);GPX1.GPX1DAT |= 0x1;printf("IRQ interrupt !! Turn on LED3; Turn off LED2\n");//Clear PendEXT_INT41_PEND |= 0x1 << 1;ICDICPR.ICDICPR1 |= 0x1 << 26;break;}// End of interruptCPU0.ICCEOIR = (CPU0.ICCEOIR & ~(0x1FF)) | irq_num;}(5)时延函数:void mydelay_ms(int ms){int i, j;while(ms--){for (i = 0; i < 5; i++)for (j = 0; j < 514; j++);}3、实验步骤:(1)导入工程源码。