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

news2024/11/17 15:36:09

混杂设备驱动

混杂设备也叫杂项设备,是对普通的字符设备(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    未触发是0
	fire = 0;//重置标志位   因为是下降沿触发,所以在没有按下按钮时清除fire
	return 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.coloradmin.cn/o/2075965.html

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

相关文章

备战秋招60天算法挑战,Day25

题目链接&#xff1a; https://leetcode.cn/problems/combination-sum/ 视频题解&#xff1a; https://www.bilibili.com/video/BV1xyiueHEb4/ LeetCode 39. 组合总和 题目描述 给你一个无重复元素的整数数组candidates和一个目标整数target&#xff0c;找出candidates中可以…

[ACP云计算]易错题(原题)

一、ECS 1、 2、 3、 4、 5、 6、 7、 8、 9、 10、 11、 12、 13、 二、对象存储OSS 1、 2、 3、 4、 5、 6、 重点&#xff01;&#xff01;&#xff01; 7、 8、 9、 10、 11、 12、 13、 14、 15、 16、 17、 18、 19、 20、 21、 22、 内容分发网络CDN 1、 2、 3、 4…

宝塔面板配置FTP服务并安装内网穿透实现无公网IP远程连接

文章目录 前言1. Linux安装Cpolar2. 创建FTP公网地址3. 宝塔FTP服务设置4. FTP服务远程连接小结 5. 固定FTP公网地址6. 固定FTP地址连接 前言 本文主要介绍宝塔FTP文件传输服务如何搭配内网穿透工具&#xff0c;实现随时随地远程连接局域网环境搭建的宝塔FTP文件服务并进行文件…

从虚拟化到容器化再到池化,AI算力的灵活调度技术研究

AI算力&#xff0c;触手可及 ©作者|坚果 来源|神州问学 引言 - AI时代下的算力变革 近年来&#xff0c;人工智能&#xff08;AI&#xff09;技术的快速发展极大地推动了各个领域的创新与进步。伴随着AI模型复杂度的不断提高以及数据量的爆炸式增长&#xff0c;对于高性…

厨帽检测算法样本算法模型和厨帽检测算法实际应用

厨帽检测算法是一种利用计算机视觉和深度学习技术来监控厨房工作人员是否佩戴规定的厨帽&#xff0c;以确保食品安全和卫生标准的遵守。以下是关于厨帽检测算法源码及其实际应用的详细阐述&#xff1a; 1. 算法实现 - 基于深度学习的对象识别&#xff1a;厨帽检测算法通常采用…

2024年【安全生产监管人员】考试试卷及安全生产监管人员复审考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 安全生产监管人员考试试卷根据新安全生产监管人员考试大纲要求&#xff0c;安全生产模拟考试一点通将安全生产监管人员模拟考试试题进行汇编&#xff0c;组成一套安全生产监管人员全真模拟考试试题&#xff0c;学员可…

全球高增速电商市场有哪些?这些市场上主流电商平台又有哪些呢?

跨境电商风起云涌&#xff0c;当欧美市场步入存量竞争&#xff0c;单量的大幅下滑成为广大卖家的普遍痛点。然鹅&#xff0c;有一些市场却频频传来爆单喜讯&#xff0c;我们一起来了解一下—— 全球高增速电商市场有哪些&#xff1f; 首先&#xff0c;在全球电商增速最快的国家…

【UE5】UMG C++父类绑定蓝图子类属性

有时我们在设计UMG时可能会使用到C父类来处理一些通用逻辑&#xff0c;如果我们想要在C父类中获取其派生子类的某个属性&#xff0c;如Image或Button等&#xff0c;我们可以通过使用UE提供的BindWidget元数据标签的方式来获取。 BindWidget BindWidget元数据标签在官方文档中…

【C++指南】类和对象(一):类和对象的定义和使用 基础讲解

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《C指南》 期待您的关注 目录 引言 文章思路 一、类的定义 1.类的定义 2.类的访问限定符 3.class与struct的使用区别 4.类域…

topo组态引入-记录

一、目录&#xff08;vue-router映射到下面的index.vue界面&#xff09; &#xff08;自己记录&#xff0c;别下载不用看&#xff09;

Prometheus:alertmanager实战分组、抑制、静默

1 项目目标 &#xff08;1&#xff09;熟练部署alertmanager &#xff08;2&#xff09;熟练整合alertmanagerPrometheus &#xff08;3&#xff09;熟练alertmanager分组、抑制、静默 2 项目准备 2.1 规划节点 主机名 主机IP 节点规划 prome-master01 10.0.1.10 服务…

Graylog日志丢失解决方案

问题描述 目前公司使用的日志方案是Graylog5.0版本&#xff0c;当接入的日志并发多时&#xff0c;就会出现日志丢失的情况。 目前硬件系统centos7.9 内核5.16.13。一台graylog和一台es服务器。 两台机器硬件配置 graylog CPU 36C 内存 150G 系统硬盘 500G &#xff08;固态&…

盘点15款主流的项目管理软件,优缺点一目了然!

本文将盘点对15款主流的项目管理软件进行盘点&#xff1a; 简道云、Worktile、Teambition、Tower、泛微 e-office、用友项目管理软件、金蝶云星瀚项目管理、腾讯 TAPD、Asana、Trello、Jira、Basecamp、Monday.com、Wrike、Smartsheet。 在现代企业的运营中&#xff0c;项目管理…

uniapp,uview:inputnumber或者input,当type为number的时候,在ios里输入不了小数的问题

项目场景&#xff1a; 在做uniapp的H5页面时&#xff0c;有个需求是要输入框要能支持可以保留两位小数输入&#xff0c;不能输入负数和其他字符。心想这简单&#xff0c;直接用uview的inputnumber组件这不就好了&#xff0c;结果测试提bug说不能输入小数点&#xff0c;我心想我…

基于Hadoop+Zookeeper+Hive+HBase+Echarts的地区旅游大数据可视化管理系统设计与实现

绪论 研究背景 当今时代信息资源日益丰富大量&#xff0c;信息资源的利用对社会的发展起着主要作用&#xff0c;运用信息技术协助产业设计越来越成为行业发展的重要趋势。 旅游产业是典型的体验服务产业&#xff0c;在任何发展阶段&#xff0c;信息反馈的准确性与及时性都具…

【表格】EEG作为脑成像工具的分析与应用

EEG作为脑成像工具的分析与应用 【表格】EEG空间分析方法与应用 方法/应用描述关键点示例/公式备注全局场功率(GFP)量化头皮电位场的强度 G F P σ ( V t ) GFP \sigma(V_t) GFPσ(Vt​) 其中 V t V_t Vt​为t时刻各电极电压无具体公式&#xff0c;为标准差计算提供对同步活…

C和C++中数组的不同

本文选自公众号文章&#xff1a; https://mp.weixin.qq.com/s/xyUMWTyEu7-Uws8Zfxifpghttps://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxcheckurl?requrlhttps%3A%2F%2Fmp.weixin.qq.com%2Fs%2FxyUMWTyEu7-Uws8Zfxifpg&skey%40crypt_963c540a_c8e6882f00ef27f0c27a8357dea50…

了解Redis数据持久化(下)

4.AOF 写后日志&#xff0c;避免宕机数据丢失 4.1 AOF说明 AOF日志存储的是Redis服务器的顺序指令序列只记录对内存进行修改的指令append-only file&#xff08;AOF&#xff09;AOF主要是主线程在执行&#xff0c;将日志写入磁盘的过程中&#xff0c;如果磁盘压力太大&#x…

USB3.2 摘录(九)

系列文章目录 USB3.2 摘录&#xff08;一&#xff09; USB3.2 摘录&#xff08;二&#xff09; USB3.2 摘录&#xff08;三&#xff09; USB3.2 摘录&#xff08;四&#xff09; USB3.2 摘录&#xff08;五&#xff09; USB3.2 摘录&#xff08;六&#xff09; USB3.2 摘录&…

HCIA--网络地址转换NAT技术

NAT(Network Address Translation&#xff0c;网络地址转换技术是为了缓解IPv4地址有限的问题。 NAT技术主要用于实现内部网络的主机访问外部网络。一方面NAT缓解了IPv4地址短缺的问题&#xff0c;另一方面NAT技术让外网无法直接与使用私有地址的内网进行通信&#xff0c;提升…