在学习按键外部中断过程中,发现外部中断不能注册成功,一直返回-22
使用cat /proc/interrupt查看,发现中断已经被注册了。
注意:由于OK6410的GPIO按键中断已经被飞凌自带的按键驱动注册,所以运行我们编写的按键驱动前要先去掉飞凌自带的按键驱动,方法:make menuconfig->Device Drivers->input device support->Key Boards->GPIO Buttons 去掉前面的*,即不选该项即可。重新编译内核烧录到开发板即可。
以下驱动代码测试通过:使用的是查询的方式来获取按键值,此方法简单,但是是非常消耗cpu资源,不建议使用,只当作学习使用。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <asm/ioctls.h> /* TIOCOUTQ, TIOCINQ */
#include <asm/uaccess.h>
#include <asm/io.h>
#include <mach/gpio-bank-m.h>
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("LEO");
MODULE_DESCRIPTION("This is a Button Device Test by leo");
//S3C64XX_GPMDAT
volatile unsigned long *gpmcon = NULL;
volatile unsigned long *gpmdat = NULL;
volatile unsigned long *gpncon = NULL;
volatile unsigned long *gpndat = NULL;
static int Button_write(struct file *file,const char __user *buf,size_t count,loff_t * ppos);
static int Button_open(struct inode *inode,struct file *file);
static int Button_ioctl(struct file *file, unsigned int cmd,unsigned long arg );
static int Button_read(struct file *file,const char __user *buf,size_t count,loff_t * ppos);
static struct class *Button_leo_class;
static struct class_device *Button_leo_class_dev;
static struct file_operations Button_fops={
.owner = THIS_MODULE,
.open = Button_open,
.write = Button_write,
.read = Button_read,
//.ioctl = Button_ioctl,
.unlocked_ioctl = Button_ioctl,
};
int major;
static int Button_init(void)
{
printk( "Button module by Button init\n");
int minor;
major=register_chrdev(0, "Button_leo", &Button_fops);
if(major<0)
{
printk("Button_leo Can't register major number \n");
return major;
}
Button_leo_class = class_create (THIS_MODULE, "Button_leo_class");
if(IS_ERR(Button_leo_class))
{
return PTR_ERR (Button_leo_class);
}
Button_leo_class_dev = device_create(Button_leo_class,NULL,MKDEV (major, 0),NULL,"Button_leo");//自动创建设备节点
if(unlikely (IS_ERR(Button_leo_class_dev)))
{
return PTR_ERR (Button_leo_class_dev);
}
//LED 地址映射
gpmcon = (volatile unsigned long *)ioremap (0x7F008820l, 16);
gpmdat = gpmcon + 1 ;
//Button 地址映射
gpncon = (volatile unsigned long *)ioremap (0x7F008830l, 16);
gpndat = gpncon + 1 ;
printk( "Button module by leo initializeed suessce \n");
return 0;
}
static void Button_exit(void)
{
printk( "Button module by leo exit\n");
int minor;
iounmap(gpmcon);
iounmap(gpncon);
device_unregister (Button_leo_class_dev);
class_destroy (Button_leo_class);
unregister_chrdev(major,&Button_fops);
}
static int Button_open(struct inode *inode,struct file *file)
{
printk( "Button module by leo Open\n");
/*配置为输出引脚 M0,M1 M2 M3*/
*gpmcon &=~ ((0x0f<<(0*4)) | (0x0f<<(1*4)) | (0x0f<<(2*4)) | (0x0f<<(3*4)));//*gpmcon = (volatile unsigned long *)ioremap (0x7F008820l, 16);
*gpmcon |= ((0x01<<(0*4)) | (0x01<<(1*4)) | (0x01<<(2*4)) | (0x01<<(3*4)));
*gpncon &=~ ((0x03<<(0*2)) | (0x03<<(1*2)) | (0x03<<(2*2)) | (0x03<<(3*2)) | (0x03<<(4*2) )| (0x03<<(5*2)));
return 0;
}
static int Button_write(struct file *file,const char __user *buf,size_t count,loff_t * ppos)
{
printk( "Button module by leo Write\n");
return 0;
}
static int Button_read(struct file *file,const char __user *buf,size_t count,loff_t * ppos)
{
int KeyVal;
if (count != sizeof(KeyVal))
return -EINVAL;
/* 返回6个按键的按键值 */
//KeyVal = *gpndat;
KeyVal = ~(*gpndat & (0x3f)) ;
copy_to_user (buf, &KeyVal, sizeof(KeyVal));
return 0;
}
static int Button_ioctl(struct file *file, unsigned int cmd,unsigned long arg )
{
switch (cmd)
{
case 0:
*gpmdat |= arg;
//printk("cmd = %x,arg = %x \n",cmd,arg);
break;
case 1:
*gpmdat &= ~arg;
//printk("cmd = %x,arg = %x \n",cmd,arg);
break;
default:
break;
}
}
module_init(Button_init);
module_exit(Button_exit);
测试代码:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
void print_usage(char *file)
{
printf("Usage:\n");
printf("%s <dev> <on|off>\n",file);
}
int main(int argc, char **argv)
{
int fd;
int KeyVal = 0;
fd = open ("/dev/Button_leo", O_RDWR);
if(fd < 0)
{
printf ("the device can't open !\n");
}
while(1)
{
read(fd,&KeyVal,4);
if((KeyVal&0x0000003f)!=0)
{
printf("The key value is 0x%x \n",KeyVal&0x0000003f);
ioctl(fd,1,(KeyVal&0x0000003f));
ioctl(fd,0,~(KeyVal&0x0000003f));
}
//usleep(10);
}
return 0;
}