混杂设备驱动、Linux内核中的中断、火焰传感器驱动、呼吸传感器驱动、等待队列

混杂设备驱动

混杂设备也叫杂项设备,是对普通的字符设备(struct cdev)的一种封装。misc 设备会自动创建cdev,不需要像我 们以前那样手动创建,因此采用misc 设备驱动可以简化字符设备驱动的编写。具有以下特点:

1) 主设备号为10,次备号不同。
2) 大大简化cdev的设计流程。
3) 混杂设备与普通的字符设备在使用上并没有区别。

开发步骤

在模块加载函数中注册一个混杂设备

int misc_register(struct miscdevice * misc);

struct miscdevice结构体中我们主要关注3个成员:

1. minor:子设备号,由于主设备号都是10,子设备号必须指定而且不 能冲突, linux/miscdevice.h中定义了几个子设备号,如果需要动态获取,就用MISC_DYNAMIC_MINOR

2. name:将来在/dev下的设备名

3. fops:指向文件操作结构体变量的指针

      int ret;//创建混杂设备驱动  ret = misc_register(&fire_device);  if(ret){   printk("misc_register is error");return ret;}

  static struct file_operations fops ={.owner = THIS_MODULE,.open = fire_open,.release = fire_release,.read = fire_read,};//miscdevice 结构体static struct miscdevice fire_device ={.minor = MISC_DYNAMIC_MINOR,.fops = &fops,.name = "fire"};

对应的在模块卸载函数中注销这个混杂设备:misc_deregister(&fire_device);

Linux内核中的中断

如果按照之前的知识编写按键驱动程序,大概率会编写出一个查询方式的按键驱动。这样的做法对整个系统来说效率 比较低,使用中断方式是个不错的办法。

中断是什么?

中断就是单片机正在执行程序时,由于内部或外部事件的触发,打断当前程序,转而去处理这一事件,当处理完成后再回到原来被打断的地方继续执行原程序的过程。
                在ARM体系结构中,中断通常由外设或外部输入产生,有时也可以由软件触发。中断是单片机系统处理紧急或突发事件的重要方式,如定时器溢出、按键输入、串口数据到达等。

                        

什么是软中断?什么又是硬中断?

硬中断由硬件产生,每个设备或设备集都对应着一个中断向量号。

中断处理函数一定要快点执行完毕,越短越好。

Linux 系统为了解决中断处理程序执行过长和中断丢失的问题,将中断过程分成了两个阶段,分别是「上半部和下半部分」(或叫做顶半部和底半部)都是一个意思。

  • 上半部直接处理硬件请求,也就是硬中断,主要是负责耗时短的工作,特点是快速执行;
  • 下半部是由内核触发,也就是软中断,主要是负责上半部未完成的工作,通常都是耗时比较长的事情,特点是延迟执行

硬中断(上半部)是会打断 CPU 正在执行的任务,然后立即执行中断处理程序,而软中断(下半部)是以内核线程的方式执行。

举个例子,如果我们需要通过adc的值计算某个物理量的,那么几个 计算的过程可能是比较费时的。因此,从adcdat0寄存器读取数值应 该放在中断上半部。计算物理量的过程应该放在中断下半部,即read 函数。

主要意思就是不要在中断处理函数中写太多的东西,因为会占用cpu,中断处理函数仅仅响应中 断,然后清除中断标志位即可。

中断相关的函数

要使用linux内核中断必须要注册中断。注册中断使用的函数为

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

相关参数为:

irq:中断号,差不多就是裸机程序中的中断号。这里三星公司在 Linux源码中重新定义了2440等Soc的所有中断号。在文件 arch/arm/mach-s3c24a0/include/mach/irqs.h。结合mini2440开发板, 按键1所对应的就是IRQ_EINT8。

2. handler:中断处理函数指针,就是当某个中断产生时调用的中断服务函数的入口地址。

内核中的定义如下:typedef irqreturn_t (*irq_handler_t)(int, void *);

irq_handler_t是一个函数指针,这个函数指针必须指向返回值是irqreturn_t,函数参数必须是int和void *的那 种函数。

irqreturn_t fire_handler(int irq_num, void *dev){   if(irq_num == IRQ_EINT8){fire = 1;}conditon = 1;wake_up(&wq);return IRQ_HANDLED;}

3.flags:该参数用于表明中断产生的条件以及系统在处理时的行为,我们使用 IRQF_TRIGGER_FALLING和IRQF_DISABLED,表示电平的下降沿方式和在处理中断时不响应其他中断;

下降沿触发中断:

  • 作用:在引脚电平从高变低(下降沿)时触发中断。
  • 原理:当GPIO引脚检测到从高电平(逻辑1)变为低电平(逻辑0)时,生成一个中断请求。
  • 应用场景
    • 按键检测:检测按键被松开(假设按键松开时引脚电平由高变低)。
    • 传感器信号:当传感器输出信号由高变低时,触发中断处理数据。

4. name:为中断起个名字,设置以后可以在/proc/interrupts 文件 中看到对应的中断名字;

5.给中断服务函数传参,就是key_irq_handle的pData

void free_irq(unsigned int irq, void *dev_id);和request_irq相反,注销已经注册过的中断

void disable_irq(unsigned int irq);禁止某个中断发生,如果这个中断 正在执行,那么就等待中断执行结束后再禁止它

等待队列和poll轮询

read() 系统调用默认是阻塞的,即如果没有任何数据可读,read() 将会一直等待直到有数据可读或者发生错误。但是,有时设备驱动可能会以非阻塞模式工作,特别是在一些特殊情况下,例如键盘或其他输入设备,如果没有按键按下,设备可能不会产生任何数据供 read() 读取。

意思就是按键不按下 也不会一直读取0

为了实现一种机制使得 read() 能够在没有数据时阻塞,并在有数据时返回,通常会使用两种主要技术:等待队列和轮询机制(如 select() 和 poll())。


等待队列

等待队列是一个内核提供的同步工具,它允许内核在特定条件不满足时让进程挂起,然后在条件满足时唤醒它们。

static wait_queue_head_t wq; //等待队列头数据类型为 wait_queue_head_t,
static int conditon;//等待条件

init_waitqueue_head(&wq);//初始化等待队列头使用带参宏init_waitqueue_head(q)
wait_event_interruptible(wq, conditon);//让程序进入阻塞态

四种等待函数

1. wait_event(wq, condition) :等待以wq 为等待队列头的等待队列被 唤醒,前提是condition 条件必须满足(为真),否则一直阻塞。此函数会将进程设置为TASK_UNINTERRUPTIBLE 状态

2. wait_event_interruptible(wq, condition):与wait_event 函数类似,但 是此函数将进程设置为TASK_INTERRUPTIBLE,就是可以被信号打 断

3. wait_event_timeout(wq, condition, timeout):功能和wait_event 类似, 但是此函数可以添加超时时间,以jiffies 为单位。此函数有返回值, 如果返回0 的话表示超时时间到,而且condition为假。为1 的话表 示condition 为真,也就是条件满足了。

4. wait_event_interruptible_timeout(wq,condition, timeout) :与 wait_event_timeout 函数类似,此函数也将进程设置为 TASK_INTERRUPTIBLE,可以被信号打断。

轮询机制

如 select() 或 poll()。这些系统调用允许用户空间应用程序检查文件描述符是否准备好进行读取。当 select() 或 poll() 返回时,表示至少有一个监视的文件描述符准备好进行读取。

火焰传感器驱动

YL-38

驱动部分 

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/irqreturn.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <mach/irqs.h>
#include <asm/uaccess.h>
#include <asm/io.h>#define GPGCON (0x56000060)
#define GPGDAT (0x56000064)
#define GPGUP (0x56000068)
static unsigned int *regGPGCON;
static unsigned int *regGPGDAT;
static unsigned int *regGPGUP;static wait_queue_head_t wq; //用于管理等待队列
static int conditon;//等待条件
int fire = 0;//火焰传感器的信号irqreturn_t fire_handler(int irq_num, void *dev)//
{	if(irq_num == IRQ_EINT8){fire = 1;}conditon = 1;// 把等待条件变为真   进入阻塞wake_up(&wq);//唤醒read()函数的阻塞状态  return IRQ_HANDLED;//表示中断已被正确处理
}int fire_open(struct inode *p_node, struct file *fp)
{printk("kernel open\n");return 0;
}int fire_release(struct inode *p_node, struct file *fp)
{return 0;
}ssize_t fire_write(struct file *fp, const char __user *user_buffer, size_t n, loff_t *offset)
{return 0;
}//注意!!!!   这是相当于要在应用程序中监听火焰传感器的数据(按键是否按下
//但我们不能在驱动层用一个死循环来实现   
//在驱动层使用死循环会导致cpu无法做其他的操作而造成资源浪费//如果当前没有中断发生,进程会阻塞直到中断发生并设置标志
//然后将中断标志复制到用户空间并返回。这样就实现了阻塞式的读取操作ssize_t fire_read(struct file *fp, char __user *user_buffer, size_t n, loff_t *offset)
{conditon = 0;//在进入阻塞前将等待条件设置为假   此时read()是非阻塞态wait_event_interruptible(wq, conditon);//等待条件变为真copy_to_user(user_buffer, &fire,4);//fire 是int型  4字节   往用户空间穿 fire的值 触发火焰为1    未触发是0fire = 0;//重置标志位   因为是下降沿触发,所以在没有按下按钮时清除firereturn sizeof(fire);
}static struct file_operations fops =
{.owner = THIS_MODULE,.open = fire_open,.release = fire_release,.read = fire_read,
};//miscdevice 结构体
static struct miscdevice fire_device = 
{.minor = MISC_DYNAMIC_MINOR,.fops = &fops,.name = "fire"
};static int __init fire_driver_init(void)
{int ret;//创建混杂设备驱动  ret = misc_register(&fire_device);  if(ret){printk("misc_register is error");return ret;}//注册中断ret = request_irq(IRQ_EINT8, fire_handler, IRQF_TRIGGER_RISING | IRQF_DISABLED, "fire_irq", &fire_device);if(ret){printk("request_irq is error\n");misc_deregister(&fire_device);}// 初始化等待队列init_waitqueue_head(&wq);//相应寄存器引脚映射regGPGCON = ioremap(GPGCON,4);regGPGDAT = ioremap(GPGDAT, 4);regGPGUP = ioremap(GPGUP,4);return 0;
}static void __exit fire_exit(void)
{iounmap(regGPGCON);iounmap(regGPGDAT);iounmap(regGPGUP);//注销中断和混杂设备驱动disable_irq(IRQ_EINT8);free_irq(IRQ_EINT8, &fire_device);misc_deregister(&fire_device);
}module_init(fire_driver_init);
module_exit(fire_exit);MODULE_LICENSE("GPL");

应用程序

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
int main(void)
{int fd = open("/dev/fire",O_RDWR);if(fd<0){printf("file open error\n");return 0;}int n;while(1){read(fd,&n,4);printf("%d\n",n);sleep(1);		}return 0;
}

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

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

相关文章

DVWA靶场通关(CSRF)

CSRF 是跨站请求伪造&#xff0c;是指利用受害者尚未失效的身份认证信息&#xff08;cookie、会话等&#xff09;&#xff0c;诱骗其点击恶意链接或者访问包含攻击代码的页面&#xff0c;在受害人不知情的情况下以受害者的身份向&#xff08;身份认证信息所对应的&#xff09;服…

WRF-LES与PALM微尺度气象大涡模拟

针对微尺度气象的复杂性&#xff0c;大涡模拟&#xff08;LES&#xff09;提供了一种无可比拟的解决方案。微尺度气象学涉及对小范围内的大气过程进行精确模拟&#xff0c;这些过程往往与天气模式、地形影响和人为因素如城市布局紧密相关。在这种规模上&#xff0c;传统的气象模…

生信学院|09月06日《在线产品交流工具》

课程主题&#xff1a;在线产品交流工具 课程时间&#xff1a;2024年09月06日 14:00-14:30 主讲人&#xff1a;曾裕章 生信科技 售后服务工程师 3DEXPERIENCE云平台基于云平台的交流工具XPR功能讲解Q&A 安装腾讯会议客户端或APP报名哦~~~ 或者点击链接报名&#xff1a;…

C语言进阶(一)数据在内存中的存储

整数在内存中的存储 整数的2进制表示方法有三种&#xff0c;即原码、反码和补码 有符号的整数&#xff0c;三种表示方法均有符号位和数值位两部分 符号位用0表示“正”&#xff0c;用1表示“负”&#xff0c;最高位被当做符号位&#xff0c;剩余的都是数值位 正整数的原、反…

构建buildroot根文件系统

目录 1.确定gcc工具版本2.下载Buildroot源码并编译2.1 下载Buildroot源码2.2 配置Buildroot2.2.1 配置 Target options2.2.2 配置交叉编译工具链2.2.3 配置 System configuration2.2.4 配置 Filesystem images2.2.5 禁止编译 Linux 内核和 uboot2.2.6 编译Buildroot源码2.2.7 查…

【多线程】深入剖析线程安全问题

&#x1f490;个人主页&#xff1a;初晴~ &#x1f4da;相关专栏&#xff1a;多线程 / javaEE初阶 前言 线程安全问题是在多线程学习中一个十分重要的话题。多个线程并发执行就容易产生许多冲突与问题&#xff0c;如何协调好每个线程的执行&#xff0c;让多线程编程“多而不乱…

【Node】【3】回调函数

nodejs 是一个基于事件驱动和非阻塞异步的JavaScript运行时环境。 Node.js 采用单线程模型&#xff0c; 单线程意味着 Node.js 在任何给定时刻只能执行一段代码&#xff0c;但通过异步执行回调函数&#xff0c;可以在等待 I/O 操作完成的同时继续执行其他代码&#xff0c;从而…

每日一练-threejs实现三维动态热力图

前言&#xff1a;学习自用Three.js搞个炫酷热力山丘图&#xff0c;作者讲解的十分详细&#xff0c;在这里不再过多赘述&#xff0c;直接上代码&#xff01; <template><div class"map" ref"map"></div> </template><script set…

XTuner微调个人小助手认知 #书生浦语大模型实战营#

1.任务&#xff1a; 本次的任务是使用 XTuner 微调 InternLM2-Chat-1.8B 实现自己的小助手认知&#xff0c;从而让模型能够个性化的回复&#xff0c;让模型知道他是我们的小助手&#xff0c;在实战营帮我们完成XTuner微调个人小助手认知的任务。并截图打卡。 任务打卡&#x…

书生.浦江大模型实战训练营——(十一)LMDeploy 量化部署进阶实践

最近在学习书生.浦江大模型实战训练营&#xff0c;所有课程都免费&#xff0c;以关卡的形式学习&#xff0c;也比较有意思&#xff0c;提供免费的算力实战&#xff0c;真的很不错&#xff08;无广&#xff09;&#xff01;欢迎大家一起学习&#xff0c;打开LLM探索大门&#xf…

复杂的编辑表格

需求描述 表格可以整体编辑&#xff1b;也可以单行弹框编辑&#xff1b;且整体编辑的时候&#xff0c;依然可以单行编辑 编辑只能给某一列&#xff08;这里是参数运行值&#xff09;修改&#xff0c;且根据数据内容的参数范围来判断展示不同的形式&#xff1a;input/数字输入/单…

计算机网络——TCP协议与UDP协议详解(下)

一、TCP协议 1.1 TCP协议的报文 TCP全称为 "传输控制协议(Transmission Control Protocol")。人如其名&#xff0c;要对数据的传输进行一个详细的控制。我们先看其报文格式&#xff0c;如下图&#xff1a; TCP报文由以下几个字段组成&#xff1a; 源端口号和目标端口…

MySQL索引详解:原理、数据结构与分析和优化

在数据库管理系统中&#xff0c;索引是提高查询性能、优化数据存储结构的重要工具。MySQL作为广泛使用的开源关系型数据库管理系统&#xff0c;其索引机制对于提升数据库操作效率具有至关重要的作用。本文将围绕“MySQL索引详解&#xff1a;原理、数据结构与分析和优化”这一主…

CRUD的最佳实践,联动前后端,包含微信小程序,API,HTML等(二)

CRUD老生常谈&#xff0c;但是我搜索了一圈&#xff0c;发觉几乎是着重在后端&#xff0c;也就是API部分&#xff01; 无外乎2个思路 1.归总的接口&#xff0c;比如一个接口&#xff0c;实现不同表的CRUD 2.基于各自的表&#xff0c;使用代码生成器实现CRUD 个人来说是推荐2&am…

Harmony鸿蒙应用开发:解决Web组件加载本地资源跨域

鸿蒙开发文档中有一节 加载本地页面 提到了可以通过 $rawfile 方法加载本地 HTML 网页&#xff1a; Index.ets 1Web({ src: $rawfile("local.html"), controller: this.webviewController })但是如果在 local.html 中需要引用一些静态资源&#xff0c;例如图片、JS、…

MMS论文中关于语种识别的内容摘要

MMS论文中关于语种识别的内容摘要 前言语种识别相关内容实验结论 前言 摘要翻译一些内容。 论文地址请看这里 语种识别相关内容 Whisper支持LID&#xff0c;可以区分99种不同的语言&#xff1b;有人使用wav2vec 2.0实现LID&#xff0c;数据集中包含10种亚洲语言&#xff1b;…

JavaScript - Ajax

Asynchronous JavaScript And XML&#xff0c;异步的JavaScript和XML 作用: 数据交换&#xff1a;通过Ajax可以给服务器发送请求&#xff0c;并获取服务器响应的数据。异步交互&#xff1a;可以在不重新加载整个页面的情况下&#xff0c;与服务器交换数据并更新部分网页的技术…

[新手入门]1台电脑+1个电视+2个软件(sunshine+moonlight) 解决黑神话悟空没有hdmi线的痛...

sunshinemoonlight 解决黑神话悟空 本地串流投屏 背景:偶然间在B站发现了sunshinemoonlight方案,替代hdmi线,做本地串流...于是心灵手巧的我开始尝试踩坑之路:1.准备安装包2.开始安装2.1 笔记本windows安装sunshine2.2 遇到了第一个坑.Fatal: ViGEmBus is not installed or run…

无需多部备用机,云手机方便又便宜!

云手机&#xff0c;是云计算技术的又一创新应用&#xff0c;它通过在云服务器上虚拟出带有原生安卓操作系统的手机实例&#xff0c;为用户提供了一种全新的手机使用体验。无需携带多部手机&#xff0c;只需通过云手机&#xff0c;便可轻松实现多账号管理、应用运行及数据存储等…

【物理学】什么是运动学和动力学?

Kinematics 和 Kinetics 是力学中的两个重要分支&#xff0c;它们虽然都涉及物体的运动&#xff0c;但关注的方面不同。 Kinematics&#xff08;运动学&#xff09; Kinematics 主要研究物体的运动&#xff0c;而不涉及导致运动的力。它关注的是运动的几何特性&#xff0c;比…