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

《混杂设设备的描述》

<混在设备的概念>

在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)工作队列

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

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

(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.linux按键驱动程序(二)

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

  2. 14.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. 关于Unix/Linux的终端、伪终端、控制台和shell

    历史是什么:是过去传到将来的回声,是将来对过去的反映. ——雨果(法)<笑面人> 阅读本文大概需要花费你15分钟 文章导航: 计算机的发展 UNIX系统的诞生 UNIX系统的发展 终端与控 ...

  2. Spring4笔记3--Bean的装配

    Bean的装配: Bean 的装配,即 Bean 对象的创建.容器根据代码要求创建 Bean 对象后再传递给代码的过程,称为 Bean 的装配. 1. 创建Bean对象的方式: 1. 通过 getBe ...

  3. Once you eliminate all the other factors,the only thing remaining must be the truth.

    Once you eliminate all the other factors,the only thing remaining must be the truth. 一旦你排除了杂因,剩下的一定是 ...

  4. shell脚本实现分日志级别输出

    shell脚本如何优雅的记录日志信息,下面让我们一步一步,让shell脚本的日志也变得高端起来,实现如下功能 ①设定日志级别,实现可以输出不同级别的日志信息,方便调试 ②日志格式类似为:[日志级别] ...

  5. JAVA_OPTS讲解【转】

    JAVA_OPTS ,顾名思义,是用来设置JVM相关运行参数的变量. JAVA_OPTS="-server -Xms256m -Xmx512m -XX:PermSize=64M -XX:Ma ...

  6. dragstart drag dragend dragenter dragover dragleave drop

    dragstart drag dragend dragenter dragover dragleave drop   前端框架层出不穷,网页上的效果越来越绚丽,制作绚丽的效果的成本越来越低,其中有种拖 ...

  7. nginx+keepalived高可用服务器宕机解决方案

    http://blog.51cto.com/gdutcxh/2109841 https://blog.csdn.net/winsonyuan/article/details/52784988

  8. 【LOJ】#2064. 「HAOI2016」找相同字符

    题解 做后缀自动机题要一点脑洞,脑洞一开,就过了 我们显然要拿第二个串跑第一个串的后缀自动机 我们可以求出第二个串每个位置匹配到的节点,和匹配的长度L 那么我们统计一个后缀树上的根缀和,表示这样个节点 ...

  9. 【LOJ】#2105. 「TJOI2015」概率论

    题解 可以说是什么找规律好题了 但是要推生成函数,非常神奇-- 任何的一切都可以用\(n^2\)dp说起 我们所求即是 所有树的叶子总数/所有树的方案数 我们可以列出一个递推式,设\(g(x)\)为\ ...

  10. LoadRunner WebTours无法显示页面