OpenVINOTM,给你看得见的未来!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 开源硬件 » 芯灵思SinlinxA33开发板Linux中断编程4-最终代码(1)

共2条 1/1 1 跳转至

芯灵思SinlinxA33开发板Linux中断编程4-最终代码(1)

助工
2019-02-13 16:12:16    评分

按键驱动代码:

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <asm/uaccess.h>
#include <linux/delay.h> 
#include <linux/sched.h>  
#define DEVICE_BUTTON  "mybtn"
#define BTN_MAJOR   255
static char keybuf[] = {"0"};
static struct miscdevice misc = {
    .minor = BTN_MAJOR, 
    .name  = DEVICE_BUTTON,
};

irqreturn_t key_isr(int irq, void* dev)
{
    int btn = 0;
	//读取按键状态
    btn= !gpio_get_value(GPIOL(14));	
    printk("key %s\r\n",  btn ? "down" : "up");
	//把按键状态更新到对应的按缓冲中
	keybuf = “0” + btn;
    return IRQ_HANDLED;
}

static ssize_t btn_read  (struct file *flp, char __user *buff, size_t count, loff_t * off)
{
    int ret ;
	if(!count) {
         return 0;
    }
    ret = copy_to_user(buff, keybuf, count);
    if(ret) {
        printk("error:copy_to_user\r\n");
        return -EFAULT;
    }
    return count;
}

static const struct file_operations dev_fops = {
    .read   =   btn_read ,
    .owner  =   THIS_MODULE,
};
static int __init btn_init(void)
{
    int ret;
    int irq;
    int flags;
    flags = IRQ_TYPE_EDGE_BOTH;
    irq = gpio_to_irq( GPIOL(14) );
	//发生中断号为irq的中断会执行key_isr函数。注册成功会在/proc/irq号/KEY文件夹出现或 cat /proc/interrupts, 记录了本中断发生的次数cat /proc/irq/442/spurious
    ret = request_irq(irq,key_isr, flags, "KEY",NULL);
    if(ret < 0)
    {   
           irq = gpio_to_irq( GPIOL(14) ); 
           disable_irq(irq);
           free_irq(irq, NULL);
           return ret;
    }
    ret = misc_register(&misc); 
    printk(KERN_EMERG " Device registered \n ");
    return ret;
}
static void __exit btn_exit(void)
{
    int irq;
    irq = gpio_to_irq( GPIOL(14) ); 
    disable_irq(irq);
    free_irq(irq, NULL);
    misc_deregister(&misc);
    printk(KERN_EMERG " Equipment logged out \n");
}
module_init(btn_init);
module_exit(btn_exit);
MODULE_LICENSE("GPL");
测试应用代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <errno.h>    
#define  DEV_NAME    "/dev/mybtn"
int main(int argc, char *args[])
{
    int fd = 0;
    int ret = 0;
    unsigned char recv_buf[1] = {"0"};

    fd = open(DEV_NAME, O_RDONLY);
    //fd = open(DEV_NAME, O_RDONLY|O_NONBLOCK);
    if(fd < 0) {
        perror("open");
    }

    while(1) {
        strcpy(recv_buf, "0000");
        //读取按键数据
        ret = read(fd, recv_buf, 1);
        if((ret < 0) && (errno != EAGAIN)) {
            perror("read");
            exit(-1);
        }

        //输出按键状态
        printf("%s\r\n", recv_buf);
    }

    return 0;
}

Makefile代码:

KERN_DIR = /work/lichee/linux-3.4
all:
	make -C $(KERN_DIR) M=`pwd` modules 
	arm-none-linux-gnueabi-gcc  btntest.c -o btntest
clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order
obj-m        += btn_drv.o


遗憾的是,代码虽然能编译成功,但是驱动加载有错误,等找出原因再发帖补充,

开发板交流群 QQ:641395230

1.PNG



管理员
2019-02-14 09:59:29    评分
2楼

谢谢楼主分享


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]