JZ2440笔记:字符设备驱动程序之中断方式的按键驱动(等快递等到睡着)

在上回代码上修改为third_drv.c和 thirddrvtest.c。

(1)third_drv.c中增加中断注册注销(设置,让门卫老大爷帮忙提醒快递已到)

static irqreturn_t buttons_irq(int irq,void *dev_id)
{
        printk("irq = %d\n",irq);
        return IRQ_HANDLED;
}


static int third_drv_open(struct inode *inode,struct file *file)
{
        request_irq(IRQ_EINT0, buttons_irq,IRQT_BOTHEDGE,"S2",1);
        request_irq(IRQ_EINT2, buttons_irq,IRQT_BOTHEDGE,"S3",1);
        request_irq(IRQ_EINT11,buttons_irq,IRQT_BOTHEDGE,"S4",1);
        request_irq(IRQ_EINT19,buttons_irq,IRQT_BOTHEDGE,"S5",1);
        return 0;
}

static int third_drv_close(struct inode *inode,struct file *file)
{
        free_irq(IRQ_EINT0, 1);
        free_irq(IRQ_EINT2, 1);
        free_irq(IRQ_EINT11,1);
        free_irq(IRQ_EINT19,1);
        return 0;
}


static struct file_operations third_drv_fops = {
        .owner = THIS_MODULE,
        .open = third_drv_open,
        .read = third_drv_read,
        .release = third_drv_close,
};

make出现error: unknown type name 'irqreturn_t',增加头文件#include <linux/irq.h>

再次make出现error: implicit declaration of function 'request_irq' [-Werror=implicit-function-declaration],增加头文件#include <linux/interrupt.h>

再次make出现error: 'IRQT_BOTHEDGE' undeclared (first use in this function),将IRQT_BOTHEDGE换成IRQ_TYPE_EDGE_BOTH

再次make出现warning: passing argument 5 of 'request_irq' makes pointer from integer without a cast [-Wint-conversion],根本就不管,通过。

# exec 5</dev/buttons

# ps
PID   USER     TIME  COMMAND
  872 0         0:00 -/bin/sh

 # ls -l /proc/872/fd
lr-x------    1 0        0               64 Jan  1 19:37 5 -> /dev/buttons


# cat /proc/interrupts
 16:          0  s3c-ext0   0 Edge      S2
 18:          0  s3c-ext0   2 Edge      S3
 59:          0   s3c-ext  11 Edge      S4
 67:          0   s3c-ext  19 Edge      S5

# exec 5<&-

# exec 5</dev/buttons
# irq = 16
irq = 16
irq = 16
irq = 16

(2)third_drv.c中增加读pin值(阻塞读,等快递等得睡着了,没门卫老大爷给的通知就继续睡,通知到了才去拿)

#include <asm/mach/map.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/interrupt.h>


static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
static volatile int ev_press = 0;

static unsigned char key_val;
struct pin_desc{
	unsigned int pin;
	unsigned int key_val;
};
struct pin_desc pin_desc[4]={
	{S3C2410_GPF(0), 0X01},
	{S3C2410_GPF(2), 0X02},
	{S3C2410_GPG(3), 0X03},
	{S3C2410_GPG(11),0X04},
};  

static irqreturn_t buttons_irq(int irq,void *dev_id)
{
	unsigned int pinval;
	struct pin_desc *pindesc = (struct pin_desc *)dev_id;
	pinval = s3c2410_gpio_getpin(pindesc->pin);
	if(pinval)
	{
		key_val = 0x80|pindesc->key_val;
	}
	else
	{
		key_val = pindesc->key_val;
	}
	ev_press = 1;
	wake_up_interruptible(&button_waitq);
	return IRQ_HANDLED;
}


static int third_drv_open(struct inode *inode,struct file *file)
{
	request_irq(IRQ_EINT0, buttons_irq,IRQ_TYPE_EDGE_BOTH,"S2",&pin_desc[0]);
	request_irq(IRQ_EINT2, buttons_irq,IRQ_TYPE_EDGE_BOTH,"S3",&pin_desc[1]);
	request_irq(IRQ_EINT11,buttons_irq,IRQ_TYPE_EDGE_BOTH,"S4",&pin_desc[2]);
	request_irq(IRQ_EINT19,buttons_irq,IRQ_TYPE_EDGE_BOTH,"S5",&pin_desc[3]);
	return 0;
}

static ssize_t third_drv_read(struct file *file,char __user *buf,size_t len,loff_t *ppos)
{
	if(len!=1)
		return -EINVAL;
	wait_event_interruptible(button_waitq,ev_press);
	copy_to_user(buf,key_val,1);
	ev_press = 0;
	return 1;
}


static int third_drv_close(struct inode *inode,struct file *file)
{
        free_irq(IRQ_EINT0, &pin_desc[0]);
        free_irq(IRQ_EINT2, &pin_desc[1]);
        free_irq(IRQ_EINT11,&pin_desc[2]);
        free_irq(IRQ_EINT19,&pin_desc[3]);
        return 0;
}


static struct file_operations third_drv_fops = {
	.owner = THIS_MODULE,
	.open = third_drv_open,
	.read = third_drv_read,
	.release = third_drv_close,
};

int major;
static struct class *thirddrv_class;
static struct device *thirddrv_device;
static int third_drv_init(void)
{
	major = register_chrdev(0,"third_drv",&third_drv_fops);
	thirddrv_class = class_create(THIS_MODULE,"thirddrv");
	thirddrv_device = device_create(thirddrv_class,NULL,MKDEV(major,0),NULL,"buttons");

	printk("third_drv_init\n");
	return 0;
}

static void third_drv_exit(void)
{
	unregister_chrdev(major,"third_drv");
	device_destroy(thirddrv_class,MKDEV(major,0));
	class_destroy(thirddrv_class);
	printk("third_drv_exit\n");
}

module_init(third_drv_init); 
module_exit(third_drv_exit);

MODULE_LICENSE("GPL");

make出现error: implicit declaration of function 'S3C2410_GPF' ,则添加头文件#include <mach/gpio-samsung.h>

再次make出现error: implicit declaration of function 's3c2410_gpio_getpin',则将s3c2410_gpio_getpin() 换成 gpio_get_value()

再次make出现warning: passing argument 2 of 'copy_to_user' makes pointer from integer without a cast,则copy_to_user(buf,key_val,1);应该为copy_to_user(buf,&key_val,1);编译通过。

vi thirddrvtest.c

#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc,char *argv[])
{
        int fd;
        unsigned char key_value;

        fd = open("/dev/buttons",O_RDWR);
        if(fd<0)
        {
                printf("can't open /dev/buttons!\n");
                return 0;
        }

        while(1)
        {
                read(fd,&key_value,1);
                printf("key_value = 0x%x\n",key_value);
        }
        return 0;
}

编译通过。

测试驱动:# rmmod third_drv.
rmmod: remove 'third_drv': Resource temporarily unavailable

# exec 5<&-
/mnt/5 # rmmod third_drv.ko
third_drv_exit

 # cat /proc/interrupts
           CPU0
 16:         18  s3c-ext0   0 Edge      S2
 18:          1  s3c-ext0   2 Edge      S3
 59:          1   s3c-ext  11 Edge      S4
 67:          0   s3c-ext  19 Edge      S5
# 按键按下断开
key_value = 0x1
key_value = 0x81
key_value = 0x1
key_value = 0x81
 

(3)third_drv.c中增加poll(不能一直睡着了啊,定个10分钟闹钟醒来看看撒)

static int third_drv_poll(struct file *file, poll_table *wait)
{
	int mask = 0;

	poll_wait(file, &button_waitq, wait);
	if (ev_press)
		mask |= POLLIN | POLLRDNORM;
	return mask;
}



static struct file_operations third_drv_fops = {
	.owner = THIS_MODULE,
	.open = third_drv_open,
	.read = third_drv_read,
	.release = third_drv_close,
	.poll = third_drv_poll,

make出现error: unknown type name 'poll_table',则添加头文件#include <linux/poll.h>

再次make出现error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
  .poll = third_drv_poll,
          ^
/home/embedfire/linux/nfs/6/third_drv.c:97:10: note: (near initialization for 'third_drv_fops.poll'),将static int third_drv_poll(struct file *file, poll_table *wait)替换为__poll_t third_drv_poll (struct file *, struct poll_table_struct *)编译通过。

vi thirddrvtest.c

#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <poll.h>

int main(int argc,char *argv[])
{
        int fd;
        unsigned char key_value;
        int ret;
        struct pollfd fds[1];

        fd = open("/dev/buttons",O_RDWR);
        if(fd<0)
        {
                printf("can't open /dev/buttons!\n");
                return 0;
        }

        fds[0].fd = fd;
        fds[0].events = POLLIN;

        while(1)
        {
                ret = poll(fds, 1, 5000);
                if(ret==0)
                {
                        printf("time out!\n");
                }
                else
                {
                        read(fd,&key_value,1);
                        printf("key_value = 0x%x\n",key_value);
                }
        }
        return 0;
}

测试驱动:# insmod third_drv.ko
third_drv: loading out-of-tree module taints kernel.
third_drv_init

# ./thirddrvtest &
# time out!
time out!
time out!
time out!
time out!
time out!
time out!
key_value = 0x1
key_value = 0x81
 

#top

Mem: 10456K used, 47540K free, 0K shrd, 0K buff, 3492K cached
CPU:  0.1% usr  0.1% sys  0.0% nic 99.0% idle  0.0% io  0.0% irq  0.5% sirq
Load average: 0.05 0.04 0.00 1/30 887
  PID  PPID USER     STAT   VSZ %VSZ CPU %CPU COMMAND
  887   873 0        R     3624  6.2   0  0.5 top
  886   873 0        S     1764  3.0   0  0.0 ./thirddrvtest
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值