
1.C中断初始化和按键初始化
第一步:设置异常向量表基地址(VBAR)
__set_VBAR是一个封装了 ARM 协处理器指令 MCR 的函数,作用是设置 VBAR(Vector 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的优先级最高


完整代码为:
cs
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 方向寄存器,&= ~(1<<18) 表示将第 18 位清 0 → 输入模式(按键是输入)
GPIO1->GDIR &= ~(1 << 18);
// 4. 配置中断触发方式:ICR2 是 GPIO 中断配置寄存器2,(0x3 << 4) 表示"下降沿触发"(因为 0x3 对应下降沿)
GPIO1->ICR2 |= (0x3 << 4);
// 5. 使能 GPIO 中断:IMR 是中断屏蔽寄存器,|= (1<<18) 表示将第 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(系统级中断处理,由汇编调用)
cs
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的IAR(Interrupt Acknowledge Register),获取当前中断号。 - 后续处理 :根据中断号计算GIC寄存器偏移(+0x200C),读取中断状态;若为GPIO1_IO18中断,则调用C语言处理函数
system_irq_handler,处理完毕后写入EOIR(偏移0x10)清除中断。
翻cortex-A7手册 找到System Control Reguster

1. 设置异常向量表基地址(VBAR)为0
2. 配置 SCTLR 寄存器(系统控制寄存器)
- 目的:启用指令缓存、禁用 MMU,确保在无操作系统环境下能正确执行代码。
- 关键位设置 :
- 第 12 位(I 位) :置 1 → 启用指令缓存
- 第 13 位(C 位) :清 0 → 禁用 MMU(内存管理单元)

- 实现方式 :
- 使用
MRC读取 SCTLR 当前值到寄存器 R1; - 使用
ORR将第 12 位置 1; - 使用
BIC将第 13 位清 0; - 使用
MCR写回 SCTLR。
- 使用


- 设置中断
调用这个函数去C 东西放R0里面

获取基地址(手册)


**获取基地址(**头文件里面)

找到的GIC是结构体的 实际的IAR有偏移 如下所示

汇编文件 start.S中的 _irq_handler(IRQ 中断处理汇编代码)
cs
_irq_handler:
sub lr, lr, #4 ; 修正返回地址(LR是中断时CPU自动存的PC+4,减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(返回被中断的程序)