Linux学习第22天:Linux中断驱动开发(一): 突如其来

Linux版本号4.1.15   芯片I.MX6ULL                                    大叔学Linux    品人间百味  思文短情长 


        中断作为驱动开发中很重要的一个概念,在实际的项目实践中经常用到。本节的主要内容包括中断简介、硬件原理分析、驱动程序开发及运行测试。其中驱动程序的开发是本节的重点内容。

        本节内容较多,分两次更新。

        本笔记的思维导图如下:

一、Linux中断简介

1.中断API函数

        中断号:很好理解,不赘述了。

        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:中断标志
name:中断名字,设置以后可以在/proc/interrupts 文件中看到对应的中断名字。
dev: 如果将 flags 设置为 IRQF_SHARED 的话, dev 用来区分不同的中断,一般情况下将
dev 设置为设备结构体, dev 会传递给中断处理函数 irq_handler_t 的第二个参数。
返回值: 0 中断申请成功,其他负值 中断申请失败,如果返回-EBUSY 的话表示中断已经
被申请了。
free_irq 函数:中断释放

如果中断不是共享的,那么 free_irq 会删除中断处理函数并且禁止中断。 free_irq
函数原型如下所示:

void free_irq(unsigned int irq,
void *dev)

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

中断处理函数:

中断处理函数格式如下所示:
 

irqreturn_t (*irq_handler_t) (int, void *)

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

10 enum irqreturn {
11 IRQ_NONE = (0 << 0),
12 IRQ_HANDLED = (1 << 0),
13 IRQ_WAKE_THREAD = (1 << 1),
14 };
15
16 typedef enum irqreturn irqreturn_t;

一般中断服务函数返回值使用如下形式:

return IRQ_RETVAL(IRQ_HANDLED)

中断使能与禁止:

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

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

void disable_irq_nosync(unsigned int irq)

关闭当前处理器的整个中断系统:

local_irq_enable()
local_irq_disable()

要考虑到别的任务的感受,此时就要用到下面两个函数:

local_irq_save(flags)
local_irq_restore(flags)

这两个函数是一对, local_irq_save 函数用于禁止中断,并且将中断状态保存在 flags 中。
local_irq_restore 用于恢复中断,将中断到 flags 状态。


2.上半部和下半部

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

        1)不希望被打断

        2)时间敏感

        3)硬件相关

        Linux 内核使用结构体 softirq_action 表示软中断,内容如下:

433 struct softirq_action
434 {
435 void (*action)(struct softirq_action *);
436 };

softirq_action 结构体中的 action 成员变量就是软中断的服务函数
要使用软中断,必须先使用 open_softirq 函数注册对应的软中断处理函数, open_softirq 函数原型如下:

void open_softirq(int nr, void (*action)(struct softirq_action *))

nr:要开启的软中断,在示例代码 51.1.2.3 中选择一个。
action:软中断对应的处理函数。
返回值: 没有返回值。
注册好软中断以后需要通过 raise_softirq 函数触发, raise_softirq 函数原型如下:
 

void raise_softirq(unsigned int nr)

nr:要触发的软中断
无返回值

! Linux 内核使用 softirq_init 函数初始化软中断。

634 void __init softirq_init(void)
635 {
636 int cpu;
637
638 for_each_possible_cpu(cpu) {
639 per_cpu(tasklet_vec, cpu).tail =
640 &per_cpu(tasklet_vec, cpu).head;
641 per_cpu(tasklet_hi_vec, cpu).tail =
642 &per_cpu(tasklet_hi_vec, cpu).head;
643 }
644
645 open_softirq(TASKLET_SOFTIRQ, tasklet_action);
646 open_softirq(HI_SOFTIRQ, tasklet_hi_action);
647 }

softirq_init 函数默认会打开 TASKLET_SOFTIRQ 和HI_SOFTIRQ。


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

484 struct tasklet_struct
485 {
486 struct tasklet_struct *next; /* 下一个 tasklet */
487 unsigned long state; /* tasklet 状态 */
488 atomic_t count; /* 计数器,记录对 tasklet 的引用数 */
489 void (*func)(unsigned long); /* tasklet 执行的函数 */
490 unsigned long data; /* 函数 func 的参数 */
491 };

tasklet_init 函数初始化 tasklet,taskled_init 函数原型如下:

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(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。
work_struct 结构体表示一个工作:
 

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

工作队列使用 workqueue_struct 结构体表示。

worker 结构体表示工作者线程。

每个 worker 都有一个工作队列。
只需要定义工作(work_struct)即可。

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

#define INIT_WORK(_work, _func)

_work 表示要初始化的工作, _func 是工作对应的处理函数。
DECLARE_WORK 宏一次性完成工作的创建和初始化:

#define DECLARE_WORK(n, f)

n 表示定义的工作(work_struct), f 表示工作对应的处理函数。
工作的调度函数为 schedule_work,函数原型如下所示:

bool schedule_work(struct work_struct *work)

work: 要调度的工作。
返回值: 0 成功,其他值 失败。
 

3.设备树中断信息节点

intc 节点就是I.MX6ULL 的中断控制器节点。

对于 ARM 处理的
GIC 来说,一共有 3 个 cells,这三个 cells 的含义如下:
第一个 cells:中断类型, 0 表示 SPI 中断, 1 表示 PPI 中断。
第二个 cells:中断号,对于 SPI 中断来说中断号的范围为 0~987,对于 PPI 中断来说中断
号的范围为 0~15。
第三个 cells:标志, bit[3:0]表示中断触发类型,为 1 的时候表示上升沿触发,为 2 的时候
表示下降沿触发,为 4 的时候表示高电平触发,为 8 的时候表示低电平触发。 bit[15:8]为 PPI 中
断的 CPU 掩码。
interrupt-controller 节点为空,表示当前节点是中断控制器。
gpio 节点也可以作为中断控制器。
简单总结一下与中断有关的设备树属性信息:
①、 #interrupt-cells,指定中断源的信息 cells 个数。
②、 interrupt-controller,表示当前节点为中断控制器。
③、 interrupts,指定中断号,触发方式等。
④、 interrupt-parent,指定父中断,也就是中断控制器。
 

4.获取中断号

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 对应的中断号。
 

二、硬件原理图

按键 KEY0 是连接到 I.MX6U 的 UART1_CTS 这个 IO 上的, KEY0接了一个 10K 的上拉电阻,因此 KEY0 没有按下的时候 UART1_CTS 应该是高电平,当 KEY0按下以后 UART1_CTS 就是低电平。
 


以下内容,将在后续的笔记中整理更新:

三、驱动开发

1.修改设备树文件

2.按键中断驱动程序编写

3.编写测试APP

四、运行测试

1.编译驱动程序和测试APP

2.运行测试

五、总结


本文为参考正点原子开发板配套教程整理而得,仅用于学习交流使用,不得用于商业用途。

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

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

相关文章

【用unity实现100个游戏之13】复刻类泰瑞利亚生存建造游戏——包括建造系统和库存系统

文章目录 前言素材人物瓦片其他 一、建造系统1. 定义物品类2. 绘制地图3. 实现瓦片选中效果4. 限制瓦片选择5. 放置物品功能6. 清除物品7. 生成和拾取物品功能 二、库存系统1. 简单绘制UI2. 零代码控制背包的开启关闭3. 实现物品的拖拽拖拽功能拖拽恢复问题 4. 拖拽放置物品5. …

FastestDet---模型训练

代码:https://github.com/dog-qiuqiu/FastestDet 一、构造数据集 数据集格式YOLO相同,每张图片对应一个txt标签文件。标签格式:“category cx cy wh”,category为类别id,cx, cy为归一化标签框中心点的坐标,w, h为归一化标签框的宽度和高度, .txt标签文件内容示例如下: 0…

c++迷宫小游戏

一、总结 一句话总结&#xff1a; 显示&#xff1a;根据map数组输出图像 走动&#xff1a;修改map数组的值&#xff0c;每走一步重新刷新一下图像就好 1、如果走函数用z()&#xff0c;出现输入s会向下走多步的情况&#xff0c;原因是什么&#xff1f; 向下走两层循环ij增加&a…

云中网络的隔离GREVXLAN

底层的物理网络设备组成的网络我们称为 Underlay 网络&#xff0c;而用于虚拟机和云中的这些技术组成的网络称为 Overlay 网络&#xff0c;这是一种基于物理网络的虚拟化网络实现。 第一个技术是 GRE&#xff0c;全称 Generic Routing Encapsulation&#xff0c;它是一种 IP-o…

深信服云桌面用户忘记密码后的处理

深信服云桌面用户忘记了密码&#xff0c;分两种情况&#xff0c;一个是忘记了登录深信服云桌面的密码&#xff0c;另外一个是忘记了进入操作系统的密码。 一、忘记了登录深信服云桌面的密码 登录虚拟桌面接入管理系统界面&#xff0c;在用户管理中选择用户后&#xff0c;点击后…

20分钟彻底理解Pointpillars论文-妥妥的

PointPillars: Fast Encoders for Object Detection from Point Clouds PointPillars&#xff1a;快就对了 摘要&#xff08;可跳过&#xff09;&#xff1a; 这帮人提出了PointPillars&#xff0c;一种新颖的编码器&#xff0c;它利用PointNets来学习以垂直列组织的点云&am…

一个简单的工具,多种用途—J2L3x的优势

J2L3x 是一款流行的团队合作工具&#xff0c;许多组织和公司已经开始使用它来简化和提高沟通和协作的效率。J2L3x 的优势与其多种用途不无关系&#xff0c;下面将详细介绍。 1、实时通信与信息共享 J2L3x 通过实时通信功能&#xff0c;使团队成员随时随地都能保持联系。J2L3x…

Python 实现 PDF 文件转换为图片 / PaddleOCR

文章用于学习记录 文章目录 前言一、PDF 文件转换为图片二、OCR 图片文字识别提取三、服务器端下载运行 PaddleOCR四、下载权重文件总结 前言 文字识别&#xff08;Optical Character Recognition&#xff0c;简称OCR&#xff09;是指将图片、扫描件或PDF、OFD文档中的打印字符…

Flask扩展:简化开发的利器以及26个日常高效开发的第三方模块(库/插件)清单和特点总结

目录 寻找扩展 使用扩展 创建扩展 26个常用的Flask扩展模块 总结 原文&#xff1a;Flask扩展&#xff1a;简化开发的利器以及26个日常高效开发的第三方模块&#xff08;库/插件&#xff09;清单和特点总结 (qq.com) Flask是一个轻量级的Python Web框架&#xff0c;它提供…

【计算机网络】互联网公司的网络架构和业务场景

互联网公司的网络架构和业务场景 1. 互联网公司网络的组成1.1 网络的物理组成1.2 骨干网组成1.3 数据中心网络组成 2.互联网公司网络服务场景2.1 通用服务场景2.1.1 客户端到服务端请求真实网络过程2.1.2 客户端到服务端请求抽象网络过程2.1.3 负载均衡网络模型 2.2 边缘服务场…

python学习之路

python 初识python下载python安装python安装成功 idea中配置python环境并运行我的idea是2022版和上一个有点区别VSCode搭建Python开发环境(含Python环境搭建) 学习python 初识python 当我了解python时我决定试一试 首先了解一下什么是python,推荐廖雪峰老师的官网 python简介 …

C语言连接MySQL并执行SQL语句(hello world)

1.新建一个控制台项目 参考【VS2022 和 VS2010 C语言控制台输出 Hello World】VS2022 和 VS2010 C语言控制台输出 Hello World_vs2022源文件在哪_西晋的no1的博客-CSDN博客 2.安装MySQL 参考【MySQL 8.0.34安装教程】MySQL 8.0.34安装教程_西晋的no1的博客-CSDN博客 3.复制MySQ…

sentinel-dashboard-1.8.0.jar开机自启动脚本

启动阿里巴巴的流控组件控制面板需要运行一个jar包&#xff0c;通常需要运行如下命令&#xff1a; java -server -Xms4G -Xmx4G -Dserver.port8080 -Dcsp.sentinel.dashboard.server127.0.0.1:8080 -Dproject.namesentinel-dashboard -jar sentinel-dashboard-1.8.0.jar &…

m4a怎么转换mp3?4个方法包教包会

m4a怎么转换mp3&#xff1f;M4A是一种备受欢迎的音频文件格式&#xff0c;通常用于存储高保真音频数据。它代表着“MPEG-4 Audio”扩展名&#xff0c;这意味着它属于基于MPEG-4标准的音频格式之一。M4A格式有着众多的优势。首先&#xff0c;它能够提供出色的音质&#xff0c;并…

Sui主网升级至V1.10.1版本

升级要点 Sui协议版本升至&#xff1a;25 #13822 使用由仪式生成的验证密钥来验证zklogin交易中的证明&#xff0c;升级协议版本至25&#xff0c;启用JWK共识和3个OAuth提供商的zklogin标志。 #13422 在构建具有这些元素的Move代码时&#xff0c;可能会出现关于未使用常量…

中药材商城小程序的作用是什么

古往今来中药材的作用非常大&#xff0c;无论中医院还是相关药材作坊都会有大量人购买&#xff0c;随着互联网电商拓展更多商品类目&#xff0c;中药材也可以通过线上销售&#xff0c;让消费者随时购买到所需商品&#xff0c;商家也能获得更多生意。 那么通过【雨科】平台搭建中…

Python大数据之Python进阶(一)介绍

课程介绍 数据埋点本质上就是进行数据采集&#xff0c;数据埋点是对自身业务数据进行采集。要进行数据埋点就要了解我们的业务程序的开发流程&#xff0c;知道整个数据的传递过程&#xff0c;这样能让我们更加明确数据分析的业务需求&#xff0c;有利于数据埋点的准确性。 在…

QT基础入门——认识与创建QT(一)

前言&#xff1a; 前面学了Linux的基础命令、系统编程、网络编程&#xff0c;对LInux的使用也有了一个简单的了解与认识&#xff0c;之后的学习就要用到 imx6ull_pro这款开发板进行学习了&#xff0c;所以在使用前还是决定把QT的基础知识学习一下&#xff0c;好在后面的linu…

ssl证书申请

申请SSL证书其实没有那么复杂&#xff0c;给大家总结了一下&#xff0c; 就是提交一下域名配合解析就可以申请。 一、申请准备&#xff1a; 1、域名&#xff08;域名一般主域名或者子域名为主&#xff0c;比如&#xff1a;baidu.com或者bbs.baidu.com&#xff09; 2、邮箱&a…

leetCode 198.打家劫舍 动态规划

198. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09; 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#…