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

linux驱动学习3-外部中断

在做中断试验时,发现中断驱动总是insmod失败,之后定位到 gpio_request 失败,之后是想到使用的野火做好的系统,在uEnv.txt中会加载大量设备树插件,将key相关的设备树插件屏蔽即可。

linux中断API函数

中断号

每个中断都有一个中断号,通过中断号即可区分不同的中断,在 Linux 内核中使用一个 int 变量表示中断号

request_irq函数

在 Linux 内核中要想使用某个中断是需要申请的, request_irq 函数用于申请中断, request_irq函数可能会导致睡眠,因此不能在中断上下文或者其他禁止睡眠的代码段中使用 request_irq 函数。 request_irq 函数会激活(使能)中断,所以不需要我们手动去使能中断, request_irq 函数原型如下:

int request_irq(unsigned int irq,irq_handler_t handler,unsigned long flags,const char *name,void *dev)

irq:要申请中断的中断号。
handler:中断处理函数,当中断发生以后就会执行此中断处理函数。
flags:中断标志,可以在文件 include/linux/interrupt.h 里面查看所有的中断标志,这些标志可以通过“|”来实现多种组合。
在这里插入图片描述
name:中断名字,设置以后可以在/proc/interrupts 文件中看到对应的中断名字。
dev: 如果将 flags 设置为 IRQF_SHARED 的话, dev 用来区分不同的中断,一般情况下将dev 设置为设备结构体, dev 会传递给中断处理函数 irq_handler_t 的第二个参数。

free_irq函数

使用中断的时候需要通过 request_irq 函数申请,使用完成以后就要通过 free_irq 函数释放掉相应的中断。

void free_irq(unsigned int irq,void *dev)

irq: 要释放的中断。
dev:如果中断设置为共享(IRQF_SHARED)的话,此参数用来区分具体的中断。共享中断只有在释放最后中断处理函数的时候才会被禁止掉。

中断处理函数

使用 request_irq 函数申请中断的时候需要设置中断处理函数,中断处理函数格式如下所示:

irqreturn_t (*irq_handler_t) (int, void *)

第一个参数是要中断处理函数要相应的中断号。第二个参数是一个指向 void 的指针,也就是个通用指针,需要与 request_irq 函数的 dev 参数保持一致。用于区分共享中断的不同设备,dev 也可以指向设备数据结构。中断处理函数的返回值为 irqreturn_t 类型, irqreturn_t 类型定义
如下所示:

 enum irqreturn {IRQ_NONE = (0 << 0),IRQ_HANDLED = (1 << 0),IRQ_WAKE_THREAD = (1 << 1),};typedef enum irqreturn irqreturn_t;

可以看出 irqreturn_t 是个枚举类型,一共有三种返回值。一般中断服务函数返回值使用如下形式:

return IRQ_RETVAL(IRQ_HANDLED)

中断使能和禁止函数

void enable_irq(unsigned int irq)
void disable_irq(unsigned int irq)

disable_irq函数要等到当前正在执行的中断处理函数执行完才返回,因此使用者需要保证不会产生新的中断,并且确保所有已经开始执行的中断处理程序已经全部退出。在这种情况下,可以使用另外一个中断禁止函数:

void disable_irq_nosync(unsigned int irq)

关闭全局中断可以使用如下函数:

local_irq_save(flags)   //禁止中断
local_irq_restore(flags)  //恢复中断

上半部与下半部

上半部:上半部就是中断处理函数,那些处理过程比较快,不会占用很长时间的处理就可以放在上半部完成
下半部:如果中断处理过程比较耗时,那么就将这些比较耗时的代码提出来,交给下半部去执行,这样中断处理函数就会快进快出。

tasklet

tasklet 是利用软中断来实现的另外一种下半部机制,在软中断和 tasklet 之间,建议大家使用 tasklet。 Linux 内核使用 tasklet_struct 结构体来表示 tasklet:

struct tasklet_struct
{
struct tasklet_struct *next; /* 下一个 tasklet */
unsigned long state; /* tasklet 状态 */
atomic_t count; /* 计数器,记录对 tasklet 的引用数 */
void (*func)(unsigned long); /* tasklet 执行的函数 */
unsigned long data; /* 函数 func 的参数 */
};
void tasklet_init(struct tasklet_struct *t,void (*func)(unsigned long),unsigned long data);

t:要初始化的 tasklet
func: tasklet 的处理函数。
data: 要传递给 func 函数的参数
也 可 以 使 用 宏 DECLARE_TASKLET 来 一 次 性 完 成 tasklet 的 定 义 和 初 始 化 ,DECLARE_TASKLET 定义在 include/linux/interrupt.h 文件中,定义如下:

DECLARE_TASKLET(name, func, data)

其中 name 为要定义的 tasklet 名字,这个名字就是一个 tasklet_struct 类型的时候变量, func就是 tasklet 的处理函数, data 是传递给 func 函数的参数。
在上半部,也就是中断处理函数中调用 tasklet_schedule 函数就能使 tasklet 在合适的时间运行, tasklet_schedule 函数原型如下:

void tasklet_schedule(struct tasklet_struct *t)

t:要调度的 tasklet,也就是 DECLARE_TASKLET 宏里面的 name。
关于 tasklet 的参考使用示例如下所示:

/* 定义 taselet */
struct tasklet_struct testtasklet;
/* tasklet 处理函数 */
void testtasklet_func(unsigned long data)
{
/* tasklet 具体处理内容 */
}
/* 中断处理函数 */
irqreturn_t test_handler(int irq, void *dev_id)
{
......
/* 调度 tasklet */
tasklet_schedule(&testtasklet);
......
}
/* 驱动入口函数 */
static int __init xxxx_init(void)
{
......
/* 初始化 tasklet */
tasklet_init(&testtasklet, testtasklet_func, data);
/* 注册中断处理函数 */
request_irq(xxx_irq, test_handler, 0, "xxx", &xxx_dev);
......
}

工作队列

工作队列是另外一种下半部执行方式,工作队列在进程上下文执行,工作队列将要推后的工作交给一个内核线程去执行,因为工作队列工作在进程上下文,因此工作队列允许睡眠或重新调度。因此如果你要推后的工作可以睡眠那么就可以选择工作队列,否则的话就只能选择软中断或 tasklet。
Linux 内核使用 work_struct 结构体表示一个工作,内容如下(省略掉条件编译):

struct work_struct {
atomic_long_t data;
struct list_head entry;
work_func_t func; /* 工作队列处理函数 */
};

简单创建工作很简单,直接定义一个 work_struct 结构体
变量即可,然后使用 INIT_WORK 宏来初始化工作, INIT_WORK 宏定义如下:

#define INIT_WORK(_work, _func)

_work 表示要初始化的工作, _func 是工作对应的处理函数。
也可以使用 DECLARE_WORK 宏一次性完成工作的创建和初始化,宏定义如下:

#define DECLARE_WORK(n, f)

n 表示定义的工作(work_struct), f 表示工作对应的处理函数。
和 tasklet 一样,工作也是需要调度才能运行的,工作的调度函数为 schedule_work,函数原型如下所示:

bool schedule_work(struct work_struct *work)

函数参数和返回值含义如下:
work: 要调度的工作。
返回值: 0 成功,其他值 失败。

/* 定义工作(work) */
struct work_struct testwork;
/* work 处理函数 */
void testwork_func_t(struct work_struct *work);
{
/* work 具体处理内容 */
}
/* 中断处理函数 */
irqreturn_t test_handler(int irq, void *dev_id)
{
......
/* 调度 work */
schedule_work(&testwork);
......
}
/* 驱动入口函数 */
static int __init xxxx_init(void)
{
......
/* 初始化 work */
INIT_WORK(&testwork, testwork_func_t);
/* 注册中断处理函数 */
request_irq(xxx_irq, test_handler, 0, "xxx", &xxx_dev);
......
}

设备树修改

设备树修改如下:

key{#address-cells = <1>;#size-cells = <1>;compatible = "fire,key";pinctrl-names = "default";pinctrl-0 = <&pinctrl_key>;key_gpio = <&gpio5 1 GPIO_ACTIVE_LOW>;interrupt-parent = <&gpio5>;interrupts = <1 IRQ_TYPE_EDGE_FALLING>;  //1表示使用gpio5_io01status = "okay";};

IRQ_TYPE_EDGE_FALLING 定义在文件 include/linux/irq.h 中,定义如下:

enum {
IRQ_TYPE_NONE = 0x00000000,
IRQ_TYPE_EDGE_RISING = 0x00000001,
IRQ_TYPE_EDGE_FALLING = 0x00000002,
IRQ_TYPE_EDGE_BOTH = (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING),
IRQ_TYPE_LEVEL_HIGH = 0x00000004,
IRQ_TYPE_LEVEL_LOW = 0x00000008,
IRQ_TYPE_LEVEL_MASK = (IRQ_TYPE_LEVEL_LOW |
IRQ_TYPE_LEVEL_HIGH),
......
}

获取中断号

编写驱动的时候需要用到中断号,我们用到中断号,中断信息已经写到了设备树里面,因此可以通过 irq_of_parse_and_map 函数从 interupts 属性中提取到对应的设备号,函数原型如下:
unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
函数参数和返回值含义如下:
dev: 设备节点。
index:索引号, interrupts 属性可能包含多条中断信息,通过 index 指定要获取的信息。
返回值:中断号。
如果使用 GPIO 的话,可以使用 gpio_to_irq 函数来获取 gpio 对应的中断号,函数原型如
下:

int gpio_to_irq(unsigned int gpio)

函数参数和返回值含义如下:
gpio: 要获取的 GPIO 编号。
返回值: GPIO 对应的中断号。

相关文章:

linux驱动学习3-外部中断

在做中断试验时&#xff0c;发现中断驱动总是insmod失败&#xff0c;之后定位到 gpio_request 失败&#xff0c;之后是想到使用的野火做好的系统&#xff0c;在uEnv.txt中会加载大量设备树插件&#xff0c;将key相关的设备树插件屏蔽即可。 linux中断API函数 中断号 每个中断…...

vue中的canvas插件

vue中canvas插件有vue-konva、vue-fabricjs、vue-canvas-effect、vue-chartjs和vue-threejs等。详细介绍&#xff1a;1、vue-konva是一个用于在Vue.js中使用Konva.js的插件&#xff0c;Konva.js是一个功能强大的HTML5 2D 渲染引擎&#xff0c;可以用于创建交互式的Canvas应用程…...

分享图片 | 快速浏览网页资源,批量保存、一键分享图片

前言 小伙伴学习吉他&#xff0c;有时需要在互联网搜索曲谱资源&#xff0c;而多数曲谱均为图片&#xff0c;并且为多页&#xff0c;在电脑上显示练习很不方便&#xff0c;需要停下来点击鼠标进行翻页&#xff0c;影响练习的连贯性。 为了解决上述问题&#xff0c;通常把图片…...

Programming abstractions in C阅读笔记:p123-p126

《Programming Abstractions In C》学习第50天&#xff0c;p123-p126&#xff0c;总结如下&#xff1a; 一、技术总结 1.notaion 这也是一个在计算机相关书籍中出现的词&#xff0c;但有时却不是那么好理解&#xff0c;因为它可以指代很多对象&#xff0c;这里做一个记录。示…...

自然语言处理从入门到应用——LangChain:链(Chains)-[通用功能:LLMChain、RouterChain和SequentialChain]

分类目录&#xff1a;《自然语言处理从入门到应用》总目录 LLMChain LLMChain是查询LLM对象最流行的方式之一。它使用提供的输入键值&#xff08;如果有的话&#xff0c;还包括内存键值&#xff09;格式化提示模板&#xff0c;将格式化的字符串传递给LLM&#xff0c;并返回LLM…...

ElasticSearch-安装部署全过程

本文已收录于专栏 《中间件合集》 目录 概念说明什么是ElasticSearch什么是Kibana什么是RESTful API 提供服务安装过程安装ElasticSearch1.下载ElasticSearch 安装包2.解压安装包3.进入解压之后的文件夹4.创建一个data文件夹用来存储数据5.进入config文件夹编辑elasticsearch.y…...

mathematica报错:Tag Plus is \ Protected

在使用化简函数Simplify的时候使用了规则的语法&#xff0c;但是规则可能没有使用等号。 例如 Simplify[(1 - c^2)/d^2, c^2 d^2 1]等号被认为是赋值符号&#xff0c;要修改为两个等号&#xff1a; Simplify[(1 - c^2)/d^2, c^2 d^2 1]这样就不会报错了。...

Python Django 模型概述与应用

今天来为大家介绍 Django 框架的模型部分&#xff0c;模型是真实数据的简单明确的描述&#xff0c;它包含了储存的数据所必要的字段和行为&#xff0c;Django 遵循 DRY Principle 。它的目标是你只需要定义数据模型&#xff0c;然后其它的杂七杂八代码你都不用关心&#xff0c;…...

Golang Gorm 更新字段 save update updates

更新和删除操作的前提条件都是要在找到数据的情况下&#xff0c;先要查询到数据才可以做操作。 更新的前提的先查询到记录&#xff0c;Save保存所有字段&#xff0c;用于单个记录的全字段更新它会保控所有字段&#xff0c;即使零值也会保存。 在更新和删除之前&#xff0c;要利…...

springBoot 配置文件引入 redis 的相关参数说明

在Spring Boot应用中使用Redis作为缓存或数据存储时&#xff0c;可以在应用的配置文件中配置相关参数。下面是常用的Redis配置参数及其说明&#xff1a; spring.redis.host: Redis服务器主机地址&#xff0c;默认为localhost。spring.redis.port: Redis服务器端口&#xff0c;…...

Docker的使用心得:简化开发与部署的利器

开发与测试的无缝衔接&#xff1a; Docker让开发与测试之间的切换变得前所未有的顺畅。我可以在本地开发环境中创建一个与生产环境一致的Docker容器&#xff0c;这样不仅可以确保开发过程中不会出现意外问题&#xff0c;还可以在测试阶段避免不必要的繁琐配置。 跨平台的可移植…...

vue3 基于element plus对el-pagination进行二次封装

vue3 基于element plus对el-pagination进行二次封装 1、前言2、在components文件夹中新建pagination.vue文件3、在组件内使用分页 1、前言 在vue3项目中&#xff0c;如果每个列表页都敲一遍分页方法&#xff0c;显然是不合理的&#xff0c;那么&#xff0c;下面我将基于elemen…...

RuntimeError: result type Float can‘t be cast to the desired output type __int64报错解决方法

小白刚开始学习YOLOv5&#xff0c;跟随老哥的步骤走了一遍目标检测--手把手教你搭建自己的YOLOv5目标检测平台 最后训练最后一步出现RuntimeError: result type Float can‘t be cast to the desired output type __int64报错 解决方法&#xff1a;找到5.0版报错的loss.py中最…...

解析Python爬虫常见异常及处理方法

作为专业爬虫程序猿长期混迹于爬虫ip解决方案中&#xff0c;我们经常会遇到各种各样的异常情况。在爬虫开发过程中&#xff0c;处理这些异常是不可或缺的一部分。本文将为大家总结常见的Python爬虫异常&#xff0c;并分享相应的处理方法&#xff0c;帮助你避免绊倒在爬虫之路上…...

详解Spring的循环依赖问题、三级缓存解决方案源码分析

0、基础&#xff1a;Bean的生命周期 在Spring中&#xff0c;由于IOC的控制反转&#xff0c;创建对象不再是简单的new出来&#xff0c;而是交给Spring去创建&#xff0c;会经历一系列Bean的生命周期才创建出相应的对象。而循环依赖问题也是由Bean的生命周期过程导致的问题&#…...

oracle分析函数学习

0、建表及插入测试数据 --CREATE TEST TABLE AND INSERT TEST DATA. create table students (id number(15,0), area varchar2(10), stu_type varchar2(2), score number(20,2));insert into students values(1, 111, g, 80 ); insert into students values(1, 111, j, 80 ); …...

代码随想录训练营day17|110.平衡二叉树 257. 二叉树的所有路径 404.左叶子之和 v...

TOC 前言 代码随想录算法训练营day17 一、Leetcode 110.平衡二叉树 1.题目 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a; 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。 示例 1&#x…...

C# Thread用法

C# 中的线程&#xff08;Thread&#xff09;是一种并发执行的机制&#xff0c;允许同时执行多个代码块&#xff0c;从而提高程序的性能和响应性。下面是关于如何使用 C# 线程的一些基本用法&#xff1a; 1. 创建线程&#xff1a; 使用 System.Threading 命名空间中的 Thread 类…...

新榜 | CityWalk本地生活商业价值洞察报告

如果说现在有人问&#xff0c;最新的网络热词是什么? “CityWalk”&#xff0c;这可能是大多数人的答案。 近段时间&#xff0c;“CityWalk”刷屏了各种社交媒体&#xff0c;给网友们带来了一场“城市漫步”之旅。 脱离群体狂欢&#xff0c;这个在社交媒体引发热议的词汇背后又…...

LVS负载均衡集群-NAT模式部署

集群 集群&#xff1a;将多台主机作为一个整体&#xff0c;然后对外提供相同的服务 集群使用场景&#xff1a;高并发的场景 集群的分类 1.负载均衡器集群 减少响应延迟&#xff0c;提高并发处理的能力 2&#xff0c;高可用集群 增强系统的稳定性可靠性&…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...

Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换

目录 关键点 技术实现1 技术实现2 摘要&#xff1a; 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式&#xff08;自动驾驶、人工驾驶、远程驾驶、主动安全&#xff09;&#xff0c;并通过实时消息推送更新车…...

什么是VR全景技术

VR全景技术&#xff0c;全称为虚拟现实全景技术&#xff0c;是通过计算机图像模拟生成三维空间中的虚拟世界&#xff0c;使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验&#xff0c;结合图文、3D、音视频等多媒体元素…...