北京市网站建设_网站建设公司_响应式网站_seo优化
2026/1/22 6:37:17 网站建设 项目流程

目录

一、中断的引用

1.1 轮询方式的局限性

1.2 中断系统简介

二、ARM 中断系统硬件架构

2.1 通用中断控制器 GIC

2.1.1 GIC 中断分类

2.1.2 架构组成

2.2 协处理器 CP15

2.2.1 访问指令

2.2.2 关键寄存器

三、代码实现:中断驱动的按键控制

3.1 向量表管理与初始化

3.2 GPIO 与中断配置

3.3 中断服务函数 (ISR)

3.4 主程序流程

四、软件设计原则:低耦合与 OCP


一、中断的引用

1.1 轮询方式的局限性

在学习中断之前,我们通常使用轮询(Polling)的方式来处理按键等外设输入:

while (1) { if ((GPIO1->DR & (1 << 18)) == 0) // 检测到低电平 { led_nor(); beep_nor(); } delay(0x7FFFFF); // 模拟大量复杂业务 }

轮询方式的原理:CPU 周期性地读取 GPIO 引脚状态,判断是否有按键按下。

轮询的致命缺陷:

  • 漏查风险:当主程序需要处理大量、复杂且耗时的业务时(例如模拟一个 delay(0x7FFFFF) 的长延时),CPU 无法及时检查按键状态。
  • 实时性差:就像“汽车刹车”这种高实时性场景,如果 CPU 正在处理其他任务而无法立即响应刹车信号,后果不堪设想。

因此,我们需要引入中断(Interrupt)。

1.2 中断系统简介

定义:中断是指 CPU 能打断当前正在进行的工作,去处理更为紧急的任务(中断服务函数),并且在处理完后,能自动回到原先的地方继续工作。

中断处理的标准流程:

  1. 中断请求:中断源(外设)发出信号。
  2. 中断响应检查:CPU 检查是否响应该中断,以及该中断是否被屏蔽。
  3. 优先级检查:GIC 判定当前中断的优先级。
  4. 保护现场:保存被暂停程序的上下文。
  5. 执行中断服务函数(ISR):处理紧急任务。
  6. 恢复现场:还原上下文,继续执行原程序。

二、ARM 中断系统硬件架构

2.1 通用中断控制器 GIC

IMX6ULL 使用的是单核 Cortex-A7,其内部集成了 GIC v2.0 控制器。GIC 负责管理所有的中断源,并决定分发给哪个核心处理。GIC逻辑分区如下:

GIC逻辑分区

2.1.1 GIC 中断分类

根据 ARM GIC v2.0 规范,中断源被分为三类(共 1020 个 ID):

类型全称ID 范围描述
SGISoftware-generated Interrupt (软件中断)0 - 15由软件向寄存器 GICD_SGIR 写入数据触发,常用于多核间通信。
PPIPrivate Peripheral Interrupt (私有中断)16 - 31每个核心独有的中断(如 Generic Timer),必须由指定核心处理。
SPIShared Peripheral Interrupt (共享中断)32 - 1019外部外设产生的中断(如 GPIO、I2C 等),所有核心共享。

注意:这里的 SPI 指的是共享中断,不要和通信协议 SPI 总线混淆。

2.1.2 架构组成

GIC 主要由两部分组成:

  • Distributor (分发器):负责检测、排序和分发中断。
  • CPU Interface (CPU 接口):负责将分发器发送的中断信号传输给处理器核心。

2.2 协处理器 CP15

在配置中断和系统底层时,离不开协处理器 CP15。它负责系统控制、MMU 配置、Cache 管理以及虚拟化等任务。

2.2.1 访问指令

CP15 包含 c0 到 c15 组寄存器,通过专用指令访问:

  • MRC:读 CP15 寄存器。
  • MCR:写 CP15 寄存器。

2.2.2 关键寄存器

  • MIDR (Main ID Register, c0):存储内核的基本信息。
  • SCTLR (System Control Register,c1):系统控制寄存器,其中两个位至关重要:
    • Bit 13 (V 位):控制异常向量表的基地址。
      • 0:基地址为 0x00000000(软件可通过 VBAR 重映射)。
      • 1:基地址为 0xFFFF0000(高地址向量,不可重映射)。
    • Bit 12 (I 位):指令 Cache 开关。
  • VBAR (Vector Base Address Register, c12):向量基地址寄存器,用于重新映射异常向量表的基地址。在IMX6ULL中,我们将向量表重映射到 0x87800000。
  • CBAR (Configuration Base Address Register, c15):配置基地址寄存器,指向GIC控制器的物理基地址。

三、代码实现:中断驱动的按键控制

本文的核心目标是实现 "按键中断触发 LED 翻转 + 蜂鸣器翻转",遵循 "低耦合、高可扩展" 的设计原则。

3.1 向量表管理与初始化

首先,我们需要定义一个中断服务函数指针数组,用于注册和管理中断。

// 定义中断向量表 typedef void (*irq_handler_t)(void); irq_handler_t Vector_table[160]; // 系统中断初始化 void system_interrupt_init(void) { // 1. 重映射异常向量表基地址 __set_VBAR(0x87800000); // 2. 初始化GIC控制器 GIC_Init(); } // 注册中断处理函数 int system_interrupt_register(IRQn_Type irq, irq_handler_t handler) { if (irq > PMU_IRQ2_IRQn || irq < IOMUXC_IRQn) return -1; if (handler == NULL) return -2; Vector_table[irq] = handler; // 将中断号与处理函数关联 return 0; }

3.2 GPIO 与中断配置

在 key_init 中,我们不仅配置 GPIO 为输入,还需要配置 GPIO 的中断触发方式和使能。

  • 复用配置:将 UART1_CTS_B 复用为 GPIO1_IO18。
  • 电气特性:配置上拉电阻和输入迟滞。
  • 中断触发:配置 GPIO1->ICR2 寄存器,选择下降沿触发(按下时电平由高变低)。
  • 中断使能:配置 GPIO1->IMR 寄存器,置位对应位以允许中断。
void key_init(void) { // 1. 复用功能配置 IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0); // 2. 电气特性配置 IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0xF0B0); // 3. 引脚方向设置为输入模式 GPIO1->GDIR &= ~(1 << 18); // 4. 配置中断触发方式 (ICR2寄存器,bit4-5对应GPIO1_18) GPIO1->ICR2 |= (3 << 4); // 下降沿触发 // 5. 中断屏蔽寄存器 (IMR) - 解除屏蔽 GPIO1->IMR |= (1 << 18); // 6. GIC配置 GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn); // 使能该中断 GIC_SetPriority(GPIO1_Combined_16_31_IRQn, 0); // 设置优先级 // 7. 注册回调函数 system_interrupt_register(GPIO1_Combined_16_31_IRQn, key_irq_handler); }

3.3 中断服务函数 (ISR)

当中断发生时,CPU会跳转到对应的处理函数。

void key_irq_handler(void) { // 检查GPIO中断状态寄存器 (ISR) // 注意:ISR用于指示中断是否发生,IMR用于使能/屏蔽。 if ((GPIO1->ISR & (1 << 18)) != 0) { // 执行业务逻辑:翻转LED和蜂鸣器 led_nor(); beep_nor(); // 必须手动清除中断标志位 GPIO1->ISR |= (1 << 18); } }

3.4 主程序流程

主程序在初始化完成后,进入无限循环,此时CPU可以自由执行其他任务(如 g_delay),而按键的中断请求会被GIC捕获并打断主循环。

int main(void) { system_interrupt_init(); // 初始化中断系统 clock_cg_init(); // 开启时钟 beep_init(); led_init(); key_init(); // 配置按键中断 while (1) { g_delay(0x7FFFF); // 主循环执行耗时任务,但不会阻塞中断响应 } return 0; }

四、软件设计原则:低耦合与 OCP

在编写中断驱动代码时,我们遵循了良好的软件工程原则:

  1. 低耦合:
    1. 中断模块只负责中断的底层处理(如向量表管理)。
    2. GPIO模块只负责引脚的输入输出。
    3. 业务逻辑(按键处理)独立封装。
  2. 开闭原则 (OCP):
    1. 对修改关闭:核心的中断分发逻辑(system_interrupt_handler)不需要因为新增设备而修改。
    2. 对扩展开放:当需要增加一个新的按键或设备时,只需调用 system_interrupt_handler 注册一个新的函数指针,无需改动核心代码。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询