2.14作业【GPIIO控制LED】

设备树

     myleds{
         myled1 = <&gpioe 10 0>;
         myled2 = <&gpiof 10 0>;
         myled3 = <&gpioe 8 0>;        
     };

驱动代码

    #include<linux/init.h>
    #include<linux/module.h>
    #include<linux/of.h>
    #include<linux/of_gpio.h>
    #include<linux/gpio.h>
    #include<linux/fs.h>
    #include<linux/uaccess.h>
    #include<linux/io.h>
    #include<linux/cdev.h>
    #include<linux/slab.h>
    #include"./six.h"
    /*
      myleds{                       
          myled1 = <&gpioe 10 0>;
          myled2 = <&gpiof 10 0>;
          myled3 = <&gpioe 8 0>;
    */
    #define GNAME "mydev"
    unsigned int major =0;
    char kbuf[128]={0};
    struct cdev* cdev;
    struct class * cls;
    struct device *devic;
    dev_t dev1;
    int minor = 0;
    unsigned count=6;
    wait_queue_head_t wq;
    int condition=0;
     
    int mydev_open(struct inode *inode, struct file *file)
    {
        printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
        return 0;
    }
    long mydev_ioctl(struct file *file,unsigned int cmd,unsigned long arg)
    {
        int addr;
        switch(cmd)
        {
            case LED_ON:
            {
                    ret = copy_from_user(&addr,(void*)arg,sizeof(int));
                        if(ret)
                        {
                            printk("copy from user on is error\n");
                            return -EIO;
                        }
                        switch(addr)
                        {
                            case LED1:
                            {
                                gpiod_set_value(gpiono1,1);
                                break;
                            }
                            case LED2:
                            {
                                gpiod_set_value(gpiono2,1);
                                break;
                            }
                            case LED3:
                            {
                                gpiod_set_value(gpiono3,1);
                                break;
                            }
                        }    
                break;
            }
            case LED_OFF:
            {
                 ret = copy_from_user(&addr,(void*)arg,sizeof(int));
                        if(ret)
                        {
                            printk("copy from user on is error\n");
                            return -EIO;
                        }
                        switch(addr)
                        {
                            case LED1:
                            {
                                gpiod_set_value(gpiono1,0);
                                break;
                            }
                            case LED2:
                            {
                                gpiod_set_value(gpiono2,0);
                                break;
                            }
                            case LED3:
                            {
                                gpiod_set_value(gpiono3,0);
                                break;
                            }
                        }    
            break;
            }
        }
        return 0;
    }
    int mydev_close(struct inode *inode, struct file *file)
    {
        printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
        return 0;
    }
    struct file_operations fops={
        .open=mydev_open,
        .unlocked_ioctl=mydev_ioctl,
        .release=mydev_close,
    };
    static int __init mynode_init(void)
    {
        int i;
        int ret;
        //分配字符设备驱动
        cdev=cdev_alloc();
        if(NULL==cdev)
        {
            printk("cdev alloc error\n");
            goto ERR1;
        }
        //设备驱动初始化
        cdev_init(cdev,&fops);
        //申请设备号
        if(major>0)
        {
            ret=register_chrdev_region(MKDEV(major,minor),count,GNAME);
            if(ret!=0)
            {
                printk("register chrdev region error\n");
                ret = -ENOMEM;
                goto ERR2;
            }
        }
        else
        {
            ret=alloc_chrdev_region(&dev1,0,count,GNAME);
            if(ret!=0)
            {
                printk("alloc chrdev region error\n");
                ret = -ENOMEM;
                goto ERR2;
            }
            major = MAJOR(dev1);
            minor = MINOR(dev1);
        }
     
        //驱动的注册
        ret = cdev_add(cdev,MKDEV(major,minor),count);
        if(ret!=0)
        {
            printk("cdev add error\n");
            ret = -EIO;
            goto ERR3;
        }
        //通过名字获取设备树节点信息
        node = of_find_node_by_name(NULL,"myleds");
        if(NULL == node)
        {
            printk("of find node by name error\n");
            return -EFAULT;
        }
        //获取并申请LED1的gpio编号
        gpiono1 = gpiod_get_from_of_node(node,"myled1",0,GPIOD_OUT_LOW,NULL);
        if(IS_ERR(gpiono1))
        {
            printk("1gpiod get from of node error\n");
            return PTR_ERR(gpiono1);
        }
        //获取并申请LED2的gpio编号
         gpiono2 = gpiod_get_from_of_node(node,"myled2",0,GPIOD_OUT_LOW,NULL);
        if(IS_ERR(gpiono2))
        {
            printk("2gpiod get from of node error\n");
            return PTR_ERR(gpiono2);
        }
        //获取并申请LED3的gpio编号
         gpiono3 = gpiod_get_from_of_node(node,"myled3",0,GPIOD_OUT_LOW,NULL);
        if(IS_ERR(gpiono3))
        {
            printk("3gpiod get from of node error\n");
            return PTR_ERR(gpiono3);
        }

        //设置LED1管脚为输出
        gpiod_direction_output(gpiono1,0);
         //设置LED2管脚为输出
        gpiod_direction_output(gpiono2,0);
         //设置LED3管脚为输出
        gpiod_direction_output(gpiono3,0);

        //自动创建设备节点  
        cls = class_create(THIS_MODULE,GNAME);
        if(IS_ERR(cls))
        {
            ret = PTR_ERR(cls);
            goto ERR4;
        }
        for(i=0;i<count;i++)
        {
        devic = device_create(cls,NULL,MKDEV(major,i),NULL,"myled%d",i);
        if(IS_ERR(devic))
        {
            ret = PTR_ERR(devic);
            goto ERR5;
        }
        }
        init_waitqueue_head(&wq);
        return 0;
    ERR5:
        for(--i;i>=0;i--)
        {
            device_destroy(cls,MKDEV(major,i));
        }
        class_destroy(cls);
    ERR4:
        cdev_del(cdev);
    ERR3:
        unregister_chrdev_region(MKDEV(major,minor),count);
    ERR2:
        kfree(cdev);
    ERR1:
        return -EIO;
        
    }
     
    static void __exit mynode_exit(void)
    {
        int i;
        //卸载驱动前熄灭灯LED1
        gpiod_set_value(gpiono1,0);
            //卸载驱动前熄灭灯LED2
        gpiod_set_value(gpiono2,0);
            //卸载驱动前熄灭灯LED3
        gpiod_set_value(gpiono3,0);
            //卸载驱动前熄灭灯LED1

        //释放申请得到的LED1gpio编号
        gpiod_put(gpiono1);
            //释放申请得到的LED2gpio编号
        gpiod_put(gpiono2);
            //释放申请得到的LED3gpio编号
        gpiod_put(gpiono3);

     
        //销毁设备节点信息
        for(i=0;i<count;i++)
        {
        device_destroy(cls,MKDEV(major,i));
        }
        class_destroy(cls);
        //释放驱动
        cdev_del(cdev);
        //释放设备号
        unregister_chrdev_region(MKDEV(major,minor),count);
        //注销字符设备驱动
        
        kfree(cdev);
     
    }
     
    module_init(mynode_init);
    module_exit(mynode_exit);
     
    MODULE_LICENSE("GPL");

应用层代码

   #include<stdio.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    #include<unistd.h>
    #include<stdlib.h>
    #include<string.h>
    #include<sys/ioctl.h>
    #include"./six.h"
     
    int main(int argc, char const *argv[])
    {
        int fd1 = -1;
        int fd2 = -1;
        int fd3 = -1;

        int i=0;
        int whitch;
        fd1 = open("/dev/myled1",O_RDWR);
        if(-1 == fd1)
        {
            perror("open is error");
            exit(1);
        }
        fd2 = open("/dev/myled2",O_RDWR);
        if(-1 == fd2)
        {
            perror("open is error");
            exit(1);
        }
        fd3 = open("/dev/myled3",O_RDWR);
        if(-1 == fd3)
        {
            perror("open is error");
            exit(1);
        }

        while(1)
        {
            whitch=LED1;
            ioctl(fd1,LED_ON,&whitch);
            sleep(1);
            ioctl(fd1,LED_OFF,&whitch);
            whitch=LED2;
            ioctl(fd2,LED_ON,&whitch);
            sleep(1);
            ioctl(fd2,LED_OFF,&whitch);
            whitch=LED3;
            ioctl(fd3,LED_ON,&whitch);
            sleep(1);
            ioctl(fd3,LED_OFF,&whitch);
            sleep(1);
        }
        close(fd1);
        close(fd2);
        close(fd3);

        return 0;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值