i.MX6ULL终结者GPIO中断例程中断系统简介及原理分析

本文介绍了i.MX6ULL芯片中断系统的基础知识,包括中断向量表和GIC控制器的工作原理。重点讲述了GIC(Generic Interrupt Controller)的角色,它是如何接收并分发中断,以及如何通过CP15协处理器访问GIC的寄存器。此外,还讨论了中断使能、优先级设置以及如何配置中断服务函数。文章适用于理解嵌入式Linux系统中的中断处理机制。
摘要由CSDN通过智能技术生成

1 中断系统简介

1.1 中断向量表

中断向量表的定义的就是中断服务程序的跳转指令,因为每个中断向量在向量表中只有一个字节的存储空间,只能存放一条指令,所以通常存放跳转指令,使程序跳转到存储器的其他地方,再执行中断处理。这里cpu就可以找中断服务程序,跳转指令例如:
LDRPC, =ISR_HANDLER
在这里插入图片描述

Cortex-A7内核有8个异常中断,这8个异常中断的中断向量表如下表所示:
中断向量表里面都是中断服务函数的入口地址,因此一款芯片有什么中断都是可以从中断向量表看出来的。从上表中可以看出,Cortex-A7 一共有 8 个中断,而且还有一个中断向量未使用,实际只有 7 个中断。

下面我们来简单介绍一下这7个中断:
1.复位中断(Rest), CPU 复位以后就会进入复位中断,我们可以在复位中断服务函数里面做一些初始化工作,比如初始化SP指针、DDR等等。
2.未定义指令中断(Undefined Instruction),如果指令不能识别的话就会产生此中断。
3.软中断(Software Interrupt,SWI),由SWI指令引起的中断,Linux的系统调用会用SWI指令来引起软中断,通过软中断来陷入到内核空间。
4.指令预取中止中断(Prefetch Abort),预取指令的出错的时候会产生此中断。
5.数据访问中止中断(Data Abort),访问数据出错的时候会产生此中断。
6.IRQ 中断(IRQ Interrupt),外部中断,前面已经说了,芯片内部的外设中断都会引起此中断的发生。
7.FIQ 中断(FIQ Interrupt),快速中断,如果需要快速处理中断的话就可以使用此中断。

在上面的7个中断中,我们常用的就是复位中断和IRQ中断,所以我们需要编写这两个中断的中断服务函数,稍后我们会讲解如何编写对应的中断服务函数。首先我们要根据上表的内容来创建中断向量表,中断向量表处于程序最开始的地方,比如我们8_int例程的 start.S文件最前面,中断向量表如下:

  1 
  2 .global _start         /* 全局标号 */
  3 
  4 /*
  5  * 描述:_start函数,首先是中断向量表的创建
  6  * 参考文档:ARM Cortex-A(armV7)编程手册V4.0.pdf P42,
		3 ARM Processor Modes and Registers(ARM处理器模型和寄存器)
  7  * ARM Cortex-A(armV7)编程手册V4.0.pdf P165 11.1.1 Exception priorities(异常)
  8  */
  9 _start:
 10         ldr pc, =Reset_Handler          /* 复位中断 */                                   
 11         ldr pc, =Undefined_Handler      /* 未定义中断 */                               
 12         ldr pc, =SVC_Handler            /* SVC(Supervisor)中断*/
 13         ldr pc, =PrefAbort_Handler      /* 预取终止中断 */                                      
 14         ldr pc, =DataAbort_Handler      /* 数据终止中断 */                                       
 15         ldr     pc, =NotUsed_Handler    /* 未使用中断  */                                  
 16         ldr pc, =IRQ_Handler            /* IRQ中断 */                                      
 17         ldr pc, =FIQ_Handler            /* FIQ(快速中断)未定义中断 */                      
 18 
 19 /* 复位中断 */
 20 Reset_Handler:
 21 
 22         cpsid i   /* 关闭全局中断 */
 23 
 24         /* 关闭I,DCache和MMU 
 25          * 采取读-改-写的方式。
 26          */
 27         mrc     p15, 0, r0, c1, c0, 0     /* 读取CP15的C1寄存器到R0中*/                                    
 28     bic     r0,  r0, #(0x1 << 12)  /* 清除C1寄存器的bit12位(I位),关闭I Cache*/                 
 29     bic     r0,  r0, #(0x1 <<  2)  /* 清除C1寄存器的bit2(C位),关闭D Cache */                                   
 30     bic     r0,  r0, #0x2        /* 清除C1寄存器的bit1(A位),关闭对齐 */                                              
 31     bic     r0,  r0, #(0x1 << 11)  /* 清除C1寄存器的bit11(Z位),关闭分支预测 */                                 
 32     bic     r0,  r0, #0x1        /* 清除C1寄存器的bit0(M位),关闭MMU  */                                      
 33     mcr     p15, 0, r0, c1, c0, 0  /* 将r0寄存器中的值写入CP15的C1寄存器中*/ 
 34 
 35 
 36 #if 0
 37         /* 汇编版本设置中断向量表偏移 */
 38         ldr r0, =0X87800000
 39 
 40         dsb
 41         isb
 42         mcr p15, 0, r0, c12, c0, 0
 43         dsb
 44         isb
 45 #endif
 46 
 47         /* 设置各个模式下的栈指针,
 48          * 注意:IMX6UL的堆栈是向下增长的!
 49          * 堆栈指针地址一定要是4字节地址对齐的!!!
 50          * DDR范围:0X80000000~0X9FFFFFFF
 51          */
 52         /* 进入IRQ模式 */
 53         mrs r0, cpsr
 54         bic r0, r0, #0x1f /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4*/    
 55         orr r0, r0, #0x12       /* r0或上0x13,表示使用IRQ模式  */                                  
 56         msr cpsr, r0           /* 将r0 的数据写入到cpsr_c中 */                                    
 57         ldr sp, =0x80600000    /*设置IRQ模式下栈首地址0X80600000,大小为2M*/ 
 58 
 59         /* 进入SYS模式 */
 60         mrs r0, cpsr
 61         bic r0, r0, #0x1f    /* 将r0寄存器中的低5位清零,cpsr的M0~M4 */   
 62         orr r0, r0, #0x1f    /* r0或上0x13,表示使用SYS模式 */                                   
 63         msr cpsr, r0       /* 将r0 的数据写入到cpsr_c中 */                                    
 64         ldr sp, =0x80400000 /* 设置SYS模式栈首地址为0X80400000,大小2M*/ 
 65 
 66         /* 进入SVC模式 */
 67         mrs r0, cpsr
 68         bic r0, r0, #0x1f  /* 将r0寄存器中低5位清零,cpsr的M0~M4 */   
 69         orr r0, r0, #0x13  /* r0或上0x13,表示使用SVC模式 */                                   
 70         msr cpsr, r0        /* 将r0 的数据写入到cpsr_c中 */                                    
 71         ldr sp, =0X80200000 /* 设置SVC模式栈首地址为0X80200000,大小2M*/ 
 72 
 73         cpsie i    /* 打开全局中断 */
 74 #if 0
 75         /* 使能IRQ中断 */
 76         mrs r0, cpsr    /* 读取cpsr寄存器值到r0中 */                       
 77         bic r0, r0, #0x80 /* 将r0中bit7清零,也就是CPSR的I位清零,允许IRQ*/ 
 78         msr cpsr, r0            /* 将r0重新写入到cpsr中 */                         
 79 #endif
 80 
 81         b main    /* 跳转到main函数  */                              
 82 
 83 /* 未定义中断 */
 84 Undefined_Handler:
 85         ldr r0, =Undefined_Handler
 86         bx r0
 87 
 88 /* SVC中断 */
 89 SVC_Handler:
 90         ldr r0, =SVC_Handler
 91         bx r0
 92 
 93 /* 预取终止中断 */
 94 PrefAbort_Handler:
 95         ldr r0, =PrefAbort_Handler
 96         bx r0
 97 
 98 /* 数据终止中断 */
 99 DataAbort_Handler:
100         ldr r0, =DataAbort_Handler
101         bx r0
102 
103 /* 未使用的中断 */
104 NotUsed_Handler:
105 
106         ldr r0, =NotUsed_Handler
107         bx r0
108 
109 /* IRQ中断!重点!!!!! */
110 IRQ_Handler:
111         push {
   lr}            /* 保存lr地址 */
112         push {
   r0-r3, r12}      /* 保存r0-r3,r12寄存器 */
113 
114         mrs r0, spsr          /* 读取spsr寄存器 */
115         push {
   r0}           /* 保存spsr寄存器 */
116 
117         mrc p15, 4, r1, c15, c0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值