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.运行测试
五、总结
本文为参考正点原子开发板配套教程整理而得,仅用于学习交流使用,不得用于商业用途。
相关文章:
Linux学习第22天:Linux中断驱动开发(一): 突如其来
Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 中断作为驱动开发中很重要的一个概念,在实际的项目实践中经常用到。本节的主要内容包括中断简介、硬件原理分析、驱动程序开发及运行测试。其中驱动程…...
IDEA 2019 Springboot 3.1.3 运行异常
项目场景: 在IDEA 2019 中集成Springboot 3.1.3 框架,运行异常。 <?xml version"1.0" encoding"UTF-8"?><project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSch…...
【JAVA】飞机大战
代码和图片放在这个地址了: https://gitee.com/r77683962/fighting/tree/master 最新的代码运行,可以有两架飞机,分别通过WASD(方向),F(发子弹);上下左右(控…...
Midjourney 生成油画技巧
基本 prompt oil painting, a cute corgi dog surrounded with colorful flowers技法 Pointillism 点描绘法 笔刷比较细,图像更精细 oil painting, a cute corgi dog surrounded with colorful flowers, pontillismImpasto 厚涂绘法 笔刷比较粗,图像…...
26559-2021 机械式停车设备 分类
声明 本文是学习GB-T 26559-2021 机械式停车设备 分类. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本文件规定了机械式停车设备的分类及有关的型式、型号和适停汽车组别、尺寸及质量。 本文件适用于 GB/T 3730.1—2001定义的乘用车及商用…...
xxe攻击(XML外部实体)
1.定义 XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。 http://www.w3school.com.…...
大数据-hadoop
1.hadoop介绍 1.1 起源 1.2 版本 1.3生产环境版本选择 Hadoop三大发行版本:Apache、Cloudera、Hortonworks Apache版本最原始的版本 Cloudera在大型互联网企业中用的较多 Hortonworks文档较好 1.4架构 hadoop由三个模块组成 分布式存储HDFS 分布式计算MapReduce 资源调度引擎Y…...
容器启动报错
容器启动报错 docker: Error response from daemon: driver failed programming external connectivity on endpoint XXX 如下: 据百度: 在docker启动后在,再对防火墙firewalld进行操作,就会发生上述报错 详细原因:…...
求生之路2服务器搭建插件安装及详细的游戏参数配置教程linux
求生之路2服务器搭建插件安装及详细的游戏参数配置教程linux 大家好我是艾西,在上一篇文章中我用windows系统给搭建演示了一遍怎么搭建自己的L4D2游戏。 那么也有不少小伙伴想知道linux系统的搭建方式以及在这个过程中有什么区别。 那么艾西今天就跟大家分享下用lin…...
IntelliJ IDEA 左侧Commit栏不见了
1.点击File->Settings->Version Control->Commit 2.勾选Use non-modal commit interface...
使用自功率谱、互功率谱估计滤波器幅频特性
这段时间终于对工程中的随机信号的一般处理方式有点头绪了,功率谱密度估计是十分重要的方式之一,仍需继续深入细化相关内容。 示例:使用自功率谱、互功率谱估计滤波器幅频特性,自己实现 & Matlab自带函数实现。 clc;clear;cl…...
51单片机光照强度检测自动路灯开关仿真( proteus仿真+程序+报告+讲解视频)
51单片机光照强度检测自动路灯开关仿真( proteus仿真程序报告讲解视频) 仿真图proteus7.8及以上 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:S0052 讲解视频 基于51单片机的光照检测自动路灯控制仿真设计( proteus仿…...
socat管理haproxy配置
文章目录 前言一、配置二、简单使用1. 先安装 socat2. 获取 haproxy 的监控数据 总结 前言 我们可以通过 socat 命令 实现对 haproxy 的管理,包括获取监控数据,对后端服务器实现启动停止,服务流量控制等等。 一、配置 要想 haproxy 支持通过…...
Linux发行版X华为鲲鹏openEuler
前言 作为硬件和软件之间的桥梁,我接触的最多的就是Windows和Centos,还记得最初的鸟哥的Linux私房菜,而Centos即将停止维护更新(Centos7维护到2024),对于个人学习来说没有任何影响,但是对于企业…...
计算机网络相关知识点
谈一谈对OSI七层模型和TCP/IP四层模型的理解? 这两种模型都是网络通信中重要的参考模型,他们的设计和功能有一些区别。 首先OSI,OSI七层模型,也被称为开放系统互联参考模型,是一种在国际标准化组织(ISO)中…...
Jmeter+Ant+Git+Jenkins持续集成介绍
【软件测试面试突击班】如何逼自己一周刷完软件测试八股文教程,刷完面试就稳了,你也可以当高薪软件测试工程师(自动化测试) 一 简介 1.什么是ant? ant是构建工具 2.什么是构建 概念到处可查到,形象来说ÿ…...
Spring Cloud Gateway实战WebFlux解析请求体及抛出指定错误代码和信息
概述 基于Spring Cloud开发微服务时,使用Spring Cloud原生自带的Gateway作为网关,所有请求都需要经过网关服务转发。 为了防止恶意请求刷取数据,对于业务请求需要进行拦截,故而可在网关服务增加拦截过滤器。基于此,有…...
Servlet开发-通过代码案例熟悉HttpServletRequest类
关于Servlet开发的流程推荐看servlet开发-通过Tomcat部署一个简单的webapp Servlet开发与idea集成的插件安装推荐看idea集成tomcat(Smart Tomcate插件安装) postman(第三方创建HTTP请求工具)的安装推荐看创建HTTP请求的几种方式…...
离线环境harbor 搭建及使用
一 摘要 本文主要介绍harbor 的安装及使用。 二 环境信息及部署图 2.1 环境信息 名称版本备注操作系统centos7.9容器docker 23.0.1harbor2.7代理nginx待补充 2.2 架构图 说明: 1.harbor 核心服务里有个nginx ,也可以用该nginx 做代理 2.proxy-ngin…...
华为杯数学建模比赛经验分享
再过一周左右,第二十届华为杯数学建模比赛就要开赛了,所以今天分享一下个人数学建模比赛的经验。 今天给大家分享一期关于华为杯数学建模比赛的经验分享,我将从以下三个方面展开说明: (1)如何准备数学建模比赛&#x…...
c语言 - 实现每隔1秒向文件中写入当前系统时间
实现思路 主要是通过库函数和结构体获取当前系统时间(年月日和时分秒)保存到变量里,然后通过格式化输出函数将当前系统时间输出到文件中去。 但是需要注意的是题目要求每隔 1 s对系统时间进行输出,所以需要加入 sleep()函数进行调…...
使用cpolar端口映射的方法轻松实现在Linux环境下SVN服务器的搭建与公网访问
文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件 3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口 5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6…...
前后台分离开发 YAPI平台 前端工程化之Vue-cli
目录 YAPI介绍前端工程化之Vue-cli前端工程化简介前端工程化入门——Vue-cli环境准备Vue项目简介创建Vue项目vue项目目录结构介绍vue项目运行方法 Vue项目开发流程 前后台混合开发这种开发模式有如下缺点: 沟通成本高:后台人员发现前端有问题࿰…...
【js/es6】合集
目录 随机生成字符串每十个字符换行 随机生成字符串 function generateRandomAlphaNum(len) {var rdmString "";for (; rdmString.length < len; rdmString Math.random().toString(36).substr(2));return rdmString.substr(0, len); }每十个字符换行 string.…...
Nginx modules build fail:field ‘pkt6’ has incomplete type
前言 最近升级Nginx 1.24.0,编译第三方module出错: /usr/src/nginx_modules/ngx_json_post_module/src/ngx_json_post_module.c In file included from src/event/ngx_event.h:526,from src/http/ngx_http_upstream.h:14,from src/http/ngx_http.h:34,…...
电脑突然提示mfc140u.dll丢失,缺失mfc140u.dll无法运行程序的解决方法
在当今信息化社会,电脑已经成为我们生活和工作中不可或缺的一部分。然而,随着技术的不断发展,电脑也会出现各种问题。其中,最常见的问题之一就是“mfc140u.dll丢失”。那么,当我们遇到这个问题时,应该如何解…...
国庆day1
消息队列 代码 发送 #include<myhead.h> //声明一个消息结构体 typedef struct {long msgtype; //消息类型char data[1024]; //消息正文 }Msg_s; #define SIZE sizeof(Msg_s)-sizeof(long) //消息正文的大小 int main(int argc, const char *argv[]) {key_t key; /…...
从零开始之了解电机及其控制(11)实现空间矢量调制
广泛地说,空间矢量调制只是将电压矢量以及磁场矢量在空间中调制到任意角度,通常同时最大限度地利用整个电压范围。 其他空间矢量调制模式确实存在,并且根据您最关心的内容,它们可能值得研究。 如何实际执行这种所谓的交替反向序列…...
如何将html转换成markdown
什么是Turndown “Turndown” 是一个用于将 HTML 转换为 Markdown 的 JavaScript 库。它通常用于将富文本内容从网页或其他 HTML 格式转换为纯文本 Markdown 格式,以便在不同平台上显示或存储。 如果在有node环境的情况下要使用 Turndown,首先需要将它…...
【VUE复习·3】@keyup.xxx 键盘事件触发函数(单按键 or 组合按键触发)
总览 1.keyup.xxx or keydown.xxx 单按键触发 2.组合按键触发 一、keyup.xxx or keydown.xxx 1.用法 在我们使用 keyup.enter 时,那么我们可以这样写: <div><input type"text" placeholder"按下回车键以确定..." keyu…...
泊头市做网站/如何推广自己产品
第1关:求图中边或弧的数目 任务描述 本关任务:求给定图中的边(或弧)的数目。 相关知识 实验目的 掌握图的基本概念; 掌握图的存储结构的设计与实现,基本运算的实现; 熟练掌握图的两种遍历算法、遍历生成树及遍历算法的应用。 实验任务 说明:为使实验程序简洁直观,下…...
如何转换page到wordpress/现在推广平台哪家最好
OpenCv图像处理之图像归一化归一化中心化标准化归一化 图像处理中,图像单通道像素值为0~255之间的uchar类型,通常使用min-max归一化将其转化为0~1区间之间,既不会改变数据的分布和信息存储,又加速了后续网络的计算。 min-max归一…...
东营做网站优化的公司/网络营销课程
欢迎来到我的《从源码中学Vue》专题系列文章,更多精彩内容持续更新中,欢迎关注 :)上一章节我们通过源码分析了Vue中的methods对象下的方法是如何挂载到vm下,以及各方法内部的this为何是指向了vm对象。其实在Vue中,还有…...
网站top排行榜/网页推广怎么做的
基本配置: Configuration public class RestConfig {Beanpublic RestClient getClient() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {// 如果有多个从节点可以持续在内部new多个HttpHost,参数1是ip,参数2是HTTP端口…...
佛山百度网站排名优化/免费的行情网站
首先一点要说明的是,在matlab中,矩阵中的元素序号是按照“先行后列”的顺序排列的。设如下随机矩阵:Arand(4,6)A 0.6551 0.95970.7513 0.8909 0.1493 0.81430.1626 0.3404 0.2551 0.9593 0.2575 0.24350.1190 0.5853 0.5060 0.5472 0.8407 0.…...
抚顺市城市建设档案馆网站/中国突然宣布一重磅消息
前言 Nodejs目前处境稍显尴尬,很多语言都已经拥有异步非阻塞的能力。阿里的思路是比较合适的,但是必须要注意,绝对不能让node做太多的业务逻辑,他只适合接收生成好的数据,然后或渲染后,或直接发送到客户端。…...