【嵌入式Linux】i.MX6ULL GPIO 中断服务函数注册与编写

文章目录

  • 1 外部中断初始化与中断服务函数
    • 1.2 外部中断初始化函数 `exti_init`
      • 1.2.1 GPIO引脚配置
      • 1.2.2 中断使能与注册
      • 1.2.3 `GIC_EnableIRQ()`函数的分析
    • 1.3 中断服务函数 `gpio1_io20_irqhandler`
      • 1.3.1 消抖处理
      • 1.3.2 中断事件处理
      • 1.3.3 清除中断标志
  • 2 BUG处理
    • 2.1 问题描述
    • 2.2 解决过程
    • 2.3 解决方式

  • 本文章结合了正点原子的 i.mx6u嵌入式Linux开发指南和笔者的理解。
  • 前面我们进行了编写GPIO 中断管理与配置函数,下面将具体使用这些GPIO 中断管理与配置函数来进行一个具体的中断初始化,以及中断服务函数的编写

1 外部中断初始化与中断服务函数

这段代码主要用于初始化特定的GPIO端口(GPIO1_IO18)作为外部中断,并定义中断服务函数来处理中断事件。以下是每个部分的详细说明:

1.2 外部中断初始化函数 exti_init

1.2.1 GPIO引脚配置

key_config.direction = kGPIO_DigitalInput;
key_config.interruptMode = kGPIO_IntFallingEdge;
gpio_init(GPIO1, 18, &key_config);

设置GPIO1_IO18为数字输入并配置为下降沿触发中断。

1.2.2 中断使能与注册

GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn);
system_register_irqhandler(GPIO1_Combined_16_31_IRQn, gpio1_io18_irqhandler, NULL);
gpio_int_enable(GPIO1, 18);

在GIC(通用中断控制器)中使能对应的中断,并注册中断服务函数gpio1_io18_irqhandler

1.2.3 GIC_EnableIRQ()函数的分析

/*  
 * 使能指定的中断
 */
FORCEDINLINE __STATIC_INLINE void GIC_EnableIRQ(IRQn_Type IRQn)
{
  	GIC_Type *gic = (GIC_Type *)(__get_CBAR() & 0xFFFF0000UL);
  	gic->D_ISENABLER[((uint32_t)(int32_t)IRQn) >> 5] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}

这段代码定义了一个名为 GIC_EnableIRQ 的函数,用于启用指定的中断。

  • 函数首先获取 GIC 控制器基地址。

    • __get_CBAR() 函数返回 GIC 控制器基地址,并将其与 0xFFFF0000UL 进行按位与运算,得到 GIC 控制器基地址的最高 16 位。
    • Cortex-A7 Technical ReferenceManua.pdfP138
      在这里插入图片描述
      在这里插入图片描述
  • 然后,函数计算出要操作的寄存器地址。

    • ((uint32_t)(int32_t)IRQn) >> 5 将中断号右移 5 位,得到中断号所在的寄存器索引。
  • 最后,函数设置该寄存器中的相应位,从而启用该中断。

    • ((uint32_t)(int32_t)IRQn) & 0x1FUL 将中断号与 0x1FUL 进行按位与运算,得到中断号在寄存器中的位索引。
    • 然后,将 1UL 左移 位索引 位,得到一个掩码,并将其写入 D_ISENABLER 寄存器中,从而启用该中断。
  • D_ISENABLER 寄存器是 GIC 分发器中的一组寄存器,用于控制每个中断的启用状态。
    ARM Generic Interrupt Controller(ARM GIC控制器)V2.0.pdfP93
    在这里插入图片描述

    • 每个寄存器包含 32 个 Set-enable 位,分别对应于 32 个中断。
    • 当 Set-enable 位被设置为 1 时,对应中断会被启用,这意味着 GIC 会将该中断转发到 CPU。
    • 当 Set-enable 位被设置为 0 时,对应中断会被禁用,这意味着 GIC 不会将该中断转发到 CPU。

    根据中断 ID (m),对应 GICD_ISENABLER 寄存器的编号 (n) 可以通过 n = m DIV 32 计算得到,也就是IRQn) >> 5

    • 对应 GICD_ISENABLER 寄存器的偏移地址为 0x100 + (4*n),这里不用手动计算,通过gic->D_ISENABLER·就可以得到。
    • 对应 GICD_ISENABLER 寄存器中需要设置的位的编号为 m MOD 32,也就是IRQn & 0x1FUL

1.3 中断服务函数 gpio1_io20_irqhandler

1.3.1 消抖处理

delay(10);

简单的延时用于消除由于机械或电气噪声产生的误触发。

1.3.2 中断事件处理

if(gpio_pin_read(GPIO1, 18) == 0){
    state = !state;
    beep_switch(state);
}

读取GPIO1_IO18的状态,如果为低电平(按键被按下),则切换状态并控制蜂鸣器的开关状态。

1.3.3 清除中断标志

gpio_int_flagClear(GPIO1, 18);

完成事件处理后,清除中断标志以准备接收下一个中断。

2 BUG处理

2.1 问题描述

程序烧写后,发现当尝试按下按键,进入按键中断处理函数时,灯会一直保持在按键按下那一刻的状态,程序卡死。

2.2 解决过程

  • 查看反汇编文件,发现bss段放在了程序起始地址,导致中断向量表的位置不对了(之前说过,应该放在程序的起始位置)

BSS 段(Block Started by Symbol)是程序内存中用于存储未初始化全局变量和静态变量的区域。

在这里插入图片描述

2.3 解决方式

_start:中,将bss段初始化放到中断向量表初始化后面

_start:
    @ 在处理器启动时执行一次,用于初始化中断向量表
    ldr pc, =Reset_Handler     @ 复位中断服务函数
    ldr pc, =Undefined_Handler @ 未定义指令中断服务函数
    ldr pc, =SVC_Handler       @ SVC中断服务函数
    ldr pc, =PreAbort_Handler  @ 预取终止
    ldr pc, =DataAbort_Handler @ 数据终止
    ldr pc, =NotUsed_Handler   @ 未使用
    ldr pc, =IRQ_Handler       @ IRQ中断服务函数
    ldr pc, =FIQ_Handler       @ FIQ中断服务函数

@ 复位中断服务函数
Reset_Handler:
    @ 0.禁止IRQ中断
    @ 方式:修改PSTATE处理器状态寄存器
    @ Change PE State (CPS) 用于修改处理器状态寄存器 (PSTATE) 中的某些位
    @ PSTATE 是一个特殊的寄存器,它包含了处理器当前的运行状态信息,包括:
    @ A (Application) 位: 控制应用程序模式下的中断是否允许。
    @ I (IRQ) 位: 控制 IRQ 中断是否允许。
    @ F (FIQ) 位: 控制 FIQ 中断是否允许。
    @ M (Mode) 位: 控制处理器当前运行的模式。
    cpsid i

    @ 1.关闭I/D Cache, MMU
    @ 方式:修改SCTLR寄存器
    @ (System Control Register,可以通过 CP15 协处理器访问)
    @ SCTLR寄存器:
        @ bit0:MMU 
        @ bit1:对齐控制 
        @ bit2:D Cache 
        @ bit11:分支预测控制 
        @ bit12:I Cache
    MRC p15, 0, r0, c1, c0, 0   @ Move to Register from Coprocessor(这个形式操作的是SCTLR寄存器)
    bic r0, r0, #(1<<12)        @ 关闭I Cache(bic:Bit Clear)
    bic r0, r0, #(1<<11)        @ 关闭分支预测
    bic r0, r0, #(1<<2)         @ 关闭D Cache
    bic r0, r0, #(1<<1)         @ 关闭对齐控制
    bic r0, r0, #(1<<0)         @ 关闭MMU
    MCR p15, 0, r0, c1, c0, 0   @ Move to Coprocessor from Register

#if 0
    @ 2.设置中断向量偏移
    @ 方式:修改VBAR寄存器
    @ (Vector Base Address Register,可以通过 CP15 协处理器访问)
    ldr r0, =0x87800000
    dsb
    isb
    MCR p15, 0, r0, c12, c0, 0  @ 设置VBAR寄存器为0x87800000
    dsb
    isb
#endif

.global _bss_start             @ 声明_bss_start符号为全局可见
_bss_start:                    @ 定义_bss_start标签
    .word _bss_start           @ 将_bss_start标签的地址存储为一个字(4字节)

.global _bss_end               @ 声明_bss_end符号为全局可见
_bss_end:                      @ 定义_bss_end标签
    .word _bss_end             @ 将_bss_end标签的地址存储为一个字(4字节)
    @ 3.清除bss段
    @ 方式:使用循环逐个清除
    ldr r0, _bss_start         @ 将_bss_start地址加载到r0寄存器
    ldr r1, _bss_end           @ 将_bss_end地址加载到r1寄存器
    mov r2, #0                 @ 将0存储到r2寄存器
bss_loop:
    stmia r0!, {r2}            @ 存储r2寄存器的值到r0指向的内存地址,并自增r0
    cmp r0, r1                 @ 比较r0和r1的值
    ble bss_loop               @ 如果r0小于等于r1,则跳转到bss_loop标签(继续循环)

    @ 4.设置处理器进入IRQ模式
    @ 方式:修改cpsr寄存器
    @ (Current Program Status Register,当前程序状态寄存器)
    @ 它包含了处理器状态和控制信息,例如 APSR、指令集状态、IT 块状态、字节序和当前处理器模式。 
    mrs r0, cpsr               @ 读取CPSR寄存器的值到r0寄存器
    bic r0, r0, #0x1f          @ 通过位清除操作,清除r0寄存器的低5位
    orr r0, r0, #0x12          @ 使用IRQ模式
    msr cpsr, r0               @ 将r0寄存器的值写回CPSR寄存器
    ldr sp, =0x80600000        @ 设置IRQ下的sp指针

    @ 5.设置处理器进入SYS模式
    @ 方式:修改cpsr寄存器
    @ (Current Program Status Register,当前程序状态寄存器)
    @ 它包含了处理器状态和控制信息,例如 APSR、指令集状态、IT 块状态、字节序和当前处理器模式。 
    mrs r0, cpsr               @ 读取CPSR寄存器的值到r0寄存器
    bic r0, r0, #0x1f          @ 通过位清除操作,清除r0寄存器的低5位
    orr r0, r0, #0x1f          @ 使用SYS模式
    msr cpsr, r0               @ 将r0寄存器的值写回CPSR寄存器
    ldr sp, =0x80400000        @ 设置SYS下的sp指针

    @ 6.设置处理器进入SVC模式
    @ 方式:修改cpsr寄存器
    @ (Current Program Status Register,当前程序状态寄存器)
    @ 它包含了处理器状态和控制信息,例如 APSR、指令集状态、IT 块状态、字节序和当前处理器模式。 
    mrs r0, cpsr               @ 读取CPSR寄存器的值到r0寄存器
    bic r0, r0, #0x1f          @ 通过位清除操作,清除r0寄存器的低5位
    orr r0, r0, #0x13          @ 使用SVC模式
    msr cpsr, r0               @ 将r0寄存器的值写回CPSR寄存器
    ldr sp, =0x80200000        @ 设置SVC下的sp指针

    @ 7.使能IRQ中断
    @ 方式:修改PSTATE处理器状态寄存器
    @ Change PE State (CPS) 用于修改处理器状态寄存器 (PSTATE) 中的某些位
    @ PSTATE 是一个特殊的寄存器,它包含了处理器当前的运行状态信息,包括:
    @ A (Application) 位: 控制应用程序模式下的中断是否允许。
    @ I (IRQ) 位: 控制 IRQ 中断是否允许。
    @ F (FIQ) 位: 控制 FIQ 中断是否允许。
    @ M (Mode) 位: 控制处理器当前运行的模式。
    cpsie i

    @ 8.跳转到main函数的入口
    b main                     @ 跳转到main函数的入口

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/746550.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

打破数据分析壁垒:SPSS复习必备(九)

有序定性资料统计推断 1.分类 单向有序行列表 双向有序属性相同行列表 双向有序属性不同行列表 2.单向有序行列表 秩和检验 ① 两组单向有序分类资料 ②多组单向有序定性资料 步骤&#xff1a; 1.建立检验假设和确定检验水准 2.编秩 3.求秩和 4.确定检验统计量 5…

Sora:探索AI视频模型的无限可能

随着人工智能技术的飞速发展&#xff0c;AI在视频处理和生成领域的应用正变得越来越广泛。Sora&#xff0c;作为新一代AI视频模型&#xff0c;展示了前所未有的潜力和创新能力。本文将深入探讨Sora的功能、应用场景以及它所带来的革命性变化。 一、Sora的核心功能 1.1 视频生…

一年Java|16K|同程艺龙面经

面经哥只做互联网社招面试经历分享&#xff0c;关注我&#xff0c;每日推送精选面经&#xff0c;面试前&#xff0c;先找面经哥 背景 公司&#xff1a;同程艺龙成都BU,现场部门老大面 之前的同程艺龙电话一面过了&#xff0c;然后通知到同程艺龙成都办公地点现场进行部门老大…

宠物空气净化器热卖爆款,希喂、小米、352猫用空气净化器真实PK

相信大漫天多数养猫家庭都会有一个烦恼&#xff1a;猫咪们的猫实在是太多了&#xff0c;无法忍受家里面漫天飞舞的浮毛和难闻的猫猫便臭。作为养猫多年的过来人我尝试过很多种方法清理这些猫浮毛和异味&#xff0c;但都以失败告终。 直到后面看到一个宠物博主推荐的宠物空气净…

【干货】【全网最全】【全网最详细】 javaWeb关于Thymeleaf+SpringBoot 的学习教程,看这一篇就够了。

大家好&#xff0c;我是DX3906 第一部分&#xff1a;介绍 Thymeleaf 简介 1.什么是Thymeleaf Thymeleaf是一个用于Java和Java EE平台的服务器端模板引擎&#xff0c;它可以用来在服务端生成HTML、XML、JavaScript、CSS甚至纯文本的输出。Thymeleaf适用于需要快速开发和维护Web…

React+TS前台项目实战(十六)-- 全局常用组件Pagination封装

文章目录 前言Pagination组件1. 功能分析2. 代码详细注释3. 使用方式4. 效果展示 [PC端&手机端] 总结 前言 在上篇文章中&#xff0c;我们封装了表格组件Table&#xff0c;本文则继续封装配套使用的分页器组件。想看Table表格组件的&#xff0c;可自行查看全局常用组件Tab…

【渗透测试】小程序反编译

前言 在渗透测试时&#xff0c;除了常规的Web渗透&#xff0c;小程序也是我们需要重点关注的地方&#xff0c;微信小程序反编译后&#xff0c;可以借助微信小程序开发者工具进行调试&#xff0c;搜索敏感关键字&#xff0c;或许能够发现泄露的AccessKey等敏感信息及数据 工具…

工业液晶屏G065VN01 V2规格书简介

G065VN01 V2 背面实物图 2. 概述 G065VN01 V2 专为 VGA &#xff08;640 x RGB x 480&#xff09; 分辨率和 16.2M&#xff08;RGB 6 位 FRC&#xff09;或 262k 色&#xff08;RGB 6 位&#xff09;的工业显示应用而设计。它由TFT-LCD面板、驱动IC、控制和电源电路板以及包括…

按位与、或、异或操作符

目录 & --- 按位与操作符 按位与操作符运用规则 按位与操作符相关代码 按位与操作符相关代码验证 | --- 按位或操作符 按位或操作符运用规则 按位或操作符相关代码 按位或操作符相关代码验证 ^ --- 按位异或操作符 按位异或操作符运用规则 按位异或操作符相关代…

[AI开发配环境]VSCode远程连接ssh服务器

文章目录 总览&#xff1a;ssh连接远程服务器连接免密登录&#xff1a;Docker&#xff1a;ssh连接远程宿主机后&#xff0c;进一步连接并使用其中的docker容器reload window 配置解释器&#xff1a;CtrlP&#xff0c;在上面输入“>python”, 然后选selecet interpreter运行命…

ubuntu如何切换到root用户

1、主要指令&#xff1a; sudo -i su root 2、示例 3、其他说明 在Ubuntu&#xff08;以及大多数其他基于Linux的操作系统中&#xff09;&#xff0c;切换到root用户通常意味着获得了对系统的完全访问权限。这种权限允许执行以下操作&#xff08;但不限于这些&#xff09;…

【C语言】解决C语言报错:Double Free

文章目录 简介什么是Double FreeDouble Free的常见原因如何检测和调试Double Free解决Double Free的最佳实践详细实例解析示例1&#xff1a;重复调用free函数示例2&#xff1a;多次释放全局变量指针示例3&#xff1a;函数间传递和释放指针 进一步阅读和参考资料总结 简介 Doub…

【ajax实战03】拦截器

一&#xff1a;axios拦截器 拦截器分类&#xff1a; 请求拦截器以及响应拦截器 拦截器作用&#xff1a; 在请求或响应被then或catch处理前拦截它们 二&#xff1a;请求拦截器 作用&#xff1a; 发起请求之前&#xff0c;调用一个配置函数&#xff0c;对请求参数进行设置…

MyBatis案例

目录 一、配置文件1.数据与环境准备1.1 创建tb_brand表1.2 在Pojo中创建实体类Brand.java1.3 在test文件夹下的java中创建测试类1.4 安装MyBatisX插件 二、增删改查1. 查询 一、配置文件 1.数据与环境准备 1.1 创建tb_brand表 -- 删除tb_brand表 drop table if exists tb_bra…

什么是大模型?一文读懂大模型的基本概念

大模型是指具有大规模参数和复杂计算结构的机器学习模型。本文从大模型的基本概念出发&#xff0c;对大模型领域容易混淆的相关概念进行区分&#xff0c;并就大模型的发展历程、特点和分类、泛化与微调进行了详细解读&#xff0c;供大家在了解大模型基本知识的过程中起到一定参…

【Qt】初识QtQt Creator

一.简述Qt 1.什么是Qt Qt 是⼀个 跨平台的 C 图形⽤⼾界⾯应⽤程序框架 。它为应⽤程序开发者提供了建⽴艺术级图形界⾯所需的所有功能。它是完全⾯向对象的&#xff0c;很容易扩展。Qt 为开发者提供了⼀种基于组件的开发模式&#xff0c;开发者可以通过简单的拖拽和组合来实现…

Energy-based PINN在固体力学中的运用

简介 物理信息神经网络&#xff08;Physic informed neural network&#xff0c;PINN&#xff09;已经成为在有限差分、有限体积和有限元之后的另一种求解偏微分方程组的范式&#xff0c;受到学者们广泛关注。 在固体力学领域有两类不同的PINN: &#xff08;1&#xff09;PDE…

mac卡牌游戏:堆叠大陆 Stacklands for Mac 中文安装包

Stacklands 是一款轻松益智的堆叠游戏。玩家需要在游戏中不断堆叠不同形状和大小的方块&#xff0c;使它们尽可能地稳定地堆放在一起。游戏中有多种不同的关卡和挑战&#xff0c;玩家需要通过合理的堆叠方式来完成每个关卡。游戏画面简洁明快&#xff0c;操作简单直观&#xff…

跟我从零开始学C++(C++代码基础)5

引言 小伙伴们&#xff0c;在经过一些基础定义和指针&#xff0c;数组&#xff0c;函数的洗礼后&#xff0c;我相信大家肯定都已经对C编程有了新的认知&#xff0c;同时呢&#xff0c;坚持下来的小伙伴们肯定都是好样的&#xff0c;大家都是很棒的&#xff0c;现在我们来学一学…

开源模型应用落地-FastAPI-助力模型交互-WebSocket篇(二)

一、前言 使用 FastAPI 可以帮助我们更简单高效地部署 AI 交互业务。FastAPI 提供了快速构建 API 的能力,开发者可以轻松地定义模型需要的输入和输出格式,并编写好相应的业务逻辑。 FastAPI 的异步高性能架构,可以有效支持大量并发的预测请求,为用户提供流畅的交互体验。此外,F…