220 likes | 367 Views
中断实验. 中断实验. 实验目的 实验设备 实验内容 实验原理 实验参考程序. 中断实验. 实验目的 通过实验了解 ARM 的中断方式和原理。 熟悉 ARM 中断的编程方法。. 中断实验. 实验设备 硬件: PC 机,华邦 W90P710 开发板套件。 软件: Lambda IDE 集成开发环境, Windows 2000/NT/XP 。. 中断实验. 实验内容 掌握 ARM 中断工作原理,了解 W90P710 和中断有关的寄存器,掌握常用中断的编程方法 , 编写中断处理程序实现时钟中断。. 实验原理. 中断控制器介绍
E N D
中断实验 • 实验目的 • 实验设备 • 实验内容 • 实验原理 • 实验参考程序
中断实验 • 实验目的 • 通过实验了解ARM的中断方式和原理。 • 熟悉ARM中断的编程方法。
中断实验 • 实验设备 • 硬件:PC机,华邦W90P710开发板套件。 • 软件:Lambda IDE集成开发环境,Windows 2000/NT/XP。
中断实验 • 实验内容 • 掌握ARM中断工作原理,了解W90P710和中断有关的寄存器,掌握常用中断的编程方法,编写中断处理程序实现时钟中断。
实验原理 • 中断控制器介绍 W90P710开发板集成了一个高级中断控制器,简称AIC(advanced interrupt controller),来处理来自设备的中断。它类似于X86体系的8529芯片,是W90P710控制中断的部件。为了响应多个中断源,AIC为每个设备的中断号定义了的优先级。并且实现了一个中断优先级位表[7],如表1-1所示:
实验原理 表 1-1中断优先级位表
实验原理 • 若同一优先级的中断同时到来,则根据中断号越低,优先级越高的原则只响应最高优先级中断。另外,优先级为0的四个中断触发的是FIQ中断,而其余级别的中断全都属于IRQ中断。 • AIC最多可以处理32个中断源(现在只定义了31个),每个中断源都对应了唯一的中断号,如图1-1所示:
实验原理 图 1-1 W90P710 中断号分配
实验原理 • 其中中断号越低,优先级就越高。例如1号看门狗中断优先级最高。另外优先级为0的四个中断触发的是FIQ中断,而其余级别的中断全都属于IRQ中断。 • 控制AIC的寄存器映射在地址0xfff8_2100-0xfff8_2200。AIC模块的主要功能是屏蔽或者使能中断,相当于在设备级和CPU之间多了一道中断的开关,它的主要控制寄存器有IPER,MECR,MDCR等。
实验原理 • Timer(定时器)介绍 • 本实验中触发中断的设备为定时器(Timer),触发的中断类型为IRQ。 • Timer完成计时主要是靠一个叫做计数寄存器完成的,一般先赋予计数器一个初值,然后打开计数使能位,使计数器自动计数,一旦计数器里的值向下减少到零或者向上增加到某个约定的数值,那么时钟就触发了一次中断。
实验原理 • 系统的中断控制机制
实验参考程序 • 本实验里中断的程序的编写主要包括以下几个部分: • 1安装中断向量表 • 2初始化Timer和AIC,打开中断的一、二级开关 • 3编写中断处理函数 • 4使能Timer的中断位,使其可以触发中断,并开始计数。
实验参考程序 /* 打开第一级开关,将控制IRQ中断的I位置零 * / CPSR_init: mov r0,#0x5f //开中断 msr cpsr_c,r0 mov pc,lr //返回 /* 打开第二级开关,将Timer对应的AIC的中断通道13打开 */ void AIC_Init() { rAIC_MDCR = 0XFFFFFFFE; /* 将中断通道全部关闭 */ Aic_Int_Enable(13); }
实验参考程序 /* 打开中断通道i的函数 */ void Aic_Int_Enable(char vector) { unsigned int mask; if( vector > INTERRUPT_VECTOR_END) /*中断号越界检查*/ { return ; } mask = 1 << vector; rAIC_MECR = (mask|rAIC_IMR); } /* 打开第三级开关,使能Timer0的中断,并使其开始计数 */
实验参考程序 unsigned int Timer_Start( ) { rTCSR0 |= (CEN|IE); /*开启中断使能,计数使能位 */ return TRUE; } 编写中断处理函数 中断处理包括三部分:保存现场,清中断,恢复现场。 /* 保存现场 */
实验参考程序 STR R3, [SP, #-4]! //将需要使用的工作寄存器压栈 STR R2, [SP, #-4]! STR R1, [SP, #-4]! MOV R1, SP // 保存IRQ堆栈指针 ADD SP, SP,#12 // 调整IRQ堆栈指针 SUB R2, LR,#4 // 保存返回地址 MRS R3, SPSR // 保存SPSR寄存器内容 MSR CPSR_c, #(NO_INT | SYS32_MODE) // 切换成SYS模式
实验参考程序 // 保存被中断任务的寄存器现场 STR R2, [SP, #-4]! STR LR, [SP, #-4]! STR R12, [SP, #-4]! STR R11, [SP, #-4]! STR R10, [SP, #-4]! STR R9, [SP, #-4]! STR R8, [SP, #-4]! STR R7, [SP, #-4]! STR R6, [SP, #-4]! STR R5, [SP, #-4]! STR R4, [SP, #-4]! LDR R4, [R1], #4 //从IRQ堆栈中读出R1-R3的寄存器内容
实验参考程序 LDR R5, [R1], #4 LDR R6, [R1], #4 STR R6, [SP, #-4]! //将原来R1-R3的寄存器内容保存至堆栈 STR R5, [SP, #-4]! STR R4, [SP, #-4]! STR R0, [SP, #-4]! // 将R0保存 STR R3, [SP, #-4]! //被中断任务的CPSR寄存器内容保存 /******************做模式切换,执行真正的中断处理****************/ MSR CPSR_c, #(NO_INT | IRQ32_MODE) BL T0_INT_ISR
实验参考程序 /***************恢复现场,原先保存的寄存器出栈*****************/ LDR R4, [SP], #4 MSR CPSR_cxsf, R4 LDR R0, [SP], #4 LDR R1, [SP], #4 LDR R2, [SP], #4 LDR R3, [SP], #4 LDR R4, [SP], #4 LDR R5, [SP], #4 LDR R6, [SP], #4 LDR R7, [SP], #4 LDR R8, [SP], #4 LDR R9, [SP], #4 LDR R10, [SP], #4
实验参考程序 LDR R11, [SP], #4 LDR R12, [SP], #4 LDR LR, [SP], #4 LDR PC, [SP], #4 其中,除保存和恢复现场外,真正的中断处理很简单,只是为一个isr_counter简单加1,使其记录中断的次数。可以用c函数T0_INT_ISR实现: void T0_INT_ISR() { OSTimeTick(); rTISR = 0x01; rAIC_EOSCR = 0; }
实验参考程序 使能Timer的中断位,使其可以触发中断,并开始计数。 unsigned int Timer_Start( ) { rTCSR0 |= (CEN|IE); /*开启中断使能,计数使能位*/ return TRUE; } 上述函数的宏定义这里不做说明,详见实验代码附件。