正点原子 I.MX6ULL MINI 开发板学习笔记:ARM Cortex-A7 中断控制器 GIC

分享
中断响应流程

这篇笔记继续正点原子 I.MX6ULL MINI 开发板裸机学习,主题是ARM Cortex-A7 的中断系统。代码来自实际工程 /home/zhao/code/2026/touch_screen。

1. 完成什么实验?

理解 ARM Cortex-A7 中断响应流程,掌握 GIC(Generic Interrupt Controller)的初始化和中断注册方法。后续按键、EPIT、GPT、PWM、触摸屏等都依赖这套中断机制。

2. 什么是中断?

中断是外设或内部事件主动通知 CPU 的一种机制。当事件发生时,CPU 会暂停当前程序,跳转到预先设置好的中断处理函数执行;处理完后再返回原程序。相比轮询,中断能大大提高 CPU 效率。

3. ARM Cortex-A7 中断响应要经过哪几步?

  1. 外设产生中断请求,送到 GIC Distributor。
  2. Distributor 根据优先级选择一个最高优先级的中断,发给 CPU Interface。
  3. CPU Interface 向 CPU 发出 IRQ 信号。
  4. CPU 进入 IRQ 异常模式,从 VBAR 指向的向量表找到 IRQ 入口。
  5. 汇编入口保存现场,读取中断号,调用 C 层的 system_interrupt_handler(irq)。
  6. 根据中断号分发到用户注册的 key_handler、epit1_interrupt_handler 等函数。
  7. 处理完后清除中断标志,恢复现场,返回原程序。
GIC 结构

4. GIC 是什么?

GIC(Generic Interrupt Controller)是 ARM Cortex-A 系列处理器配套的中断控制器。它分为两部分:Distributor 负责接收和仲裁所有中断源;CPU Interface 负责把选中的中断发送给 CPU,并管理中断的使能、优先级和应答。

5. VBAR 向量表起什么作用?

Cortex-A7 发生异常(复位、未定义指令、IRQ、FIQ 等)时,硬件会从向量表取入口地址。代码中通过 <code>__set_VBAR(0x87800000)</code> 把向量表地址告诉 CPU;而 0x87800000 处正是 start.S 里放好的 IRQ 处理入口。

6. 真实可用的中断初始化代码

下面是工程中验证过的中断相关代码。

#include "interrupt.h"
#include "MCIMX6Y2.h"
#include "fsl_iomuxc.h"
#include "core_ca7.h"

static irq_handler_t interrupt_vector_table[160];

void system_interrupt_init(void)
{
    __set_VBAR(0x87800000);     /* 设置向量表基地址 */
    GIC_Init();                 /* 初始化 GIC */
}

void system_interrupt_register(irq_handler_t handler, int num)
{
    interrupt_vector_table[num] = handler;
}

void system_interrupt_handler(int irq)
{
    if (interrupt_vector_table[irq] != NULL)
    {
        interrupt_vector_table[irq]();
    }
}
.global _start

_start:
    ldr pc, =_reset_handler
    ldr pc, =_undefined_handler
    ldr pc, =_svc_handler
    ldr pc, =_prefetch_handler
    ldr pc, =_data_abort_handler
    ldr pc, =_not_user_handler
    ldr pc, =_irq_handler       /* 中断入口 */
    ldr pc, =_fiq_handler

_irq_handler:
    subs lr, lr, #4
    stmfd sp!, {r0-r12, lr}

    mrc p15, 4, r1, c15, c0, 0
    add r1, r1, #0x2000
    ldr r0, [r1, #0x0C]        /* 读取中断号 */

    stmfd sp!, {r0, r1}

    cps #0x1F
    stmfd sp!, {lr}
    bl system_interrupt_handler /* 调用 C 层分发函数 */
    ldmfd sp!, {lr}

    cps 0x12
    ldmfd sp!, {r0, r1}
    str r0, [r1, #0x10]        /* 写 EOIR,通知 GIC 中断处理完成 */

    ldmfd sp!, {r0-r12, pc}^   /* 恢复现场并返回 */

7. 关键点说明

  • VBAR 必须在 GIC 之前设置:否则 CPU 找不到 IRQ 入口,程序会跑飞。
  • 中断号:I.MX6ULL 为每个中断源分配了唯一中断号(如 GPIO1_Combined_16_31_IRQn、EPIT1_IRQn),注册和使能时要一致。
  • 使能中断两步走:外设自身使能中断(如 GPIO IMR)+ GIC 使能(GIC_EnableIRQ)。
  • 清中断标志:外设状态寄存器要写 1 清除,否则中断会反复触发。
  • 现场保护:start.S 中保存了 r0-r12、lr,C 函数里如果用到浮点等还要额外保存。

8. 实验现象

正确初始化中断后,按下 KEY0 会立即进入 key_handler 并翻转 LED;EPIT/GPT 定时器到点会进入对应中断服务函数。如果 VBAR 没设或 GIC 没初始化,中断来了程序会卡死或跑飞。

总结

问题答案
什么是中断?外设主动通知 CPU 事件的机制,比轮询高效
GIC 分哪两部分?Distributor(分发/仲裁)和 CPU Interface(向 CPU 发 IRQ)
VBAR 作用?异常向量表基地址,告诉 CPU 异常入口在哪里
中断处理分几步?外设请求 → GIC 仲裁 → CPU 响应 → 向量表 → C 分发 → 用户 handler
使能中断要做什么?外设使能中断源 + GIC_EnableIRQ + 必要时设置优先级

掌握了中断,就可以用定时器、按键、触摸屏等事件驱动的方式来写程序了。下一篇介绍 EPIT 定时器。

继续阅读

嵌入式开发面试知识手册

嵌入式开发工程师面试知识手册 适用对象:零基础起步、目标是通过嵌入式软件/驱动/BSP 方向面试的读者 编写依据:赵哲简历全部知识点 + 智能车 AGV 控制平台完整项目代码(i.MX6ULL Linux 端 + STM32F407 固件)+ Linux 驱动练习代码包 + embedded-agent 嵌入式开发智能体仓库 + 真实面试手撕代码与追问记录 使用方法:每篇按"通俗解释 → 原理细节 → 命令/API → 代码实例 → 项目结合 → 记忆口诀 → 面试问答"组织;口诀用于快速记忆,问答用于自测。第9篇是讲项目的演练场,第10篇是手撕代码实战题库。 总目录 * 第1篇 C语言与数据结构 * 1.1 编译链接全过程 * 1.2 数据类型与内存

作者:azhezhezhe

正点原子 I.MX6ULL MINI 开发板学习笔记:Linux 驱动架构详解——编译、树内树外与运行时效果

这是 Linux 驱动小系列的总结篇。前三篇把 LED 驱动从内核模块写到 misc 设备,属于“会用”;这篇把背后的架构讲透:驱动到底怎么编译、内核树内和树外两种方式的区别、以及驱动里每个操作在系统跑起来之后到底产生了什么效果。内容整理自我的学习笔记(note.pdf)和实际工程 code/2026/20260803。 1. 驱动代码到底怎么编译的? 不管哪种方式,最终都靠内核的 kbuild 系统。核心就三个文件的关系: * Kconfig:定义 menuconfig 里的选项(如 CONFIG_MYMODULE),三态 y/m/n——y 编进内核,m 编成模块,n 不编; * .config:menuconfig 的选择结果,保存在源码顶层; * Makefile:

作者:azhezhezhe

正点原子 I.MX6ULL MINI 开发板学习笔记:misc 设备——字符设备驱动的快捷方式

上两篇分别用手动 mknod 和 class_create+device_create 注册字符设备,调用链一长串。这篇用 misc(混杂)设备 一步搞定。代码来自实际工程 code/2026/20260803/05_misc_led,已验证可用。 1. 完成什么实验? 用 misc_register 重写 LED 驱动:一步完成设备号分配、字符设备注册、/dev/myled0 节点创建,同时保留上一篇的 sysfs 属性 led_status。 2. 什么是 misc 设备? misc(混杂)设备是 Linux 给“不好归类的小字符设备”

作者:azhezhezhe