Days 47 IMX6ULL 裸机开发:按键轮询实验 + 外部中断原理剖析(上)

IMX6ULL 裸机开发:按键轮询实验 + 外部中断原理剖析

前言

最近在做 i.MX6ULL 裸机驱动开发,前面已经完成 GPIO 点亮 LED、移植 NXP SDK 驱动蜂鸣器,还重构工程、改写 Makefile、手写链接脚本,把代码段、数据段、BSS 段在 RAM 中的排布全部自己定义。

本次实验先从最简单的按键轮询采集入手,直观发现轮询方式的缺陷;接着引入中断,讲解 ARM Cortex-A7 中断基础、GIC V2 中断控制器、CP15 协处理器相关寄存器,为后面编写外部中断按键驱动打下理论基础。

开发环境:i.MX6ULL-Mini 开发板,裸机无操作系统,C 语言 + ARM 汇编,Makefile 管理工程

一、课前回顾

前面实验要点回顾:

  1. 使用 C 语言直接操作 GPIO 寄存器,实现 LED 点灯;
  2. 移植 NXP SDK 包,基于寄存器方式驱动蜂鸣器 Beep;
  3. 工程重构,手动修改 Makefile,配置编译、链接规则;
  4. 手写链接脚本,自定义 .text.data.bss 等段在 RAM 中的地址排布。

课前思考题

  1. volatile 关键字的作用?
  2. 链接脚本(.ld)的作用是什么?
  3. (拓展)裸机程序中,BSS 段为什么需要在代码里手动清零?

二、按键轮询实验

在正式学习中断之前,先实现按键轮询驱动,观察按键读取现象,理解轮询方式的短板。

2.1 硬件介绍

i.MX6ULL-Mini 底板:

  • 一共 3 个按键:两个红色、一个黄色;
  • 中间按键:硬件复位按键;
  • 左侧:低功耗按键;
  • 右侧:本次实验使用的用户测试按键;
  • 按键电路原理:按键断开时为高电平,按键按下时拉低为低电平

查阅文档:

  1. IMX6ULL_MINI_V2.2 (Mini 底板原理图).pdf
  2. IMX6ULL 参考手册.pdf

2.2 按键驱动代码编写(轮询方式)

实验选用引脚:UART1_CTS_B,复用为 GPIO1_IO18。 按键驱动分为四步:引脚复用配置、PAD 电气属性配置、GPIO 方向配置、开启 GPIO 时钟

① IOMUX 引脚复用配置

寄存器:IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B 章节:IOMUX Controller (IOMUXC) Chapter32

  • MUX_MODE(低 4 位):0101,ALT5 模式,映射为 GPIO1_IO18

  • SION:0,关闭输入强制功能,输入路径由硬件功能决定

    IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);

② PAD 电气属性配置

寄存器:IOMUXC_SW_PAD_CTL_PAD_UART1_CTS_B

复制代码
IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0xF080);

各位含义:

表格

说明
HYS 0 关闭迟滞比较器
PUS 11 22K 上拉电阻
PUE 1 选择拉电阻功能
PKE 1 使能拉电阻
ODE 0 关闭开漏输出
SPEED 10 100MHz,中等速率
DSE 000 关闭输出驱动(输入引脚不需要)
SRE 0 低速压摆率

因为按键是输入引脚,所以 DSE 输出驱动能力关闭,配置上拉。

③ GPIO 方向寄存器 GDIR

GPIO1_IO18 设置为输入:

复制代码
GPIO1->GDIR &= ~(1 << 18);
  • bit = 0:GPIO 输入
  • bit = 1:GPIO 输出
④ 开启 GPIO1 时钟

CCM 时钟模块,CCM_CCGR1 寄存器,GPIO1 组时钟门控,打开 GPIO1 外设时钟。

⑤ 运行时读取按键电平

GPIO 数据寄存器 GPIOx_DR

  • 按键松开:高电平
  • 按键按下:低电平 轮询代码逻辑:循环不断读取 DR 寄存器,判断电平,检测按键状态。

2.3 轮询方式存在的致命问题

核心痛点:轮询方式在主程序有大量耗时业务时,会丢失按键事件,发生漏检!

模拟场景:在主循环中加入长时间延时函数 delay(0x7FFFFF);,模拟 CPU 正在处理复杂业务。 此时如果按下按键,CPU 卡在 delay 里,没有读取 GPIO 电平,按键按下这个事件就丢失了。

举个工业场景例子:汽车刹车信号,如果用轮询检测,CPU 正在处理别的任务时,刹车信号漏检会引发严重事故。 👉 解决方案:中断! 不需要 CPU 一直轮询查询,外设事件主动通知 CPU。


三、中断基础原理

3.1 什么是中断

中断:CPU 暂停当前正在执行的程序,跳转去处理紧急外设事件;中断服务函数处理完成后,返回原来被打断的代码继续执行。

中断参与对象:

  • 内核:被打断的主体
  • 外设:产生中断请求(GPIO 外部中断)

3.2 中断完整处理流程

  1. 中断源产生中断请求;
  2. CPU 判断是否允许响应中断、中断是否被屏蔽;
  3. 判断中断优先级;
  4. 保护现场:保存当前寄存器上下文;
  5. 执行中断服务函数 ISR;
  6. 恢复现场,回到被打断代码继续运行。

GPIO 产生的中断,属于外部中断 EINT

3.3 GIC V2 通用中断控制器(重点)

GIC 全称:Generic Interrupt Controller,通用中断控制器。i.MX6ULL 使用 GIC V2 版本。 参考文档:ARM Generic Interrupt Controller(ARM GIC控制器)V2.0.pdf

GIC V2 最多支持 8 个处理器核,i.MX6ULL 只有单核 Cortex-A7,只用 Processor 0。 最多支持 1020 个中断源,中断类型划分:

  1. SGI(Software-generated Interrupt)软件中断:中断号 0~15 软件写 GICD_SGIR 寄存器触发,多用于多核之间通信。
  2. PPI(Private Peripheral Interrupt)私有外设中断:中断号 16~31 属于每个 CPU 私有的中断,只能由指定内核处理。
  3. SPI(Shared Peripheral Interrupt)共享外设中断:中断号 32~1019 所有外设产生的硬件中断都属于 SPI(⚠️注意不是 SPI 总线!),我们的 GPIO 外部中断就是 SPI 中断。

GIC 两大模块:

  1. Distributor 分发器:管理所有中断源,使能中断、设置中断优先级、中断目标 CPU;
  2. CPU Interface CPU 接口:CPU 内核和 GIC 分发器之间的接口,CPU 从中读取中断号、确认中断结束。

i.MX6ULL 参考手册中断章节:3.2 Cortex A7 interrupts,中断编号范围 0~128; MCIMX6Y2.h 头文件中 IRQn_Type 定义外设中断 0~159。

3.4 CP15 协处理器(Cortex-A7)

Cortex-A7 有 cp0~cp15 协处理器,CP15 是系统控制协处理器 ,负责系统底层控制。 参考手册:Cortex-A7 Technical ReferenceManua.pdf Chapter4 System Control

CP15 主要功能
  • 系统全局配置;
  • MMU 内存管理单元配置;
  • Cache 配置;
  • 虚拟化与安全模式配置;
  • 系统性能监控;

CP15 的寄存器编号 c0 ~ c15,不能直接用 C 指针访问,必须使用 ARM 汇编指令:

  • MRC:协处理器寄存器 → 通用寄存器(读)

  • MCR:通用寄存器 → 协处理器寄存器(写)

    MRC{} , , , , {, }
    MCR{} , , , , {, }

中断相关 CP15 寄存器
  1. c0:MIDR 主 ID 寄存器,读取 CPU 内核版本信息;

  2. c1:SCTLR 系统控制寄存器

    • bit13:V,异常向量表基址选择;0=0x00000000,1=0xFFFF0000;
    • bit12:I,指令 Cache 开关;0 关闭,1 开启。

    mrc p15,0,r0,c1,c0,0
    bic r0, r0, #(1 << 13)
    orr r0, r0, #(1 << 12)
    mcr p15,0,r0,c1,c0,0

  3. c12:VBAR 向量基址寄存器,设置异常向量表基地址,裸机中断必备;

    __get_VBAR(0x87800000);

  4. c15:CBAR GIC 基址寄存器,读取 GIC 控制器物理基地址。

    mrc p15, 4, r0, c15, c0, 0

相关推荐
一条破秋裤1 小时前
Hi3516CV610 20S V4 开发板启动与调试流程
学习
sunoo-2291 小时前
【ARM嵌入式学习笔记Day6】一文打通i.MX6ULL时钟体系:PLL/PFD/预分频+滞回比较器全解析
arm开发·笔记·vscode·单片机·imx6ull·汇编语言
G.E.M.小白1 小时前
【IMX6ULL ARM内核启动与时钟系统超详解】PLL/PFD/分频/根时钟配置
嵌入式·arm·时钟·imx6ull
AAA代码批发商1 小时前
Days 50 51 单片机与 i.MX6ULL 定时器对比:Timer、EPIT、GPT 原理与实验
51单片机·定时器·imx6ull·裸机开发
景煜拾年1 小时前
RHCA-Docker知识点整理
运维·笔记
P.D.Wei2 小时前
[Leetcode 3524] 求出数组的X值I
python·学习
边境悍匪2 小时前
蜗牛学苑 Java 智能体学习 Day46|贯穿项目 2 思维导图复盘
java·开发语言·vue.js·学习·spring
M78佐菲9 小时前
ARM学习笔记(1)
linux·arm开发·笔记·嵌入式硬件·学习
益达丫11 小时前
Socket编程揭秘:端口、IP与进程通信的底层逻辑
linux·笔记