OK6410 linux设备驱动:Button驱动-轮询的形式

在学习按键外部中断过程中,发现外部中断不能注册成功,一直返回-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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值