向量中断控制器(VIC)具 有 32 个中断请求输入,可将其编程分为3 类:FIQ 、向量IRQ和非向量IRQ 。可编程分配机制意味着不同外设的中断优先级可以动态分配并调整。
快速中断请求(FIQ )要求具有最高优先级。如果分配给 FIQ 的请求多于1 个,VIC 将中断请求“相或”后向ARM处理器产生 FIQ 信号。当只有一个中断被分配为 FIQ 时可实现
最短的FIQ 等待时间,因为FIQ 服务程序只要简单地启动器件的处理就可以了。但如果分配给FIQ 级的中断多于1 个,FIQ 服务程序从 VIC 中读出一个字来识别产生中断请求的 FIQ中断源是哪一个。
向量IRQ 具有中等优先级。该级别可分配32 个请求中的 16 个。32个请求中的任意一个都可分配到16 个向量IRQ slot 中的任意一个,其中 slot0 具有最高优先级,而 slot15 则为最低优先级。
非向量IRQ 的优先级最低。VIC 将所有向量和非向量IRQ “相或”向 ARM处理器产生IRQ 信号。IRQ 服务程序可通过读取VIC 的一个寄存器立即启动并跳转到相应地址。如果有任意一个向量IRQ 发出请求,VIC 则提供最高优先级请求IRQ 服务程序的地址,否则提供所默认程序的地址。该默认程序由所有非向量IRQ 共用。默认程序可读取另一个VIC 寄存器以确定哪个IRQ 被激活。
一、向量中断
1.1 第一种方法,每次中断都可以直接跳转到对应的中断处理函数
1.1.1 启动代码
ARM
__vector:
;;
ldr pc,[pc,#+24] ;; Reset
ldr pc,[pc,#+24] ;; Undefined instructions
B . ;; Software interrupt (SWI/SVC)
ldr pc,[pc,#+24] ;; Prefetch abort
ldr pc,[pc,#+24] ;; Data abort
__vector_0x14:
DC32 0 ;; RESERVED
ldr pc,[pc,#-0xFF0] ;; IRQ
ldr pc,[pc,#+24] ;; FIQ
DC32 __iar_program_start ;; Reset
DC32 undef_handler ;; Undefined instructions
DC32 0 ;; Software interrupt (SWI/SVC)
DC32 prefetch_handler ;; Prefetch abort
DC32 data_handler ;; Data abort
DC32 0 ;; RESERVED
DC32 0 ;; IRQ
DC32 fiq_handler ;; FIQ
这里FIQ很好理解,但这里的IRQ为什么要PC-0XFF0呢?
结合ARM7的三级流水线,这个问题应该就很简单了,当程序跳到0X18执行指令的时候,PC应该是0x18+8=0x20,
然后0x20-0xff0=0xfffff030,此处0XFFFFF030正好是 VICVectAddr 的地址,意思就是通过一条简单的ARM指令,
实现了IRQ的程序跳转
1.1.2 初始化,以串口中断为例
设置 0号 IRQ slot (向量中断中优先级最高)为串口中断,并且把 中断处理函数 IRQ_UART_0 赋给 VICVectAddr0
void Init_uart0()
{
U0LCR = 0x83; //使能访问除数寄存器,8位字符长度
U0DLM = 0x00; //115200时为6 9600时为0x006c
U0DLL = 0x6c;
U0LCR = 0x03; //禁止访问除数寄存器
U0IER = 0x03; //允许接收数据可用中断[第0位]和发送缓冲为空中断[第1位]
//以下是中断设置 设置为中断通道0
VICIntSelect = 0x00000000;
VICVectCntl0 = 0x26; //第5位置1:向量使能,[4:0]中断源序号
VICVectAddr0 = (unsigned long)&IRQ_UART_0;
//jtk 当发生向量中断时处理器自动把 VICVectAddrN 赋给 VICVectAddr
VICIntEnable = 0x00000040;
PINSEL0 |= 0x00000005;
}
1.1.3 中断处理函数
__irq __arm void IRQ_UART_0(void)
{
…………
VICVectAddr = 0x00;
}
1.2 第二方法,先跳转到一个处理函数然后再跳转到对应的中断处理函数
1.2.1 启动代码
ARM
__vector:
;jtk 绝对跳转,跳转到相应的异常处理程序,PC总是指向当前指令的下两条指令的地址,即PC的值为当前指令的地址值加8个字节
;jtk 所以LDR PC, [PC,#24]跳转到24+8=32字节后
ldr pc,[pc,#+24] ;; Reset jtk 跳转到__iar_program_start
ldr pc,[pc,#+24] ;; Undefined instructions
B . ;; Software interrupt (SWI/SVC)
ldr pc,[pc,#+24] ;; Prefetch abort
ldr pc,[pc,#+24] ;; Data abort
__vector_0x14
DC32 0 ;; RESERVED
ldr pc,[pc,#+24] ;; IRQ
ldr pc,[pc,#+24] ;; FIQ
;jtk 上面的中断向量跳转到这里来,如果在c语言中有定义,
;下面的标号如果在c语言中有相应的处理程序,那么一旦有中断产生就会跳到相应的中断函数去
DC32 __iar_program_start ;; Reset
DC32 undef_handler ;; Undefined instructions
DC32 0 ;; Software interrupt (SWI/SVC)
DC32 prefetch_handler ;; Prefetch abort
DC32 data_handler ;; Data abort
DC32 0 ;; RESERVED
DC32 irq_handler ;; IRQ 跳转到 irq_handler 这个函数
DC32 fiq_handler ;; FIQ
void Init_key()
{
PINSEL1_bit.P0_16 = 1;//引脚P0.16选择为外部中断功能
EXTWAKE=0X00;//jtk 不作为唤醒用,为1时处理器从掉电模式唤醒
EXTMODE =0x00;//jtk 为0用电平激活,为1时是边缘激活
EXTPOLAR=0x00;//jtk 为低电平或下降沿有效
VICIntSelect_bit.EINT0 =0; //jtk 中断选择寄存器第14位是0就行。
//第5位置1:向量使能,[4:0]中断源序号
VICVectCntl9 = 0x20|14;//将9号IRQ slot设置为向量中断(第5位为1使能向量中断,为0时是非向量中断)
VICVectAddr9 = (unsigned int)KEY_IRQ; //当设置为向量中断时,中断函数地址给 VICVectAddrN
VICDefVectAddr = (unsigned long)KEY_IRQ; //当设置为非向量中断时,中断函数地址给 VICDefVectAddr
//当一个IRQ服务程序读取向量地址寄存器 VICVectAddr ,并且没有 IRQ slot 响应时,则返回 VICDefVectAddr 的地址
//所以当没有 IRQ slot 响应时,则 VICDefVectAddr 的地址被读取了,这样就变成了处理非向量中断的程序了
//KEY_IRQ; //中断函数地址
EXTINT=0X01;//jtk 通过向 EXTINT 寄存器 写入 1 来将其清零
VICIntEnable_bit.EINT0 = 1;//中断使能寄存器 查表可知ext0的中断源号是14,第14位置1.
}
__irq __arm void irq_handler (void) //公共中断处理函数,检查 VICVectAddr 是否为空
{
void (*interrupt_function)();
unsigned int vector;
vector = VICVectAddr; // Get interrupt vector.
//jtk 如果作为向量中断,这里把 VICVectAddrN 赋给 vector 和把 VICVectAddr 赋给 vector 都可以,
//jtk 当发生向量中断时处理器自动把 VICVectAddrN 赋给 VICVectAddr
interrupt_function = (void(*)())vector;
if(interrupt_function !=NULL){
interrupt_function(); // Call vectored interrupt function.
}else{
VICVectAddr = 0; // Clear interrupt in VIC.
}
}
二、非向量中断
ARM
__vector:
;jtk 绝对跳转,跳转到相应的异常处理程序,PC总是指向当前指令的下两条指令的地址,即PC的值为当前指令的地址值加8个字节
;jtk 所以LDR PC, [PC,#24]跳转到24+8=32字节后
ldr pc,[pc,#+24] ;; Reset jtk 跳转到__iar_program_start
ldr pc,[pc,#+24] ;; Undefined instructions
B . ;; Software interrupt (SWI/SVC)
ldr pc,[pc,#+24] ;; Prefetch abort
ldr pc,[pc,#+24] ;; Data abort
__vector_0x14
DC32 0 ;; RESERVED
ldr pc,[pc,#+24] ;; IRQ
ldr pc,[pc,#+24] ;; FIQ
;jtk 上面的中断向量跳转到这里来,如果在c语言中有定义,
;下面的标号如果在c语言中有相应的处理程序,那么一旦有中断产生就会跳到相应的中断函数去
DC32 __iar_program_start ;; Reset
DC32 undef_handler ;; Undefined instructions
DC32 0 ;; Software interrupt (SWI/SVC)
DC32 prefetch_handler ;; Prefetch abort
DC32 data_handler ;; Data abort
DC32 0 ;; RESERVED
DC32 irq_handler ;; IRQ 跳转到 irq_handler 这个函数
上一篇:LPC17XX 学习之系统时钟与功率控制
下一篇:KEIL / MDK生成BIN文件
推荐阅读最新更新时间:2024-11-04 11:27
设计资源 培训 开发板 精华推荐
- 典型应用显示使用 A8519 LED 驱动器的可选 P-MOSFET 进行 VOUT 接地短路保护
- 【训练营】【物联网实战】立创EDA-830012A
- OP213FSZ-REEL7假接地发生器的典型应用
- AD8657ARMZ同相运算放大器配置的典型应用电路
- LTC2164 演示板,16 位 105Msps ADC,LVDS 输出,5-140MHz
- 具有低电池电量指示的 LTC4419CDD 早期电源故障警告的典型应用电路
- 具有 1.5A 开关电流的 LT3517 全功能 LED 驱动器的典型应用
- SY58012U,用于 SONET 的 5000MHz 时钟缓冲器的评估板
- 用于医疗的 4 节锂离子/锂聚合物电池充电器
- 具有迟滞功能的 MC33074ADR2G 低输入电压比较器的典型应用