7.阻塞型驱动设计

阻塞型驱动设计

唤醒之后按优先级执行。

对按键驱动进行阻塞型改造

改造的duokey.c:

Make会产生一下的问题还没解决,由于没有网络。差个头文件.....

明天有网络再说咯

找到了头文件,linux/sched.h又出现了奇怪的错误:

很奇怪,是重名。可我没有定义key..h,是系统的。最后改为button_init和button_exit.make通过了。

Duokey.c的代码:

#include <linux/module.h>        /* For module specific items */

#include <linux/fs.h>            /* For file operations */

#include <linux/ioport.h>        /* For io-port access */

#include <linux/io.h>            /* For inb/outb/... */

#include <linux/init.h>

#include <linux/miscdevice.h>

#include <linux/interrupt.h>

#include <linux/slab.h>

#include <linux/uaccess.h>

#include <linux/sched.h>

#define TASK_UNINTERRUPTIBLE    2

#define TASK_INTERRUPTIBLE    1

#define TASK_NORMAL        (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE)

#define GPNCON 0x7f008830

#define GPNDAT 0x7f008834

struct work_struct *work1;

struct timer_list key_timer;//定义定时器

unsigned int *gpio_data;

//全局变量,初始化为0

unsigned int key_num =0 ;

//定义等待队列

wait_queue_head_t key_q;

//read按键

ssize_t key_read(struct file *filp, char __user *buf, size_t size, loff_t *pos)

{

wait_event(key_q,key_num);

printk("<0> in kernel:key num is%d\n",key_num);

//返回内核的给用户

copy_to_user(buf,&key_num,4);

key_num=0;//清空按键

return 4;

}

void work1_func(struct work_struct *work)

{

//启动定时器 100毫秒超时=HZ/10,HZ=1秒。jiffies是系统当前时间

mod_timer(&key_timer,jiffies+HZ/10);

}

void key_timer_func(unsigned long data)

{    //定时器超时的函数需要修改,需要判断是哪个按键超时

unsigned int key_val;

//超时的时候,就要读取data

key_val=readw(gpio_data)&0x01;//读出一个按键EINT0的值。

//当他被按下,就是低电平的时候,就是被按下了。才是有效的按键

if(0==key_val)//真正按下

key_num=1;//读取按键编号

key_val=readw(gpio_data)&0x02;//读出一个按键EINT1的值。

//当他被按下,就是低电平的时候,就是被按下了。才是有效的按键

if(0==key_val)//真正按下

key_num=2;

//当有数据的时候,需要唤醒

wake_up(&key_q);

}

irqreturn_t key_int(int irq, void *dev_id)

{

//1.检测是否发生了按键中断

//2.清除已经发生的按键中断

//前面的都是硬件相关的工作,必须在中断里面执行

//下面是硬件无关的工作,我们把它提到中断以外的work1_func函数去处理。

//3.打印按键值

schedule_work(work1);

return 0;

}

void key_hw_init()

{

unsigned int *gpio_config;

unsigned short data;

gpio_config = ioremap(GPNCON,4);

data = readw(gpio_config);

data &= ~0b1111;//增加一个按键

data |= 0b1010;

writew(data,gpio_config);

gpio_data = ioremap(GPNDAT,4);

}

int key_open(struct inode *node, struct file *filp)

{

return 0;

}

struct file_operations key_fops =

{

.open = key_open,

.read = key_read,//增加了读取操作

};

struct miscdevice key_miscdevice =

{

.minor = 200,

.name = "6410key",

.fops = &key_fops,

};

static int button_init()

{

misc_register(&key_miscdevice);

//注册中断处理程序

request_irq(IRQ_EINT(0),key_int, IRQF_TRIGGER_FALLING,"6410key",0);

//增加一个按键的支持

request_irq(IRQ_EINT(1),key_int, IRQF_TRIGGER_FALLING,"6410key",0);

//硬件初始化

key_hw_init();//相应的位进行设置

//2. 创建工作

work1 = kmalloc(sizeof(struct work_struct),GFP_KERNEL);

INIT_WORK(work1, work1_func);

//定时器初始化

init_timer(&key_timer);

key_timer.function=key_timer_func;

//注册定时器

add_timer(&key_timer);

//初始化等待队列

init_waitqueue_head(&key_q);

return 0;

}

static void button_exit()

{

misc_deregister(&key_miscdevice);

}

module_init(button_init);

module_exit(button_exit);

/*优化:多一个中断,gpio也进行多按键初始化,中断产生的时候要判断是哪个按键产生的中断。*/

Make成功:

时间: 2024-10-25 13:37:43

7.阻塞型驱动设计的相关文章

阻塞型驱动设计

一. 当应用程序要对某个资源进行访问的时候,如果这个资源没有或者说被占用,这个应用程序就要进入阻塞状态,在linux系统中它会进入一个内核等待队列,等到被唤醒之后才能运行.这就是阻塞机制,它对一个驱动程序来说是很重要和必要的.二.如何使用等待队列 1.定义等待队列 wait_queue_head_t    name; 2.初始化等待队列 init_waitqueue_head    (&name);  1&2.定义+初始化等待队列 DECLARE_WAIT_QUEUE_HEAD    (n

Linux 设备驱动--- 阻塞型字符设备驱动 --- O_NONBLOCK --- 非阻塞标志【转】

转自:http://blog.csdn.net/yikai2009/article/details/8653697 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 阻塞 阻塞操作 非阻塞操作 阻塞方式-read- 实现 阻塞方式-write- 实现 非阻塞方式的读写操作 实例 --- 读阻塞的实现 实例 --- 按键驱动阻塞实现 1在 open 函数 查看看是 阻塞方式 还是 非阻塞方式 2在 read 函数中同样查看 3应用程序中 1以阻塞方式运行 2以非阻塞方式运行

国嵌内核驱动进阶班-7-3(阻塞型字符设备驱动)

为什么阻塞? 在阻塞方式下,写没有足够的空间或读时候没有数据. ※ 阻塞方式是文件读写的默认方式.没有空间或者读时没有数据返回错误. ※残留问题: 驱动程序中全局变量 在不同进程间是共享的吗? 阻塞型设备驱动程序 驱动代码: 1 #ifndef _MEMDEV_H_ 2 #define _MEMDEV_H_ 3 4 #ifndef MEMDEV_MAJOR 5 #define MEMDEV_MAJOR 0 /*预设的mem的主设备号*/ 6 #endif 7 8 #ifndef MEMDEV_N

linux设备驱动归纳总结(三):5.阻塞型IO实现【转】

本文转载自:http://blog.chinaunix.net/uid-25014876-id-60025.html linux设备驱动归纳总结(三):5.阻塞型IO实现 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 一.休眠简介: 进程休眠,简单的说就是正在运行的进程让出CPU.休眠的进程会被内核搁置在在一边,只有当内核再次把休眠的进程唤醒,进程才会会重新在CPU运行

.NET领域驱动设计—实践(穿过迷雾走向光明)

阅读目录 开篇介绍 1.1示例介绍 (OnlineExamination在线考试系统介绍) 1.2分析.建模 (对真实业务进行分析.模型化) 1.2.1 用例分析 (提取系统的所有功能需求) 1.3系统设计.建模 (技术化业务模型) 1.3.1 枚举类型的使用 (别让枚举类型成为数值型对象) 1.3.2 基础数据.业务数据 (显示实体和隐式过程) 1.3.3 模型在数据库中的主外键关联问题 (面向对象模型与关系模型的天然抗阻) 1.3.4 角色.类型 (区分类型与面向对象概念) 1.3.5 名词

EntityFramework之领域驱动设计实践

EntityFramework之领域驱动设计实践 - 前言 EntityFramework之领域驱动设计实践 (一):从DataTable到EntityObject EntityFramework之领域驱动设计实践 (二):分层架构 EntityFramework之领域驱动设计实践 (三):案例:一个简易的销售系统 EntityFramework之领域驱动设计实践 (四):存储过程 - 领域驱动的反模式 EntityFramework之领域驱动设计实践 (五):聚合 EntityFramewor

Hibernate(5)—— 联合主键 、一对一关联关系映射(xml和注解) 和 领域驱动设计

俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及的知识点总结如下: One to One 映射关系 一对一单向外键(XML/Annotation) 一对一双向外键关联(XML/Annotation) 联合主键 一对一单向外键联合主键(Xml/Annotation) 一对一组件关联(XML/Annotation) 理解组件 领域驱动设计——自动生成数据库脚本 一对一关系的小结 一些出错问题的总结 自动生成数据库脚本 一般在项目开发过程中,我们的习惯是先建好数据库和表,然后在进

AC620教程 第十五节 8位7段数码管驱动设计与验证

本章导读 电子系统中常用的显示设备有数码管.LCD液晶以及VGA显示器等.其中数码管又可分为段式显示(7段.米字型等)以及点阵显示(8*8.16*16等),LCD液晶的应用可以分为字符式液晶(1602.12864等)以及真彩液晶屏,VGA显示器一般是现在的电脑显示器.芯航线开发板对以上三种设备均提供了硬件接口. 本章将实现FPGA驱动数码管动态显示并提取出实现的电路结构,从电路结构入手编写代码,仿真对设计进行验证.最终板级调试时使用In system sources and probes edi

平台总线驱动设计

平台总线驱动设计1.平台总线概述(总线驱动中最为重要的一个总线)平台总线(Platform bus)是linux2.6内核加入的一种虚拟总线,其 优势在于采用了总线的模型对设备与驱动进行了管理,这总线的模 型对设备与驱动进行了管理,这样提高了程序的可移植性.通过平台总线机制开发设备驱动的流程:定义platform_device->注册platform_device->定义 platform_drivre->注册platform_driver 屏台总线驱动与设备匹配机制:内核代 码/drv