当前位置: 首页 > news >正文

学习嵌入式第五十三天

文章目录

  • 中断
    • 一、按键
      • 1.初始化
      • 2.运行时开关检测
    • 二、中断
      • 1.概念
      • 2.中断控制器GIC
      • 3.协处理器(coprocrssor)
    • 三、中断实现流程
      • 1.相关寄存器与关键偏移
      • 2.初始化阶段流程
        • 1. 中断控制器初始化
        • 2. 外设初始化
        • 3. 注册回调函数
      • 3.异常向量与 IRQ 入口
      • 4.IRQ 进入时的汇编执行流程
      • 5.根据中断ID调用相应的用户注册的处理函数
      • 6.代码与流程串联速览

中断

一、按键

1.初始化

  • 复用功能配置
    1. IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B:低四位(0101)
    2. IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0);
    3. SION(信号监控)1位:0 //DISABLED
    4. MUX_MODE(复用功能)4:0101
  • 电气特性
    1. IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0xF080);
    2. HYS(压摆率)1位:0 //HYS_0_Hysteresis_Disabled;
    3. PUS(上拉或下拉)2位:11 //PUS_3_22K_Ohm_Pull_Up — 22K Ohm Pull Up
    4. PUE(拉与保持选择)1位: 1 //选择拉
    5. PKE(拉或保持使能)1位: 1 //使能
    6. ODE(漏极开漏)1位: 0 //使能
    7. SPEED(速度)2位: 10 //SPEED_2_medium_100MHz_ — medium(100MHz)
    8. DSE(驱动能力)3位: 000 //DSE_0_output_driver_disabled_ — output driver disabled; 输出是才有用,所以关闭
    9. SRE(系统寄存器使能)1位: 0 //SRE_0_Slow_Slew_Rate — Slow Slew Rate
  • 方向寄存器
    1. GPIO1->GDIR &= ~(1 << 18)
    2. 0 INPUT — GPIO is configured as input
    3. 1 OUTPUT — GPIO is configured as output
  • GPIO工作时钟
    • 打开CCM Clock Gating Register ,CCM_CCGR1: GPIO1组所有引脚共用该CG门;

2.运行时开关检测

  • GPIO数据寄存器
    • GPIO1_DR:开关断开高电平,开关按下低电平

二、中断

1.概念

  • CPU能打断当前正在进行的工作,去处理更为紧急的任务,并且在处理完中断任务后,可以回到原先的地方继续工作
  • 中断流程
    1. 中断源发出中断请求
    2. CPU检查是否响应中断以及该终端是否被屏蔽
    3. 检查当前产生的中断的中断优先级
    4. 保护现场
    5. 执行中断服务函数
    6. 恢复现场

2.中断控制器GIC

  • 通用的中断控制器
  • 每个内核可以响应1020个中断源,其中015是SGI,1631是PPI,能够作为外设中断源的是SPI32~1019
  • Distributor
    1. SGI(Software-generated Interrupt),软件中断:由软件触发引起的中断,通过向寄存器GICD_SGIR 写入数据来触发,系统会使用 SGI 中断来完成多核之间的通信
    2. PPI(Private Peripheral Interrupt),私有中断: GIC 是支持多核的,每个核都有自己独有的中断。这些独有的中断势必是要指定的核心处理,而这些中断就叫做私有中断
    3. SPI(Shared Peripheral Interrupt),共享中断:可以被任意一个CPU处理,GIC会将SPI分配给最适合的CPU,可以避免单个CPU过载

3.协处理器(coprocrssor)

  • 功能:负责所有系统控制与配置和MMU的配置与管理,以及Cache的配置与管理,并负责虚拟化和安全设置和系统性能监视
  • 寄存器组:c0~c15
  • cp15寄存器读写
    • 读:MRC<c> <coproc>, <opc1>, <Rt>, <CRn>, <CRm>{, <opc2>}
    • MCR<c> <coproc>, <opc1>, <Rt>, <CRn>, <CRm>{, <opc2>}
  • 中断相关寄存器组
    • c0 registers:MIDR(Main ID Register):主标识寄存器,存储内核的一些基本信息,识别处理器型号和版本
    • c1 registers:SCTLR(System Control Register):系统控制寄存器,控制处理器核心功能
    • c12 registers:VBAR(Vector Base Address Register),异常向量表基地址寄存器,存储异常向量表的基地址,并决定CPU发生异常时跳转到哪里
    • c15 registers:CBAR(Configuration Base Address Register),配置基地址寄存器,存储GIC分发器的基地址,用于软件定位GIC硬件模块

三、中断实现流程


1.相关寄存器与关键偏移

模块基础来源说明
VBAR软件设置异常向量表基地址
CBARmrc p15,4,r1,c15,c0,0GIC Distributor 基地址(硬件定义)
CPU Interface 基地址CBAR + 0x2000GIC CPU Interface
IAR (Interrupt Acknowledge)CPU_IF + 0x0C读取当前待处理的中断 ID
EOIR (End Of Interrupt)CPU_IF + 0x10写入中断 ID 以结束处理

2.初始化阶段流程

1. 中断控制器初始化
void system_interrupt_init(void) {__set_VBAR(0x87800000);  // 设置异常向量表基地址GIC_Init();              // 初始化 GIC
}
2. 外设初始化
void key_init(void){IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0);IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF0B0);GPIO1->GDIR &= ~(1 << 18);          // 输入GPIO1->ICR2 |= (3 << 4);            // 双边沿 or 具体边沿配置GPIO1->IMR  |= (1 << 18);           // 解除屏蔽system_interrupt_register(GPIO1_Combined_16_31_IRQn, key_16_31_handler);GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn);GIC_SetPriority(GPIO1_Combined_16_31_IRQn, 0);
}
3. 注册回调函数
static irq_interrupt_t interrupt_Vector_table[160] = { NULL };void system_interrupt_register(unsigned int irq, irq_interrupt_t handler) {interrupt_Vector_table[irq] = handler;
}

3.异常向量与 IRQ 入口

启动时在 start.S 中放置向量表(VBAR 指向的区域):

_start:ldr pc, = _start_handlerldr pc, = _undefined_handlerldr pc, = _supervisor_handlerldr pc, = _prefetch_handlerldr pc, = _data_abort_handlerldr pc, = _not_use_handlerldr pc, = _irq_handlerldr pc, = _fiq_handler

4.IRQ 进入时的汇编执行流程

_irq_handler:sub lr, lr, #4              @ ARM 模式下返回地址校正stmfd sp!, {r0-r12, lr}     @ 保存通用寄存器 + lrmrc p15, 4, r1, c15, c0, 0  @ 读取 CBAR (GIC Distributor 基址)add r1, r1, #0x2000         @ CPU Interface 基地址 = CBAR + 0x2000ldr r0, [r1, #0x0C]         @ 读取 IAR,取得中断 IDstmfd sp!, {r0, r1}         @ 保护中断号与 CPU IF 基址cps #0x1F                   @ 进入 System 模式以调用 C 函数stmfd sp!, {lr}bl system_interrupt_handler @ 传递中断号(ABI:r0 里是 irq)ldmfd sp!, {lr}cps #0x12                   @ 回到 IRQ 模式ldmfd sp!, {r0, r1}         @ 恢复中断号与 CPU IF 基址str r0, [r1, #0x10]         @ 写 EOIR:告知 GIC 中断处理完毕ldmfd sp!, {r0-r12, pc}^    @ 恢复现场 + 异常返回( ^ 恢复 CPSR )

关键点:

  • mrc p15,4,... 获取 GIC 基址(CBAR)
  • IAR 读取时自动“应答”中断
  • EOIR 写入后才真正释放该中断
  • 通过模式切换 cps #0x1F 进入 System 模式调用 C 函数,避免在 IRQ 模式下栈/环境受限

5.根据中断ID调用相应的用户注册的处理函数

void system_interrupt_handler(IRQn_Type irq){if (interrupt_Vector_table[irq] != NULL) {interrupt_Vector_table[irq]();   // 调用已注册的设备具体处理函数}
}

6.代码与流程串联速览

main():system_interrupt_init()key_init()while(1){ ... }key_init():配复用 & 上拉 & 输入配触发方式(ICR2)解除屏蔽(IMR)注册函数(system_interrupt_register)使能GICIRQ发生 -> _irq_handler():保存现场读取CBAR -> +0x2000 -> 读IAR得到irq进入System模式 -> 调用 system_interrupt_handler(irq)-> 调用 key_16_31_handler()-> led_nor()-> 清 GPIO1->ISR 位返回IRQ模式写EOIR恢复现场 + 异常返回

AR -> +0x2000 -> 读IAR得到irq
进入System模式 -> 调用 system_interrupt_handler(irq)
-> 调用 key_16_31_handler()
-> led_nor()
-> 清 GPIO1->ISR 位
返回IRQ模式
写EOIR
恢复现场 + 异常返回


---

文章转载自:

http://6DPlb5mo.cbndj.cn
http://iO6u5vU9.cbndj.cn
http://zAqrmEwB.cbndj.cn
http://9YPOXG2L.cbndj.cn
http://AfPDQKJe.cbndj.cn
http://jEmk1CGt.cbndj.cn
http://N7mACnFz.cbndj.cn
http://xMmbXFV8.cbndj.cn
http://Z9xoEdg6.cbndj.cn
http://57iG9EfI.cbndj.cn
http://k6CPD56U.cbndj.cn
http://BozOPE0V.cbndj.cn
http://K5fTlPNA.cbndj.cn
http://4zfCeYLf.cbndj.cn
http://byZxtaJv.cbndj.cn
http://PpgDeLKv.cbndj.cn
http://vt1xgmne.cbndj.cn
http://6MJO9ZMQ.cbndj.cn
http://suQ5p7Cn.cbndj.cn
http://Jp8Rp2eW.cbndj.cn
http://b86Z3529.cbndj.cn
http://BfkhPB60.cbndj.cn
http://u5TmiMpO.cbndj.cn
http://5A0CTuLa.cbndj.cn
http://aDNGIDky.cbndj.cn
http://jUJxTCzA.cbndj.cn
http://yGtmTO61.cbndj.cn
http://5bbLnXqX.cbndj.cn
http://nvbxDiZU.cbndj.cn
http://XVhlNhVb.cbndj.cn
http://www.dtcms.com/a/381912.html

相关文章:

  • [code-review] 日志机制 | `LOG_LEVEL`
  • 物联网-无人自助茶室-如何实现24H智能营业?
  • JVM基础篇以及JVM内存泄漏诊断与分析
  • 【WRF数据准备】批量下载ERA5再分析数据-气象驱动数据
  • 如何实现文件批量重命名自动化
  • 【Unity 性能优化之路——概述(0)】
  • 零基础学AI大模型之SpringAI
  • AI行业应用:金融、医疗、教育、制造业的落地案例
  • 一文详解 Python 密码哈希库 Passlib
  • 360浏览器录屏功能、360浏览器录屏使用、免费录屏工具、Windows内置工具、开发者效率工具
  • 老梁聊全栈系列:现代全栈的「角色边界」与「能力雷达图」
  • ES——(三)DSL高级查询
  • 深度神经网络1——梯度问题+标签数不够问题
  • 【Unity UGUI 自动布局组(12)】
  • RAG 从入门到放弃?丐版 demo 实战笔记(go+python)
  • goland 断点调试显示“变量不可用”
  • Qt/C++,windows多进程demo
  • 再谈golang的sql链接dsn
  • pre-commit run --all-files 报错:http.client.RemoteDisconnected
  • STM32N6AI资料汇总
  • 【MySQL】E-R图
  • QT元对象系统(未完)
  • Netty 针对 Java NIO Selector 优化:SelectedSelectionKeySet
  • 抑制信号突变(模拟量采集+斜坡函数)
  • C语言入门指南:字符函数和字符串函数
  • JVM从入门到实战:从字节码组成、类生命周期到双亲委派及打破双亲委派机制
  • SQL-用户管理与操作权限
  • Airtable与Python:轻量级ETL数据管道实战
  • JavaScript 对象:一份全面的回顾
  • 逐时nc数据批量处理为日平均