阻塞型驱动设计
唤醒之后按优先级执行。
对按键驱动进行阻塞型改造
改造的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成功: