实用指南:20250924的学习笔记
2025-09-27 21:49 tlnshuju 阅读(9) 评论(0) 收藏 举报i.MX6ULL 按键构建速查笔记(轮询 vs 中断)
一、轮询方式(Polling)
1. 初始化 4 大步
① 复用 IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B
MUX_MODE = ALT5 (0101b) → GPIO1_IO18
代码:IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);
② 电气 IOMUXC_SW_PAD_CTL_PAD_UART1_CTS_B
HYS=0 PUS=11b(22 kΩ上拉) PUE=1 PKE=1 ODE=0 SPEED=10b(100 MHz) DSE=000(输出禁用) SRE=0
代码:IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0xF080);
③ 方向 GPIO1->GDIR &= ~(1<<18); // 输入
④ 时钟 CCM_CCGR1 |= 0x3<<26; // 打开 GPIO1 门控(也可直接 CCM->CCGR1 = 0xFFFFFFFF)
2. 运行时
读 GPIO1->DR:
1 = 松开,0 = 按下(上拉 + 按键接地)
3. 缺陷
主循环若被大量耗时任务占用(如 delay(0x7FFFFF)),会漏采样 → 实时性丧失(“汽车刹车”场景不可用)
二、中断方式(GPIO 外部中断 → GIC)
1. 中断路径
外设 GPIO → GIC(SPI) → CPU interface → Core-A7 → 向量表 → 用户 ISR
2. GIC 中断号
IMX6ULL 外设中断 0–159(MCIMX6Y2.h 的 IRQn_Type)
GPIO1_IO16–31 合并为 SPI:GPIO1_Combined_16_31_IRQn(查表 53 号)
3. 关键寄存器
• Distributor:使能、优先级、分组
• CPU interface:应答、优先级屏蔽、EOI
• CP15:
VBAR = 0x87800000 (__set_VBAR)
CBAR 保存 GIC 物理基址(0x00A00000)
4. 中断调整步骤(GPIO1_IO18 例程)
① 初始化同上(复用、电气、方向、时钟)
② 边沿触发 GPIO1->ICR2 |= 3<<4; // 双边沿
③ 取消屏蔽 GPIO1->IMR |= 1<<18;
④ GIC 使能 GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn);
⑤ 优先级 GIC_SetPriority(GPIO1_Combined_16_31_IRQn, 0);
⑥ 注册 system_interrupt_register(GPIO1_Combined_16_31_IRQn, key_irq_handler);
⑦ 向量表 system_interrupt_init(); // 设置 VBAR + GIC_Init()
5. ISR 注意事项
• 清 GPIO 中断标志:GPIO1->ISR = 1<<18;
• 清 GIC 挂起:GIC_ClearPendingIRQ(...)
• 简短迅速,可追加消抖(简单延时或定时器)
三、速记口诀
“轮询四步:复用-电气-方向-时钟;
中断加四:边沿-屏蔽-GIC-向量;
标志清俩:GPIO ISR + GIC pending;
实时用中断,轮询只教学。”
四、按照中断流程编写代码

(1)中断源:
1.中断配置寄存器(触发方式)
GPI01_ICR2:
GPIO1->1CR2|=(3<<4);
2.中断屏蔽寄存器(解除屏蔽)
GPI01_IMR:
GPI01->IMR|=(1<<18);
3.中断状态寄存器(判断中断)
GPI01_ISR:
if((GPI01->|SR&(1<<18))!=0)
{
led_norO;
GPIO1->ISRI=(1<<18);
}
(2)GIC:
1.GIC的初始化
GIC_Init();
2.使能irq中断
GIC_EnableIRQ(99);
3.中断优先级设置
GIC_SetPriority(99,0);
4.获取GIC寄存器组基地址
mrc p15, 4, r0, c15, c0,0
5.中断通知寄存器
C_IAR:base+offect(0x200C)
add r0,r0,#0x2000
ldr, r1,[r0,#0x0C]
6.中断结束寄存器
C_E0IR:base+offect(0x2010)
str,r1,[r0,#0x10]
(3)Kernal:
1.异常向量表基地址重映射(顺便打开icache)
mrc p15, 0,r0,c1, c0, 0
bic r0,r0, #(1 <<13)
orr r0,r0,#(1<<12)
mcr p15, 0,r0, c1, c0, 0
__set_VBAR(0x87800000)
2.异常向量的处理函数
_irq_handler_:
sub 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
ldmfd sp!, {lr}
cps #0x12
ldmfd sp!, {r0, r1}
str r0,[r1, #0x10]
ldmfd sp!, {r0-r12, pc}^
3.中断处理函数
void system_interrupt_handler(IRQn_Type irq)
{
if (irq == GPIO1_Combined_16_31_IRQn)
{
if ((GPIO1->ISR & (1 << 18)) != 0)
{
GPIO1->ISR = (1 << 18);
}
}
}
浙公网安备 33010602011771号