platform点灯

驱动程序 :

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define CNAME "irq_led"

int major;

struct class *cls;

struct device *dev;

wait_queue_head_t wq;

unsigned int condition=0;

unsigned int status=0;

struct device_node *node;

struct gpio_desc *desc;

unsigned int irqno;

struct resource *res;

irqreturn_t irq_led_handle(int irq, void *dev)

{

    status = gpiod_get_value(desc);

    status = !status;

    gpiod_set_value(desc,status);

    condition=1;

    wake_up_interruptible(&wq);

    return IRQ_HANDLED;

}

int irq_led_open(struct inode *inode, struct file *file)

{

    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

    return 0;

}

ssize_t irq_led_read(struct file *file,

    char __user *ubuf, size_t size, loff_t *offs)

{

    int ret;

    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

    if(file->f_flags & O_NONBLOCK){

        //非阻塞

        return 1H-EINVAL;

    }else{

        //阻塞

        ret = wait_event_interruptible(wq,condition);

        if(ret < 0){

            printk("receive signal....\n");

            return ret;

        }

    }

    //将数据拷贝到用户空间

    if(size > sizeof(status)) size = sizeof(status);

    ret = copy_to_user(ubuf,(void *)&status,size);

    if(ret){

        printk("copy data to user error\n");

        return -EIO;

    }

    //4.将条件清零

    condition = 0;

    return size;

}

int irq_led_close(struct inode *inode, struct file *file)

{

    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

    return 0;

} cvgtr54hg

bv  xrywe0-t6struct file_operations fops = {

    .open = irq_led_open,

    .read = irq_led_read,

    .release = irq_led_close,

};

//封装probe函数和remove函数

int pdrv_probe(struct platform_device *pdev)

{

     int ret;

    //1.注册字符设备驱动

    major = register_chrdev(0,CNAME,&fops);

    if(major < 0){

        printk("register char device driver error\n");

        ret = major;

        goto ERR1;

    }

    //2.创建设备节点

    cls = class_create(THIS_MODULE,CNAME);

    if(IS_ERR(cls)){

        printk("class create error\n");

        ret = PTR_ERR(cls);

        goto ERR2;

    }

    dev = device_create(cls,NULL,MKDEV(major,0),NULL,CNAME);

    if(IS_ERR(dev)){

        printk("device create error\n");

        ret = PTR_ERR(dev);

        goto ERR3;

    }

    //3.初始化等待队列头

    init_waitqueue_head(&wq);

    //4.解析设备树节点,申请使用的中断和led

    node = of_find_node_by_path("/irq_led");

    if(node == NULL){

        printk("get node error");

        ret = -EAGAIN;

        goto ERR4;

    }

    //获取gpio结构体信息

    desc = gpiod_get_from_of_node(node,"led1",0,GPIOD_OUT_LOW,NULL);

    if(IS_ERR(desc)){

        printk("get gpiod error\n");

        ret = PTR_ERR(desc);

        goto ERR4;

    }

//获取软中断号

    irqno = irq_of_parse_and_map(node,0);

    if(irqno == 0){

        printk("irq get number error\n");

        ret = -EAGAIN;

        goto ERR5;

    }

//注册中断

    ret = request_irq(irqno,irq_led_handle,IRQF_TRIGGER_FALLING,CNAME,NULL);

    if(ret){

        printk("request irq error\n");

        goto ERR5;

    }

    return 0;

ERR5:

        gpiod_put(desc);

ERR4:

        device_destroy(cls,MKDEV(major,0));

ERR3:

        class_destroy(cls);

ERR2:

        register_chrdev(major,CNAME);

ERR1:

       return ret;

};

int pdr_remove(struct platform_device *pdev)

{

    gpiod_set_value(desc,0);

    free_irq(irqno,NULL);

    gpiod_put(desc);

    device_destroy(cls,MKDEV(major,0));

    class_destroy(cls);

    unregister_chrdev(major,CNAME);

    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

    return 0;

};

struct of_device_id oftable[]=

{

    {.compatible="hqyj,irq_led",},

    {.compatible="hqyj,irq_led1",},

    {.compatible="hqyj,irq_led2",},

    {},

};

struct platform_driver pdrv=

{

    .probe=pdrv_probe,

    .remove=pdrv_remove,

    .driver={

        .name="aaaa",

        .of_match_table=oftable,

    },

};

//一键注册宏

module_platform_driver(pdrv);

MODULE_LICENSE("GPL");    class_destroy(cls);

设备树添加:

irq_led{

compatible = "hqyj,irq_led"; //用于获取节点

interrupt-parent = <&gpiof>; //引用父节点

interrupts = <9 0>; //这个节点引入的中断管脚

led1=<&gpioe 10 0>; 

};

你可能感兴趣的:(visual,studio,驱动开发)