3519AGPIO按键驱动及测试程序

3519A文档 外围设备驱动 操作指南.pdf 中介绍了linux下内核态GPIO操作的方法,修改完善后得到下边的代码:

#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
// 00 01 02 04 06 07 08 0510 0903 900901
// vup vdow up dow lef rig ok menu back PTT
unsigned int gpio_key_chip []={ 3, 3, 1, 1, 1, 1, 4, 3, 3, 1};
unsigned int gpio_key_offset[]={ 6, 7, 0, 1, 2, 3, 4, 4, 5, 7};
unsigned int gpio_key_num []={ 30, 31, 8, 9, 10, 11, 36, 28, 29, 15};
unsigned int gpio_irq_num []={ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
static DECLARE_WAIT_QUEUE_HEAD(gpio_queue);
static volatile int gpio_data = 0;
static int gpio_dev_id = 0;
spinlock_t irq_lock;

static irqreturn_t gpio_key_irq(int irq,void * dev_id){
    int i = 0;
    int value = -1;
    for(i = 0;i < sizeof(gpio_irq_num) / sizeof(int);++i){
        if(gpio_irq_num[i] == irq && irq != -1){
            value = gpio_get_value(gpio_key_num[i]);
            if(value != -1){
                gpio_data = gpio_key_num[i] + (value == 0 ? 0x1000 : 0x2000);
            }
            break;
        }
    }
    printk("func[%s %d] irq:%d value:%d data:%x\n",__FUNCTION__,__LINE__,irq,value,gpio_data);
    wake_up_interruptible(&gpio_queue);
    return IRQ_HANDLED;
}

static int gpio_key_read(struct file * file,char __user * buff,size_t count,loff_t * offp){
    int size = -1;
    int data = gpio_data;
    if(!gpio_data){
        if(file->f_flags & O_NONBLOCK){
            return -EAGAIN;
        }else{
            wait_event_interruptible(gpio_queue,gpio_data);
        }
    }
    if(copy_to_user(buff,&data,sizeof(gpio_data)) == 0){
        size = sizeof(gpio_data);
    }
    printk("func[%s %d] size:%d data:%x\n",__FUNCTION__,__LINE__,size,gpio_data);
    gpio_data = 0;
    return size;
}

static unsigned int gpio_key_poll(struct file * file,struct poll_table_struct * wait){
    unsigned int mask = 0;
    poll_wait(file,&gpio_queue,wait);
    if(gpio_data){
        mask |= POLLIN | POLLRDNORM;
    }
    return mask;
}

static int gpio_key_open(struct inode * inode,struct file * file){
    int i = 0;
    int irq_num;
    printk("\nfunc[%s %d]\n",__FUNCTION__,__LINE__);
    for(i = 0;i < sizeof(gpio_key_num) / sizeof(int);++i){
        if(gpio_request(gpio_key_num[i],NULL)){
            printk("func[%s %d] request gpio%d_%d failed.\n",__FUNCTION__,__LINE__,gpio_key_chip[i],gpio_key_offset[i]);
            continue;
        }
        if(gpio_direction_input(gpio_key_num[i])){
            printk("func[%s %d] gpio%d_%d set_input failed.\n",__FUNCTION__,__LINE__,gpio_key_chip[i],gpio_key_offset[i]);
            gpio_free(gpio_key_num[i]);
            continue;
        }
        irq_num = gpio_to_irq(gpio_key_num[i]);
        if(request_irq(irq_num,gpio_key_irq,IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_SHARED,"gpio_key_irq",&gpio_dev_id)){
            printk("func[%s %d] gpio%d_%d request_irq:%d failed.\n",__FUNCTION__,__LINE__,gpio_key_chip[i],gpio_key_offset[i],irq_num);
            gpio_free(gpio_key_num[i]);
            continue;
        }
        gpio_irq_num[i] = irq_num;
        printk("func[%s %d] gpio%d_%d request_irq:%d success.\n",__FUNCTION__,__LINE__,gpio_key_chip[i],gpio_key_offset[i],irq_num);
    }
    return 0;
}

static int gpio_key_close(struct inode * inode,struct file * file){
    int i = 0;
    for(i = 0;i < sizeof(gpio_key_num) / sizeof(int);++i){
        unsigned long flags = 0;
        spin_lock_irqsave(&irq_lock,flags);
        free_irq(gpio_to_irq(gpio_key_num[i]),&gpio_dev_id);
        spin_unlock_irqrestore(&irq_lock,flags);
        printk("func[%s %d] free gpio%d_%d\n",__FUNCTION__,__LINE__,gpio_key_chip[i],gpio_key_offset[i]);

        gpio_free(gpio_key_num[i]);
        gpio_irq_num[i] = -1;
    }
    printk("func[%s %d]\n\n",__FUNCTION__,__LINE__);

    return 0;
}

static struct file_operations dev_fops = {
    .owner = THIS_MODULE,
    .open = gpio_key_open,
    .release = gpio_key_close,
    .read = gpio_key_read,
    .poll = gpio_key_poll
};

static struct miscdevice dev_misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = "gpio_irq",
    .fops = &dev_fops
};

static int __init gpio_key_init(void){
    if(misc_register(&dev_misc)){
        printk("func[%s %d] init failed.\n",__FUNCTION__,__LINE__);
        return -1;
    }
    printk("func[%s %d] init success.\n",__FUNCTION__,__LINE__);
    spin_lock_init(&irq_lock);
    return 0;
}

static void __exit gpio_key_exit(void){
    misc_deregister(&dev_misc);
    printk("func[%s %d]\n",__FUNCTION__,__LINE__);

}

module_init(gpio_key_init);
module_exit(gpio_key_exit);

MODULE_DESCRIPTION("gpio key driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("yang");

Makefile

obj-m := button.o
export ARCH=arm
export CROSS_COMPILE=arm-himix200-linux-
###KERDIR := /home/work/Hisi/Hi3536C/Hi3536CV100_SDK_V2.0.4.0/package/osdrv/opensource/kernel/linux-3.18.y
###KERDIR := /home/work/Hisi/Hi3536CV100_SDK_V2.0.4.0/osdrv/opensource/kernel/linux-3.18.y
KERDIR := /home/work/Hisi/Hi3519AV100_SDK_V2.0.1.0/osdrv/opensource/kernel/linux-4.9.y-smp/
CURDIR := $(shell pwd)
all:
        make -C $(KERDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-himix200-linux-
clean:
        rm -f *.ko *.o *.mod.o *.mod.c *.symvers

测试程序:使用poll异步读写驱动映射文件

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
int main(int argc, char *argv[]){
    char buf[32] = {0};
    int code[] = { 30+0x1000, 31+0x1000, 8+0x1000, 9+0x1000, 10+0x1000,
                         11+0x1000, 36+0x1000, 28+0x1000, 29+0x1000, 15+0x1000,
                         30+0x2000, 31+0x2000, 8+0x2000, 9+0x2000, 10+0x2000,
                         11+0x2000, 36+0x2000, 28+0x2000, 29+0x2000, 15+0x2000};
    char * key[] = {"vup press","vdown press","up press","down press","left press",
                    "right press","ok press","menu press","back press","PTT press",
                    "vup release","vdown release","up release","down release","left release",
                    "right release","ok release","menu release","back release","PTT release"};
    struct pollfd * pollfd = (struct pollfd *)malloc(sizeof(struct pollfd));
    if(pollfd){
        pollfd->fd = open("/dev/gpio_irq",O_RDONLY);
        if(pollfd->fd >= 0){
            pollfd->events = POLLIN;
            while(1){
                if(poll(pollfd,1,-1) > 0 && pollfd->revents & POLLIN){
                    int count = read(pollfd->fd,buf,32);
                    if(count == sizeof(int)){
                        int i = 0;
                        for(i = 0;i < sizeof(code) / sizeof(int);++i){
                            if(code[i] == *(int *)buf){
                                break;
                            }
                        }
                        if(i < sizeof(code) / sizeof(int)){
                            printf("key %s ,buf:%x\n",key[i],*(int *)buf);
                        }else{
                            printf("key not find, count:%d buf:%x\n",count,*(int *)buf);
                        }
                    }else{
                        printf("read count:%d buf:%x size > 4\n",count,buf);
                    }
                }
            }
            close(pollfd->fd);
        }else{
            printf("pollfd open failed.fd:%d\n",pollfd->fd);
        }
        free(pollfd);
    }else{
        printf("pollfd malloc failed.\n");
    }
    printf("exit.\n");
    return 0;
}

使用gcc交叉编译即可:

arm-himix200-linux-gcc test.c -o test
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值