【嵌入式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 CacheMRC 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 Cachebic r0, r0, #(1<<1)         @ 关闭对齐控制bic r0, r0, #(1<<0)         @ 关闭MMUMCR p15, 0, r0, c1, c0, 0   @ Move to Coprocessor from Register#if 0@ 2.设置中断向量偏移@ 方式:修改VBAR寄存器@ (Vector Base Address Register,可以通过 CP15 协处理器访问)ldr r0, =0x87800000dsbisbMCR p15, 0, r0, c12, c0, 0  @ 设置VBAR寄存器为0x87800000dsbisb
#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指向的内存地址,并自增r0cmp 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.mzph.cn/pingmian/35980.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网易Filmly网盘影片播放器安卓TV版

我们在观看网盘内的影视时&#xff0c;想要高清/原画质观看视频&#xff0c;甚至倍速功能往往都需要开通网盘会员才可以&#xff0c;否则你只能使用”马赛克”画质观看。 最近网易上线了一款播放器&#xff1a;Filmly &#xff0c;它支持直连网盘影视资源&#xff0c;可以高速…

深入理解计算机系统 CSAPP 家庭作业7.12

A:refptr (unsigned)(ADDR(r.symbol) r.addend - refaddr) 0x4004f8 (-4) - 0x4004ea 0xa B:refaddr 0x4004d0 0xa 0x4004da refptr 0x400500 (-4) - 0x4004da 0x22 ​​​​​​​

Python24 机器学习之决策树

1.什么是机器学习&#xff1f; 机器学习是人工智能&#xff08;AI&#xff09;的一个分支&#xff0c;它使计算机系统能够从经验中学习并根据这些学习的数据做出决策或预测&#xff0c;而无需进行明确的编程。简而言之&#xff0c;机器学习涉及算法和统计模型的使用&#xff0…

Hugo Barra对Apple Vision Pro 硬件和软件的详细评述

原文&#xff1a;hugo.blog/2024/03/11/vision-pro 这篇文章的作者是Hugo Barra。Hugo Barra曾是Meta公司&#xff08;前身为Facebook&#xff09;旗下Oculus VR/AR团队的负责人。他在2017年至2020年期间领导了Oculus的团队&#xff0c;参与了多个VR头显的开发和发布。Hugo Bar…

使用提示词调教AI

“AI 是我们的数字员工&#xff0c;了解员工的秉性 &#xff0c; 从调教提示词开始。” 网上流传最广的提示词方法论&#xff0c;是“你需要给大模型一个角色”。这确实是一个好的策略&#xff0c;因为小学老师&#xff0c;大学老师这样的角色&#xff0c;预设很多背景信息。这…

【数学建模】 函数极值与规划模型

文章目录 函数极值与规划模型1. 线性代数和线性规划的联系1.1 线性代数的基本概念1.2 线性规划的基本概念1.3 线性代数与线性规划的联系矩阵和向量线性方程组单纯形法内点法凸优化 1.4 例子 2. Numpy有关矩阵运算示例2.1 矩阵的创建2.2 矩阵的基本运算2.3 矩阵的合并2.4 矩阵的…

Linux系统之nice命令的基本使用

Linux系统之nice命令的基本使用 一、nice命令介绍1.1 nice命令简介1.2 进程优先级介绍 二、nice命令基本语法2.1 nice命令的help帮助信息2.2 nice命令选项解释 三、nice命令的基本使用3.1 查看进程优先级3.2 使用nice启动进程3.3 提高优先级 四、注意事项 一、nice命令介绍 1.…

如何制作自己的网站

制作自己的网站可以帮助个人或组织在互联网上展示自己的品牌、作品、产品或服务。随着技术的发展&#xff0c;现在制作网站变得越来越简单。下面是一个简单的步骤指南&#xff0c;帮助你制作自己的网站。 1. 确定你的网站需求和目标 在开始之前&#xff0c;你需要明确你的网站的…

CSS Grid网格布局

一、前言 二、Grid布局 1、基本介绍 2、核心概念 &#xff08;1&#xff09;网格容器 &#xff08;2&#xff09;网格元素 &#xff08;3&#xff09;网格列 &#xff08;4&#xff09;网格行 &#xff08;5&#xff09;网格间距 &#xff08;6&#xff09;网格线 三…

基于PHP的酒店管理系统(改进版)

有需要请加文章底部Q哦 可远程调试 基于PHP的酒店管理系统(改进版) 一 介绍 此酒店管理系统(改进版)基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端jquery插件美化。系统角色分为用户和管理员。系统在原有基础上增加了注册登录注销功能&#xff0c;增加预订房间图片…

Claude走向开放

Claude的愿景一直是创建能够与人们协同工作并显著提升他们工作流程的人工智能系统。朝着这一方向迈进&#xff0c;Claude.ai的专业版和团队版用户现在可以将他们的聊天组织到项目中&#xff0c;将精选的知识和聊天活动整合到一个地方&#xff0c;并且可以让团队成员查看他们与C…

什么是期货基金?

期货基金&#xff0c;是指广大投资者将资金集中起来&#xff0c;委托给专业的期货投资机构&#xff0c;并通过商品交易顾问进行期货投资交易&#xff0c;投资者承担投资风险并享有投资利润的一种集合投资方式。期货基金的投资对象主要有两大类商品&#xff1a;期货与金融期货。…

django学习入门系列之第三点《案例 商品推荐部分》

文章目录 划分区域搭建骨架完整代码小结往期回顾 划分区域 搭建骨架 /*商品图片&#xff0c;父级设置*/ .slider .sd-img{display: block;width: 1226px;height: 460px; }<!-- 商品推荐部分 --> <!--搭建出一个骨架--> <div class"slider"><di…

提高开发效率之——工具介绍

一 . SerialDebug 串口调试工具 SerialDebug 是一个串口调试工具&#xff0c;它主要用于帮助电子工程师和软件开发者进行串口通信的调试工作。以下是 SerialDebug 工具的一些主要作用和特点: 基础串口通信功能&#xff1a;提供打开、关闭、接收、发送数据的基础串口操作。 数…

.NET C# 使用OpenCV实现人脸识别

.NET C# 使用OpenCV实现模型训练、人脸识别 码图~~~ 1 引入依赖 OpenCvSHarp4 - 4.10.0.20240616 OpenCvSHarp4.runtime.win - 4.10.0.20240616 2 人脸数据存储结构 runtime directory | face | {id}_{name} | *.jpg id - 不可重复 name - 人名 *.jpg - 人脸照片3 Demo 3.…

前置章节-熟悉Python、Numpy、SciPy和matplotlib

目录 一、编程环境-使用jupyter notebook 1.下载homebrew包管理工具 2.安装Python环境 3.安装jupyter 4.下载Anaconda使用conda 5.使用conda设置虚拟环境 二、学习Python基础 1.快排的Python实现 (1)列表推导-一种创建列表的简洁方式 (2)列表相加 2.基本数据类型及运…

FastGPT 调用Qwen 测试Hello world

Ubuntu 安装Qwen/FastGPT_fastgpt message: core.chat.chat api is error or u-CSDN博客 参考上面文档 安装FastGPT后 登录&#xff0c; 点击右上角的 新建 点击 这里&#xff0c;配置AI使用本地 ollama跑的qwen模型 问题&#xff1a;树上有3只鸟&#xff0c;开了一枪&#…

使用CDN方式创建Vue3.0应用程序

CDN 的全称是 content delivery network&#xff0c;即内容分发网络。它是构建在现在的互联网基础之上的一层智能虚拟网络&#xff0c;依靠部署在各地的边缘服务器&#xff0c;通过中心平台的负载均衡、内容分发和调度等功能模块&#xff0c;使用户就近获取所需内容&#xff0c…

matlab量子纠缠态以及量子门操作下的量子态

前言 今天我们来聊聊题外话&#xff0c;量子纠缠&#xff0c;在目前物理分支中&#xff0c;要说最深&#xff0c;最能改变人类对宇宙影响的莫过于量子力学了&#xff0c;假如我们可以人为的对两个粒子施加纠缠态&#xff0c;那么我们将可以足不出户的完成对外界的操控 简介 …

《TopFormer: Token Pyramid Transformer for Mobile Semantic Segmentation》

期刊&#xff1a;CVPR 年份&#xff1a;2022 代码&#xff1a;https://github.com/hustvl/TopFormer 摘要 尽管视觉Transformer(ViTs)在计算机视觉领域取得了巨大的成功&#xff0c;但沉重的计算成本阻碍了它们在密集预测任务中的应用&#xff0c;如移动设备上的语义分割。…