ARM-05-中断
1.C中断初始化和按键初始化第一步设置异常向量表基地址VBAR__set_VBAR是一个封装了 ARM 协处理器指令 MCR 的函数作用是设置 VBARVector Base Address Register异常向量表基地址寄存器。地址在lds里面,是0x87800000.第二步初始化GIC所以中断初始化函数写成下面这样子2.按键中断初始化第一步配置引脚功能和方向因为键盘初始化上次设置过了 所以直接搬过来。第二步配置中断触发方式通过查手册找到GPIO_ICR2 因为是下降沿触发所以 ICR18 设置为11则GPIO1-ICR2 | (0x3 4);第三步设置使能IMR中断掩码第18位置1第四步设置中断使能和中断优先级因为用的是IO18在引脚16到31的范围内所以在MCIMX6Y2.h里面找到 GPIO1_Combined_16_31_IRQn并且设置为0因为0的优先级最高完整代码为void key_irq_init(void) { // 1. 配置引脚复用将 UART1_CTS_B 引脚复用为 GPIO1_IO18按键输入引脚 IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0); // 2. 配置引脚属性设置 GPIO1_IO18 的上拉/下拉、驱动能力、速率等0x10B0 是芯片特定的配置值 IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0x10b0); // 3. 配置 GPIO 方向GDIR 是 GPIO 方向寄存器 ~(118) 表示将第 18 位清 0 → 输入模式按键是输入 GPIO1-GDIR ~(1 18); // 4. 配置中断触发方式ICR2 是 GPIO 中断配置寄存器2(0x3 4) 表示“下降沿触发”因为 0x3 对应下降沿 GPIO1-ICR2 | (0x3 4); // 5. 使能 GPIO 中断IMR 是中断屏蔽寄存器| (118) 表示将第 18 位设为 1 → 使能 GPIO1_IO18 的中断 GPIO1-IMR | (1 18); // 6. 使能 GIC 中断告诉 GIC 控制器允许“GPIO1_Combined_16_31_IRQn”这个中断分发到 CPU GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn); // 7. 设置中断优先级将这个中断的优先级设为 0数值越小优先级越高0 是最高优先级之一 GIC_SetPriority(GPIO1_Combined_16_31_IRQn, 0); }2.C 函数 system_irq_handler系统级中断处理由汇编调用void system_irq_handler(IRQn_Type irq_num) { // 判断是否是“GPIO1_Combined_16_31_IRQn”这个中断即 GPIO1 的 16~31 引脚共享的中断 if (irq_num GPIO1_Combined_16_31_IRQn) { // 检查 GPIO1 的 ISR中断状态寄存器的第 18 位对应 GPIO1_IO18 引脚 if (GPIO1-ISR (1 18)) { led_on(); // 点亮 LED自定义函数控制 LED 引脚输出高/低 beep_on(); // 打开蜂鸣器自定义函数控制蜂鸣器引脚输出高/低 // 清除 GPIO1 的中断标志向 ISR 的第 18 位写 1清除中断状态否则中断会一直触发 GPIO1-ISR | (1 18); } } }三修改start.c(汇编部分)中断汇编入口与IAR读取机制中断触发流程当GPIO中断发生CPU跳转至汇编异常入口。核心操作通过MRC p15, 0, r0, c12, c0, 0读取GIC的IARInterrupt Acknowledge Register获取当前中断号。后续处理根据中断号计算GIC寄存器偏移0x200C读取中断状态若为GPIO1_IO18中断则调用C语言处理函数system_irq_handler处理完毕后写入EOIR偏移0x10清除中断。翻cortex-A7手册 找到System Control Reguster1.设置异常向量表基地址VBAR为02.配置 SCTLR 寄存器系统控制寄存器目的启用指令缓存、禁用 MMU确保在无操作系统环境下能正确执行代码。关键位设置第 12 位I 位置 1 →启用指令缓存第 13 位C 位清 0 →禁用 MMU内存管理单元实现方式使用MRC读取 SCTLR 当前值到寄存器 R1使用ORR将第 12 位置 1使用BIC将第 13 位清 0使用MCR写回 SCTLR。2.设置中断调用这个函数去C 东西放R0里面获取基地址手册获取基地址头文件里面找到的GIC是结构体的 实际的IAR有偏移 如下所示汇编文件 start.S中的 _irq_handlerIRQ 中断处理汇编代码_irq_handler: sub lr, lr, #4 ; 修正返回地址LR是中断时CPU自动存的PC4减4才是正确返回位置 stmfd sp!, {r0-r12, lr} ; 保存R0-R12和LR到栈保护现场 mrc p15, 4, r1, c15, c0, 0 ; 通过协处理器读取GIC基地址到R1 add r1, r1, #0x2000 ; 加上0x2000偏移芯片特定指向GIC的CPU接口区 ldr r0, [r1, #0xc] ; 读取GIC_IAR中断确认寄存器获取当前中断号 stmfd sp!, {r0,r1} ; 暂存中断号和GIC地址到栈 cps #0x1f ; 切换到System模式方便执行C代码 stmfd sp!, {r0-r12, lr} ; 在System模式下再次保存现场 bl system_irq_handler ; 调用C语言中断处理函数R0已包含中断号 ldmfd sp!, {r0-r12, pc} ; 恢复System模式现场并返回 cps #0x12 ; 切换回IRQ模式GIC操作必须在IRQ模式 ldmfd sp!, {r0, r1} ; 恢复中断号和GIC地址 str r0, [r1, #0x10] ; 写GIC_EOIR中断结束寄存器通知GIC中断已处理 ldmfd sp!, {r0-r12, pc}^ ; 恢复IRQ模式现场^表示恢复CPSR返回被中断的程序