linux设备驱动(3)字符驱动 -按键(查询法)

本文描述查询法。 所谓查询法,就是在应用程序里面执行

while (1)
	{
		read(fd, key_vals, sizeof(key_vals));
        ...
	}

加载驱动并在后台执行应用程序时, 通过top可以看到CPU利用率,该应用进程占用99%。

先看应用程序

int main(int argc, char **argv)
{
	int fd;
	unsigned char key_vals[6];
	int cnt = 0;
	
	fd = open("/dev/buttons", O_RDWR);
	if (fd < 0)
	{
		printf("can't open!\n");
	}

	while (1)
	{
		read(fd, key_vals, sizeof(key_vals));
		if (!key_vals[0] || !key_vals[1] || !key_vals[2] || !key_vals[3] || !key_vals[4] || !key_vals[5])
		{
			printf("%04d key pressed: %d %d %d %d %d %d\n", cnt++, key_vals[0], key_vals[1], key_vals[2], 
				key_vals[3], key_vals[4], key_vals[5]);
		}
	}
	
	return 0;
}

对于应用程序, 其框架如下

①实现file_operation里面的open, read等函数

static struct file_operations buttons_fops = 
{
	.owner        = THIS_MODULE,
	.open         = buttons_open,
	.read         = buttons_read,
};

②注册(register_chrdev)

major = register_chrdev(0, "buttons_drv", &buttons_fops);

③入口(module_init)

static int buttons_init(void)
{
	major = register_chrdev(0, "buttons_drv", &buttons_fops);

	buttons_class = class_create(THIS_MODULE, "buttons_drv");
	buttons_class_dev = class_device_create(buttons_class, NULL, MKDEV(major, 0),
		            NULL, "buttons");

	gpgcon = (volatile unsigned int*)ioremap(GPG_BASE, 4);
	gpgdat = gpgcon + 1;
	
	return 0;
}

④出口(module_exit)

static void buttons_exit(void)
{
	iounmap(gpgcon);
	
	class_device_unregister(buttons_class_dev);
	class_destroy(buttons_class);

	unregister_chrdev(major, "buttons_drv");
}

⑤硬件相关设置(地址映射)

static int buttons_open (struct inode *inode, struct file *file)
{
	// 设置引脚位输入引脚
	*gpgcon &= ~((0x3 << (0 * 2)) | (0x3 << (3 * 2)) | (0x3 << (5 * 2)) | (0x3 << (6 * 2)) |\
				(0x3 << (7 * 2))| (0x3 << (11 * 2)));
	return 0;
}

完整程序如下:

/*
*  kernel : linux-2.6.22.6
*  gcc     : arm-linux-gcc -3.4.5
*
*   desc   : 这里使用轮询的方式,缺点很明显, 占CPU资源
*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>

#include <linux/device.h>    /* class_device ... */


/**
*  buttons of mini2440, 低电平触发
*    K1     GPG0    EINT8
*    K2     GPG3    EINT11
*    K3     GPG5    EINT13
*    K4     GPG6    EINT14
*    K5     GPG7    EINT15
*    K6     GPG11   EINT19
*/

static int major ;

static struct class *buttons_class;
static struct class_device *buttons_class_dev;

#define GPG_BASE 			0x56000060
static volatile unsigned int *gpgcon = NULL;
static volatile unsigned int *gpgdat = NULL;


static int buttons_open (struct inode *inode, struct file *file)
{
	// 设置引脚位输入引脚
	*gpgcon &= ~((0x3 << (0 * 2)) | (0x3 << (3 * 2)) | (0x3 << (5 * 2)) | (0x3 << (6 * 2)) |\
				(0x3 << (7 * 2))| (0x3 << (11 * 2)));
	return 0;
}

static int buttons_read (struct file *file, char __user *usrbuf, size_t len , loff_t *offset)
{
	unsigned char val[6] = {0};
	int regval = 0;

	regval = *gpgdat;
	val[0] = (regval & (1 << 0)) ? 1: 0;
	val[1] = (regval & (1 << 3)) ? 1: 0;
	val[2] = (regval & (1 << 5)) ? 1: 0;
	val[3] = (regval & (1 << 6)) ? 1: 0;
	val[4] = (regval & (1 << 7)) ? 1: 0;
	val[5] = (regval & (1 << 11)) ? 1: 0;

	if(copy_to_user(usrbuf, val, sizeof(val)))
		return -EFAULT;
	return sizeof(val);
}


static struct file_operations buttons_fops = 
{
	.owner        = THIS_MODULE,
	.open         = buttons_open,
	.read         = buttons_read,
};

static int buttons_init(void)
{
	major = register_chrdev(0, "buttons_drv", &buttons_fops);

	buttons_class = class_create(THIS_MODULE, "buttons_drv");
	buttons_class_dev = class_device_create(buttons_class, NULL, MKDEV(major, 0),
		            NULL, "buttons");

	gpgcon = (volatile unsigned int*)ioremap(GPG_BASE, 4);
	gpgdat = gpgcon + 1;
	
	return 0;
}

static void buttons_exit(void)
{
	iounmap(gpgcon);
	
	class_device_unregister(buttons_class_dev);
	class_destroy(buttons_class);

	unregister_chrdev(major, "buttons_drv");
}

module_init(buttons_init);
module_exit(buttons_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("[email protected]");
MODULE_DESCRIPTION("buttons driver for mini2440");

猜你喜欢

转载自blog.csdn.net/qq_21353001/article/details/83747188