LINUX按键驱动程序

时间:2022-09-07 23:34:59

《《混杂设备驱动模型》》

《混杂设设备的描述》

<混在设备的概念>

在linux系统中,存在一类字符设备,他们拥有相同的主设备号(10),但是次设备号不同,称这类设备为混在设备(missdevice),所有的混杂设备形成一个链表,对设备进行访问,根据次设备号在链表中查找相应的混杂设备。

注意:混杂设备是字符设备的一种。

<混杂设备的设备描述符>

struct miscdevice

{

int minor;   /*次设备号*/

const char *name; /*设备名*/

const struct file_operrations  *fops; /*文件操作*/

struct list_head list;

struct device *parent;

struct  device *this _device ;

};

<设备注册>

在linux系统中欧使用函数 misc_register() 函数来注册一个混杂设备驱动。

函数原型:

int misc_register(struct miscdevice *misc)

<设备注销>

函数原型:

int mic_deregister (struct miscdevice * misc)

《linux中断处理》

<裸机中中断处理流程>

中断会有一个统一的入口: ldr pc,_irq ——》保存环境处理——》执行:bl handle_init 指令——》 根据中断号,调用与之对应的中断处理程序。

<linux中中断处理流程分析>

在linux系统中也有一个中断处理的同样的入口:irq_svc ——》接着做相应的环境保存——》获取产生中断的中断源(寄存器 INTPND)——》利用中断号找到irq_disc[*]这个结构——》在action 中就有用户事先填写编写好的处理函数

总结:驱动程序需要做哪些事?

1)实现中断处理过程

2)将中断处理程序注册到linux系统中

<linux 中中断处理程序>

1)注册中断

函数原型:
int request_irq(unsigned int irq, void (*handler )(int ,void *,struct pt_regs*),unsigned long flags,const char*devname, void *dev_id)

参数分析:

unsigned int irq: 中断号

注意:中断号和中断类型区别

#define S3C2410_CPUIRQ_OFFSET (16)

#define S3C2410_IRQ(x) ((x) + S3C2410_CPUIRQ_OFFSET)

void (*handler )(int ,void * , struct pt_regs * ): 中断处理程序

unsigned long flags :与中断处理有关的各种的选项

例:

IRQF_DISABLEED (SA_INTERRUPT) :快速中断处理程序,如果没有该位,则表示慢速中断处理程序

注意:快速中断和慢速中断的区别

快/慢速中断主要区别在于:快速中断保证中断处理的原子性(不被打断),而慢速中断则不保证,换句话说就是开启中断标志位 (屏蔽)(处理器 IF),在运行快速中断程序是关闭的,英因此在服务该中断时,不会别其他类型的中断打断;而调用慢速中断处理时,其他类型的中断可以得到服务。

IRQF_SHARED(SA_SHIRQ):表明该中断号是设备共享的()多个设备可以共享多个中断。

IRQF_TRIGGER_FALLING: 下降沿产生中断

const char * devname:设备名

void * dev_id :共享中断时使用

返回值:

返回0 表示成功

失败:

返回一个非0 的错误值

注意:中断处理程序是在中断上下文中运行的,他的行为可能受某些限制:

1)不能使用可能引起阻塞的函数

2)不能使用可能引起调度的函数

2)中断处理

一般处理流程:

检查设备是否产生中断——》清除中断标志(要不然下次中断没法响应)——》相应的硬件操作

3)注销中断

函数原型:

void free_irq(unsigned int irq,void *dev_id)

参数分析:

irq;中断号

dev_id:对于共享中断,一个中断号,对应多个中断程序,位了将加载的中断处理程序卸载,将其中对每个中断处理程序进行编号:dev_id

《中断分层技术》

<中断嵌套>

(1)慢速中中断

当处理慢速中断当过程中,中断开关(IF)是关闭当的,即可以被其他中断打断,执行本中断,直到处理完成,再返回执行执之前被打断当中断。

注意:如果执行中断当过程中是被同类型当中断打断,此时linux系统是不会执行该中断当。

(2)快速中断

不可以被其他中断打断

<中断分层技术>

背景:

中断处理流程大致可以分为和和硬件有关的工作,和硬件无关当工作,linux系统中,将和硬件有关的工作被放到中断处理程序中去做,其他的部分放到其他地方做。其目的是减少处理中断处理的时间。使用以下三中方式处理和硬件无关部分处理。

(1)软中断

(2)tasklet

(3)工作队列

LINUX按键驱动程序

由上图可以看见,加入说这是一个3核当CPU,每一CPU后面都跟有一个队列,将和硬件没有关系的处理程序插入到这些链表中,linux内核会为每一个链表创建一个线程,系统会在CPU相对空闲的时候把挂着的线程处理一遍,当处理完一个线程该链表就会从该队列中消失。

LINUX按键驱动程序

<使用工作队列实现分层>

(1)如何实现工作队列

struct workqueue_struct

{

struct cpu_workqueue_struct *cpu_wq;

struct list_head list;

const char *name;  /*workqueue name */

int signalthread;

int freezeable  /*freeze threads during suspend*/

int rt;

}

(2)如何描述一个工作

struct work_struct

{

atomic_long_t data;

struct list _head entry;

work_fun_t func;

}

(3)实现步骤

1)创建工作队列

函数:

create_workqueue(“name”)

2)创建工作

函数:

INIT_WORK(work,fun)

3)提交工作(将工作挂载到工作队列上)

函数:
queue_work(work_queue,work)

注意:要创建工作队列,必须遵循GPL协议。

MOUDLE_LICENSE(“GPL”)

注意:但是在大多数情况下并不需要我们定义工作队列,linux系统会有一个默认当工作队列keventd_wq,所以只需要将工作挂载到该工作队列上即可。

挂载函数:

schedule_work(work)
《按键去抖》

<背景分析>

在按动按键的时候,因硬件设计的缺陷,会导致信号出现尖刺,从而导致输入信号不准确。

<处理按键抖动>

(1)硬件去抖

(2)软件去抖

一般软件去抖采用延时的方式:
1)for()循环

2)定时延时

在Linux系统中使用结构体数组:
struct timer_list

{

struct list_head entry;

unsigned long expires;

viod (*function )(unsigned long);

unsigned long data;

struct tvec_base *base;

}

expires:用来设定时间

function:这个函数指针指向定时结束后需要处理的工作。

来描述一个定时器。

注意:一般操作系统为处理的高效率,一般是不使用for()循环的。只能使用定时器。

<定时器处理流程>

(1)定义定时器变量

(2)初始化定时器

1)init_timer()

2)设置超时函数

(3)add_timer()用来向内核注册定时器

(4)mod_timer()启动定时器

<多按键驱动的优化>

相对于一个按键的驱动程序,需要多注册一个中断,注册中断就需要在对硬件操作部分多做一个引脚的功能配置。

注意:首先要实现相应的硬件驱动程序,才能在应用程序中做相应的系统调用。

<阻塞型驱动程序的设计>

(1)阻塞必要

当一个设备无法满足用户的读写请求的时候该怎么办?例如使用函数然而以后会有数据,或者一个进程企图向一个设备写入数据的时候,然而,此时设备没有做好接受数据的准备,当上述情况发生时,驱动程序应当(缺省的)阻塞进程,使进程进入等待(睡眠)状态,知道请求得到满足。

(2)内核等待队列

在实现阻塞驱动的过程中,也需要一个类似“候车室”的地方来安排阻塞队列的休息,当唤醒条件成熟时,则可以从候车室中将进程唤醒,这个“候车室”就是等待队列。

1)定义等待队列

wait_queue_head_t my_queue

2)初始化等待队列

init_waitqueue_head(&my_queue)

3)或者定义并初始化等待队列

DECLARE_WAIT_QUEUE_HEAD(my_queue)

4)进入等待队列

wait_event(queue,condition)

当condition(布尔表达式)为真时,立即返回,否者让进程进入TASK_UNINTERRUPTIBLE 模式的睡眠,并挂载到queue参数指定的等待队列上。

wait_event_interrupttible(queue,condition)

当condition(布尔表达式)为真时,立即返回,否者让进程进入TASK_INTERRUPTIBLE的睡眠,并挂载在参数queue参数指定的队列上。

5)从等待队列中唤醒

wake_up(wait_queue_t *q)

从等待队列q 中唤醒状态为TASK_UNINTERRUPTIBLE,TASK_INTERRUPTIBLE,TASK_KILLABLE 的所有进程

wake_up_interruptible(wait_queue_t *q)

从等待队列中q中,唤醒状态为TASK_INTERRUPTIBLE的进程。

(3)阻塞驱动优化

L

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

 
 
 
 

LINUX按键驱动程序的更多相关文章

  1. 15&period;linux按键驱动程序(二)

    linux按键驱动程序 包含内容定时器延时去抖动,阻塞型设备驱动设计 一.定时器延时去抖 按键所用开关为机械弹性开关,当机械触点断开.闭合时,由于机械触点的弹性作用,开关不会马上稳定地接通或断开.因而 ...

  2. 14&period;linux按键驱动程序(一)

    按键驱动程序 本文学习主要包含按键硬件的实现.中断分层管理.按键定时器去抖.阻塞性驱动程序设计.这里面需要使用到混杂设备驱动和中断处理程序的内容. 一.创建按键混杂设备驱动模型 int key_ope ...

  3. 在Linux下的中断方式读取按键驱动程序

    // 在Linux下的中断方式读取按键驱动程序 //包含外部中断 休眠 加入poll机制 // 采用异步通知的方式 // 驱动程序发 ---> app接收 (通过kill_fasync()发送) ...

  4. linux设备驱动程序--gpio控制

    gpio驱动程序 上一章节linux设备驱动程序--创建设备节点章节主要介绍了linux字符设备驱动程序的框架,从这一章节开始我们讲解各种外设的控制,包括gpio,i2c,dma等等,既然是外设,那就 ...

  5. linux网络设备驱动程序

    4.linux网络设备驱动程序体系结构 -------------------------------------- | 数据包发送 | 数据包接收 | ----->网络协议接口层 | dev_ ...

  6. linux设备驱动程序该添加哪些头文件以及驱动常用头文件介绍(转)

    原文链接:http://blog.chinaunix.net/uid-22609852-id-3506475.html 驱动常用头文件介绍 #include <linux/***.h> 是 ...

  7. 简单linux网络驱动程序

    本文代码参考<LINUX设备驱动程序>第十七章 网络驱动程序 网络地址和虚拟主机地址为: snullnet0 192.168.0.0 snullnet1 192.168.1.0 local ...

  8. 【转】linux设备驱动程序中的阻塞机制

    原文网址:http://www.cnblogs.com/geneil/archive/2011/12/04/2275272.html 阻塞与非阻塞是设备访问的两种方式.在写阻塞与非阻塞的驱动程序时,经 ...

  9. 在Ubuntu上为Android系统编写Linux内核驱动程序(老罗学习笔记1)

    这里,我们不会为真实的硬件设备编写内核驱动程序.为了方便描述为Android系统编写内核驱动程序的过程,我们使用一个虚拟的硬件设备,这个设备只有一个4字节的寄存器,它可读可写.想起我们第一次学习程序语 ...

随机推荐

  1. php实现设计模式之 简单工厂模式

    作为对象的创建模式,用工厂方法代替new操作. 简单工厂模式是属于创建型模式,又叫做静态工厂方法模式,但不属于23种GOF设计模式之一.简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例. 工厂 ...

  2. angularjs自带过滤器

    filter: filter过滤器第一个参数若是对象: <ul> <li ng-repeat="friend in friends | filter:{'name':'Jo ...

  3. hdu 5751 Eades

    题意:对于整数序列$A[1...n]$定义$f(l, r)$为区间$[l, r]$内等于区间最大值元素的个数,定义$z[i]$为所有满足$f(l, r)=i$的区间总数.对于所有的$1 \leq i ...

  4. STL源码剖析读书笔记--第四章--序列式容器

    1.什么是序列式容器?什么是关联式容器? 书上给出的解释是,序列式容器中的元素是可序的(可理解为可以按序索引,不管这个索引是像数组一样的随机索引,还是像链表一样的顺序索引),但是元素值在索引顺序的方向 ...

  5. rnqoj-57-找啊找啊找GF-二维背包

    简单的二维背包问题. 数组t[j][k]记录时间 数组dp[j][k]记录数量 保证数量的前提下,时间最少 #include<stdio.h> #include<string.h&g ...

  6. &lbrack;LeetCode 120&rsqb; - 三角形&lpar;Triangle&rpar;

    问题 给出一个三角形,找出从顶部至底部的最小路径和.每一步你只能移动到下一行的邻接数字. 例如,给出如下三角形: [ [2], [3,4], [6,5,7], [4,1,8,3] ] 从顶部至底部的最 ...

  7. Go语言Web框架gwk介绍4

    Go语言Web框架gwk介绍 (四)   事件 gwk支持事件系统,但并没有硬编码有哪些事件,而是采用了比较松散的定义方式. 订阅事件有两种方式: 调用On函数或者OnFunc函数 func On(m ...

  8. HUST 1583 长度单位

    1583 - 长度单位 时间限制:1秒 内存限制:128兆 536 次提交 103 次通过 题目描述 我们生活中常用的长度单位有英尺.英寸和厘米,众所周知它们之间的换算关系每英寸等于3厘米,而每英尺等 ...

  9. angular中文文档的滚动条样式

    个人感觉angular中文文档的滚动条样式非常棒,于是乎就扒了下来 https://www.angular.cn/ body::-webkit-scrollbar { /* 定义了滚动条整体的样式 * ...

  10. Docker系列之Docker容器&lpar;读书笔记&rpar;

    一.介绍 容器是独立运行的一个或一组应用,以及它们的运行态环境.对应的,虚拟机可以理解为模拟运行的一整套操作系统和排在上面的应用. 二.容器 2.1 启动容器 启动容器有两种方式,一种是基于镜像新建一 ...