OK6410总共有6个按键,按键分别接在GPN0~GPN5,原理图上根本没有这么说,原理图上说的是KEYINT!~KEYINT6,很明显这里是接在中断引脚上的,直接查询S3C6410的中断引脚就可以知道这个6个按键的接法,一下是用查询方法实现的按键驱动:
- #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 <mach/regs-gpio.h>
- #include <mach/hardware.h>
- #include <linux/device.h>//新版内核
- static struct class *key_drv_class;
- static struct class_device *key_class_dev;
- volatile unsigned long *gpncon=NULL;
- volatile unsigned long *gpndat=NULL;
- static int key_drv_open(struct inode * inode, struct file * file)
- {
- *gpncon &=~((0x3<<0)|(0x3<<2)|(0x3<<4)|(0x3<<6));
- return 0;
- }
- static ssize_t key_drv_write(struct inode * file, const char __user *buf, size_t count, loff_t *ppos)
- {
- return 0;
- }
- ssize_t key_drv_read (struct file *file, char __user *buf, size_t size, loff_t *ppos)
- {
- //返回四个引脚的电平
- unsigned char key_val[4];
- int regval;
- if(size != sizeof(key_val))
- return -EINVAL;
- regval=*gpndat;
- key_val[0] = (regval & (1<<0))?1:0;
- key_val[1] = (regval & (1<<1))?1:0;
- key_val[2] = (regval & (1<<2))?1:0;
- key_val[3] = (regval & (1<<3))?1:0;
- copy_to_user(buf,key_val,sizeof(key_val));
- return sizeof(key_val);
- }
- static struct file_operations key_drv_openration ={
- .owner = THIS_MODULE,
- .open = key_drv_open,
- .write =key_drv_write,
- .read=key_drv_read,
- };
- int major;
- static int key_drv_init(void)
- {
- major=register_chrdev(0,"key_drv",&key_drv_openration);
- key_drv_class = class_create(THIS_MODULE, "key_drv");
- //自动创建设备节点
- /* 新版的内核不能用class_device_create 要用device_create*/
- key_class_dev = device_create(key_drv_class, NULL, MKDEV(major, 0), NULL, "key"); /* /dev/xyz */
- gpncon = (volatile unsigned long*)ioremap(0x7F008830,16);
- gpndat=gpncon+1;//指针的操作是按照指针指向的长度为单位?
- /*本例中使用的是unsigned long类型刚好是4个字节*/
- return 0;
- }
- static void key_drv_exit(void)
- {
- unregister_chrdev(major,"key_drv");
- device_unregister(key_class_dev);
- class_destroy(key_drv_class);
- iounmap(gpncon);
- return 0;
- }
- module_init(key_drv_init);
- module_exit(key_drv_exit);
- MODULE_LICENSE("GPL");
一下是测试程序:
- #include<sys/types.h>
- #include<sys/stat.h>
- #include<fcntl.h>
- #include<stdio.h>
- int main(int argc,char **argv)
- {
- int fd;
- unsigned char key_val[4];
- int cnt;
- fd=open("/dev/key",O_RDWR);
- if(fd < 0)
- printf("can not open!!!\n");
- while(1)
- {
- read(fd,key_val,sizeof(key_val));
- if(!key_val[0]||!key_val[1]||!key_val[2]||!key_val[3])
- {
- printf("%04d key pressed :%d %d %d %d\n\n",cnt++,key_val[0],key_val[1],key_val[2],key_val[3]);
- }
- }
- return 0;
- }
一下是测试运行结果:
1452 key pressed :1 0 1 1
1453 key pressed :1 0 1 1
1454 key pressed :1 0 1 1
1455 key pressed :1 0 1 1
1456 key pressed :1 0 1 1
1457 key pressed :1 0 1 1
1458 key pressed :1 0 1 1
1459 key pressed :1 0 1 1
1460 key pressed :1 0 1 1
1461 key pressed :1 0 1 1
让测试程序后台运行,查看CPU的运行状态:
Mem: 7968K used, 246548K free, 0K shrd, 0K buff, 2096K cached
CPU: 9.1% usr 90.8% sys 0.0% nic 0.0% idle 0.0% io 0.0% irq 0.0% sirq
Load average: 0.34 0.13 0.07 2/25 984
PID PPID USER STAT VSZ %VSZ CPU %CPU COMMAND
983 969 root R 792 0.3 0 99.6 ./main
984 969 root R 2268 0.8 0 0.2 top
969 1 root S 2268 0.8 0 0.0 -/bin/sh
1 0 root S 2264 0.8 0 0.0 init
4 2 root SW 0 0.0 0 0.0 [kworker/0:0]
5 2 root SW 0 0.0 0 0.0 [kworker/u:0]
可以看出按键 程序的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 <mach/regs-gpio.h>
- #include <mach/hardware.h>
- #include <linux/interrupt.h>
- #include <linux/sched.h>
- #include <linux/device.h>//新版内核
- #include <linux/gpio.h>
- #include <plat/gpio-cfg.h>
- static struct class *key_irq_class;
- static struct class_device *key_class_irq;
- volatile unsigned long *gpncon=NULL;
- volatile unsigned long *gpndat=NULL;
- static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
- /* 中断事件标志, 中断服务程序将它置1,third_drv_read将它清0 */
- static volatile int ev_press = 0;
- struct key_desc{
- unsigned int pin;
- unsigned int key_val;
- };
- /*键值:按下时,0x01,0x02,0x03,0x04,0x05,0x06*/
- /*键值:松开时,0x81,0x82,0x83,0x84,0x85,0x86*/
- static unsigned char key_num;
- struct key_desc keys_desc[6]={
- {1,0x01},
- {2,0x02},
- {3,0x03},
- {4,0x04},
- {5,0x05},
- {6,0x06},
- };
- static irqreturn_t key_irq(int irq, void *dev_id)
- {
- struct key_desc *pin=(struct key_desc*)dev_id;
- unsigned int pinval;
- pinval=gpio_get_value(S3C64XX_GPN(pin->pin));
- if(pinval)
- {
- key_num=0x80|pin->key_val;
- }
- else
- {
- key_num=pin->key_val;
- }
- //printk("*********************");
- //printk("key_num= %x\n",key_num);
- //printk("*********************");
- //ev_press=1;/*表示中断发生了*/
- wake_up_interruptible(&button_waitq);/*唤醒休眠的进程*/
- return IRQ_HANDLED;
- }
- static int key_drv_open(struct inode * inode, struct file * file)
- {
- request_irq(IRQ_EINT(1),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S1",&keys_desc[0]);
- request_irq(IRQ_EINT(2),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S2",&keys_desc[1]);
- request_irq(IRQ_EINT(3),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S3",&keys_desc[2]);
- request_irq(IRQ_EINT(4),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S4",&keys_desc[3]);
- request_irq(IRQ_EINT(5),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S5",&keys_desc[4]);
- request_irq(IRQ_EINT(6),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S6",&keys_desc[5]);
- return 0;
- }
- static ssize_t key_drv_write(struct inode * file, const char __user *buf, size_t count, loff_t *ppos)
- {
- return 0;
- }
- ssize_t key_drv_read (struct file *file, char __user *buf, size_t size, loff_t *ppos)
- {
- //返回四个引脚的电平
- if(size != 1)
- return -EINVAL;
- /*如果没有按键动作发生就休眠*/
- wait_event_interruptible(button_waitq, ev_press);
- /*如果有按键动作,返回键值*/
- copy_to_user(buf,&key_num,1);
- ev_press=0;
- return 1;
- }
- int key_drv_release(struct inode * inode, struct file * file)
- {
- free_irq(IRQ_EINT(1),&keys_desc[0]);
- free_irq(IRQ_EINT(2),&keys_desc[1]);
- free_irq(IRQ_EINT(3),&keys_desc[2]);
- free_irq(IRQ_EINT(4),&keys_desc[3]);
- free_irq(IRQ_EINT(5),&keys_desc[4]);
- free_irq(IRQ_EINT(6),&keys_desc[5]);
- return 0;
- }
- static struct file_operations key_drv_openration ={
- .owner = THIS_MODULE,
- .open = key_drv_open,
- .write =key_drv_write,
- .read=key_drv_read,
- .release=key_drv_release,
- };
- int major;
- static int key_drv_init(void)
- {
- major=register_chrdev(0,"key_irq",&key_drv_openration);
- key_irq_class = class_create(THIS_MODULE, "key_irq");
- //自动创建设备节点
- /* 新版的内核不能用class_device_create 要用device_create*/
- key_class_irq = device_create(key_irq_class, NULL, MKDEV(major, 0), NULL, "key"); /* /dev/xyz */
- gpncon = (volatile unsigned long*)ioremap(0x7F008830,16);
- gpndat=gpncon+1;//指针的操作是按照指针指向的长度为单位?
- /*本例中使用的是unsigned long类型刚好是4个字节*/
- return 0;
- }
- static void key_drv_exit(void)
- {
- unregister_chrdev(major,"key_irq");
- device_unregister(key_class_irq);
- class_destroy(key_irq_class);
- iounmap(gpncon);
- return 0;
- }
- module_init(key_drv_init);
- module_exit(key_drv_exit);
- MODULE_LICENSE("GPL");
测试程序:
- #include<sys/types.h>
- #include<sys/stat.h>
- #include<fcntl.h>
- #include<stdio.h>
- int main(int argc,char **argv)
- {
- int fd;
- unsigned char key_val;
- int cnt;
- fd=open("/dev/key",O_RDWR);
- if(fd < 0)
- {
- printf("can not open!!!\n");
- return 0;
- }
- while(1)
- {
- read(fd,&key_val,1);
- printf("key_val = 0x%x\n", key_val);
- }
- return 0;
- }
[root@Pillar /driver/key/key_IRQ]#./main &
[root@Pillar /driver/key/key_IRQ]#*********************key_num= 81
*********************key_val = 0x81
*********************key_num= 82
*********************key_val = 0x82
*********************key_num= 3
******************************************key_num= 3
******************************************key_num= 83
*********************key_val = 0x3