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

硬件(九)寄存器、外设与中断机制

一、结构体访问寄存器的本质

通过指针 + 偏移量实现,结构体在此扮演关键角色:

  • 偏移量载体:把寄存器相对基地址的偏移值(如048),映射为易记的成员名(如DRGDIRPSR)。
  • 起始地址锚点:将指针强制转为结构体类型后,编译器会以该指针为 “起始地址”,按结构体成员的偏移量去访问对应物理地址。
  • 最终效果:无需手动计算并书写0x209C004这类物理地址,由编译器自动完成 “基地址 + 偏移量” 的地址计算与访问。

示例,能更直观理解对 GPIO 的初始化操作:

enum GPIO_Dirction
{gpio_output,gpio_input
};struct GPIO_Type_t
{enum GPIO_Dirction direction;int default_value;
};void init_gpio(GPIO_Type *base, int pin, struct GPIO_Type_t *gpio)
{if(gpio->direction == gpio_output){base->GDIR |= (1 << pin);if(gpio->default_value){base->DR |= (1 << pin);}else{base->DR &= ~(1 << pin);} }else{base->GDIR &= ~(1 << pin);}
}void init_beep(void)
{IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01, 0);IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01, 0x10B0);struct GPIO_Type_t t = {.direction = gpio_output,.default_value = 1};init_gpio(GPIO5, 1, &t);
}

二、i.MX6ULL 按键功能实现

(一)硬件原理与引脚对应

按键电路中,按键KEY0一端经电阻R12DCDC_3V3电源(上拉),另一端接地。当按键按下时,引脚电平拉低;松开时,由上拉电阻维持高电平。
从芯片引脚定义可知,按键对应引脚复用为UART1_CTS功能(实际作为 GPIO 输入使用)。

(二)软件配置流程

  1. IO 复用与电气属性设置
    调用IOMUXC_SetPinMux设置引脚复用模式,IOMUXC_SetPinConfig配置电气属性(如上下拉、驱动能力等)。示例代码中,将IOMUXC_UART1_CTS_B_GPIO1_IO18引脚配置为 GPIO 功能并设置合适电气参数:
    IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);
    IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0xF080);
    
  2. GPIO 方向与默认值设置
    因为按键是输入设备,所以通过init_gpio函数将对应 GPIO(GPIO118号引脚)配置为输入模式,且默认值设为1(高电平,对应按键未按下状态):

    struct GPIO_Type_t t = 
    {.direction = gpio_input,.default_value = 1
    };
    init_gpio(GPIO1, 18, &t);
    
  3. 中断触发方式与使能
    • 配置中断触发方式为下降沿触发(通过GPIO1->ICR2寄存器)。
    • 使能对应 GPIO 引脚的中断(通过GPIO1->IMR寄存器)。
    • 使能 GIC 中对应中断(GPIO1_Combined_16_31_IRQn),让内核能响应该中断:
    GPIO1->ICR2 |= (3 << 4);
    GPIO1->IMR |= (1 << 18);
    GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn);
    

三、中断相关知识

(一)中断的概念

中断是一种硬件机制,当外设(如按键、定时器等)或内核内部发生特定事件时,会主动向 CPU 发送请求,使 CPU 暂停当前任务,转而去处理该事件(执行中断服务程序),处理完毕后再回到原任务继续执行。

(二)GIC 控制器

  • 作用:GIC(Generic Interrupt Controller,通用中断控制器)是 ARM 公司设计的外设,负责管理各类中断,接收外部中断后进行处理,最终向 ARM 内核上报(如IRQ信号)。
  • 多内核支持:GIC V2.0 设计可支持 8 个内核,但 i.MX6ULL 仅单内核,仍可通过相关函数(如GIC_Init)统一管理中断。
  • 中断分类
    • SGI(Software Generated Interrupt,软件生成中断):中断 ID 0 - 15,由软件触发。
    • PPI(Private Peripheral Interrupt,私有外设中断):中断 ID 16 - 31,特定于单个 CPU。
    • SPI(Shared Peripheral Interrupt,共享外设中断):中断 ID 32 - 1019,所有 CPU 可共享的外设中断,按键等外部中断多属于此类。
  • 关键寄存器
    • C_IAR(Interrupt Acknowledge Register):中断确认寄存器,用于获取当前待处理中断的 ID。
    • C_EOIR(End Of Interrupt Register):中断结束寄存器,用于告知 GIC 中断处理完毕。

(三)协处理器(Coproc)

ARM 内核有cp0 - cp15等协处理器,cp15常用,负责管理系统级功能(如内存管理、中断控制等)。GIC 的基地址等关键信息由cp15管理,需通过专门指令(MRCMCR)访问cp15寄存器。

  • MRC指令:从协处理器寄存器读取数据到 ARM 通用寄存器。格式为MRC p15, 0, <Rd>, <Crn>, <Crm>, {<opc>},例如读取cp15c1寄存器到r0mrc p15, 0, r0, c1, c0, 0
  • MCR指令:将 ARM 通用寄存器的数据写入协处理器寄存器。格式为MCR p15, 0, <Rd>, <Crn>, <Crm>, {<opc>},例如将r0数据写入cp15c12寄存器:mcr p15, 0, r0, c12, c0, 0

(四)SCTLR 寄存器(系统控制寄存器)

  • V 位(位 13):选择异常向量表基地址。
    • V = 0:使用普通异常向量表,基地址为0x00000000,且可通过VBAR寄存器重新映射基地址(如改为我们代码中的0x87800000),方便将异常处理代码放在指定内存区域。
    • V = 1:使用高异常向量表,基地址固定为0xFFFF0000,不可重映射,不符合我们灵活配置异常向量表的需求。
  • I 位(位 12):指令缓存使能位。I = 1使能指令缓存(ICache),可加速指令读取;数据缓存(DCache)在此时不使能,避免数据一致性等复杂问题(后续按需开启)。

(五)异常向量表与地址设置

异常向量表存储各类异常(如中断、复位等)的处理入口地址。为让内核在异常发生时能跳转到我们编写的处理代码,需设置异常向量表基地址:

  • 通过_set_vbar函数,利用MCR指令将0x87800000写入cp15c12寄存器(VBAR寄存器),完成异常向量表基地址的重映射。

(六)GIC 基地址获取(CBAR 寄存器)

CBAR(Core Base Address Register)寄存器存储 GIC 的基地址。通过MRC指令mrc p15, 4, r0, c15, c0, 0,可将 GIC 基地址读取到r0寄存器,后续基于此地址访问 GIC 的各类寄存器。

(七)中断使能与处理

  • 全局中断使能:通过修改CPSR寄存器(当前程序状态寄存器),开启 IRQ 中断:

    _reset_handler:mrs r0, cpsrbic r0, r0, #0x1Forr r0, r0, #0x12  // 使能IRQ中断bic r0, r0, #(1 << 7)msr cpsr, r0
    
  • 中断服务程序框架

    _irq_handler:subs lr, lr, #4  // 修正返回地址(因ARM流水线,地址会超前4字节)stmfd sp!, {r0-r12, lr}  // 保存现场bl system_interrupt_handler  // 调用中断处理函数ldmfd sp!, {r0-r12, pc}^  // 恢复现场并返回,^表示同时恢复CPSR
    

(八)按键中断初始化完整代码

#include "key.h"
#include "MCIMX6Y2.h"
#include "fsl_iomuxc.h"
#include "gpio.h"
#include "core_ca7.h"void init_key(void)
{IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0xF080);struct GPIO_Type_t t = {.direction = gpio_input,.default_value = 1};init_gpio(GPIO1, 18, &t);GPIO1->ICR2 |= (3 << 4);  // 配置下降沿触发GPIO1->IMR |= (1 << 18);  // 使能GPIO1_18引脚中断GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn);  // 使能GIC中对应中断
}int key_pressed(void)
{return !read_gpio(GPIO1, 18);  // 读取引脚电平,判断按键是否按下
}

文章转载自:

http://kGDrZuSB.ygrdb.cn
http://oUv6X1z3.ygrdb.cn
http://qNajZoOE.ygrdb.cn
http://aLyIypWs.ygrdb.cn
http://GabGcot9.ygrdb.cn
http://LWCZhBJB.ygrdb.cn
http://cZ0z184v.ygrdb.cn
http://gP9oxBtE.ygrdb.cn
http://oeBvBxOM.ygrdb.cn
http://K4sEEYfa.ygrdb.cn
http://JAdW1vWs.ygrdb.cn
http://PQkavk7P.ygrdb.cn
http://z8i7hxGY.ygrdb.cn
http://qRMci9Ni.ygrdb.cn
http://S5sGcIsc.ygrdb.cn
http://Obj9kBt0.ygrdb.cn
http://hyAPPPMh.ygrdb.cn
http://JVCPidoR.ygrdb.cn
http://ddOtozw9.ygrdb.cn
http://9fKExd2D.ygrdb.cn
http://r93mMRtU.ygrdb.cn
http://HBcsO8g9.ygrdb.cn
http://rRJscHHs.ygrdb.cn
http://JOP2Rm4s.ygrdb.cn
http://7fzuo0WA.ygrdb.cn
http://JOwgJMNF.ygrdb.cn
http://RWx8gRrS.ygrdb.cn
http://Yw2cBB8u.ygrdb.cn
http://r8GF8ht2.ygrdb.cn
http://KiKTMj6P.ygrdb.cn
http://www.dtcms.com/a/381121.html

相关文章:

  • 《常见的设计模式——单例、代理与适配器》
  • 海龟交易策略
  • MySQL 事务
  • claude code使用小窍门
  • Recaptcha2 图像识别 API 对接说明
  • Spring中 @Value注解设置默认值
  • Linux / Windows 下连续发送多帧 8 字节指令,下位机只响应第一帧,第二帧“丢失”。
  • RStudio 教程:以抑郁量表测评数据分析为例
  • 驱动程序介绍及其安装说明
  • Day03 前缀和 | 1248. 统计「优美子数组」、53. 最大子数组和
  • 现代化心理中心场室建设与规划之道
  • 面向小白用户的多集群云原生应用管理平台设计
  • 怎么设计一个高效的任务调度器,避免任务饥饿
  • Linux运维核心知识体系总结:从安全加密到服务部署
  • 50期权日内交易技巧
  • 枚举算法和排序算法能力测试
  • 未来之窗昭和仙君 (四) 前端网页分页 — 东方仙盟筑基期
  • Class50 LSTM
  • Redis是什么?一篇讲透它的定位、特点与应用场景
  • [zlaq.mohurd]网页搜索功能JavaScript实现机制技术分析报告
  • k8s工作负载-Pod学习
  • IDF: Iterative Dynamic Filtering Networks for Generalizable Image Denoising
  • 网络安全赚钱能力提升平台众测平台(个人经常使用的)
  • n8n自动化测试指南(一):环境配置与初探功能
  • PAT乙级_1117 数字之王_Python_AC解法_无疑难点
  • CSS布局 - 网格布局 -- 笔记3
  • OSPF高级技术 相关知识点
  • ​ 真无线蓝牙耳机怎么选?舒适与实用如何兼得?
  • 4. 信息安全技术基础知识
  • 我“抄”了 sogou/workflow 的设计,用现代 C++ 写了个 HTTP 框架