• 9.13作业


    #include <linux/init.h>

    #include

    #include

    #include

    #include

    #include

    #include

    struct cdev *cdev

    char kbuf[128]=0;

    unsigned int major=0;

    unsigned int minor=0;

    dev_t devno;

    module-param(major,unit,0664); //方便在命令行传递major的值

    struct class*cls;

    struct device *dev;

    struct mutex mutex; //定义互斥体



     

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

    {

        mutex_lock(&mutex);//上锁

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

        return 0;

    }

    long mycdev_ioctl(struct file *file,unsigned int cmd,unsigned long arg)

    {

        int which;

        //获取arg对应的用户空间中的值

        int ret=copy_from_user(&which,(void *)arg,4);

        if(ret)

        {

            printk("从用户空间获取数据失败\n");

            return -EIO;

        }

        switch (cmd)

        {

            case LED_ON:

            switch(which)

            {

                case 1: //LED1

                    vir_led1->ODR |= 1 << 10;

                    break;

                case 2:

                    vir_led2->ODR |= 1 << 10;

                    break;

                case 3:

                    vir_led3->ODR |= 1 << 8;

                    break;

            }

            break;

            case LED_OFF:

            switch(which)

            {

                case 1: //LED1

                     vir_led1->ODR &= (~(1 << 10));

                     break;

                case 2:

                     vir_led2->ODR &= (~(1 << 10));

                     break;

                case 3:

                     vir_led3->ODR &= (~(1 << 8));

                     break;

            }

            break;

        }

        return 0;

    }

    nt mycdev_close(struct inode *inode,struct file *file)

    {

         mutex_unlock(mutex);//解锁

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

         return 0;

    }

    //定义操作方法结构体变量并赋值

    struct file_operation fops={

        .open=mycdev_open,

        .read=mycdev_read,

        .write=mycdev_write,

        .realease=mycdev_close,

    };

    int all_led_init(void)

    {

        vir_led1=ioremap(PHY_LED1_ADDR,sizeof(gpio_t));

        if(vir_led1==NULL)

        {

            printk("ioremap filed: %d\n",__LINE__);

            return -ENOMEM;

        }

          vir_led2=ioremap(PHY_LED2_ADDR,sizeof(gpio_t));

        if(vir_led2==NULL)

        {

            printk("ioremap filed: %d\n",__LINE__);

            return -ENOMEM;

        }

        vir_led3=vir_led1;

        vir_rcc=ioremap(PHY_RCC_ADDR,4);

        if(vir_rcc==NULL)

        {

            printk("ioremap filed: %d\n",__LINE__);

            return -ENOMEM;

        }

    printk("物理地址映射成功\n");

    //寄存器的初始化

    //rcc

    (*vir_rcc) |= (0x3<<4);

    //LED1

    vir_led1->MODER &= (~(3<<20));

    vir_led1->MODER |= (1<<20);

    vir_led1->ODR &= (~(1<<10));

    //LED2

    vir_led2->MODER &= (~(3<<20));

    vir_led2->MODER |= (1<<20);

    vir_led2->ODR &= (~(1<<10));

    //LED3

    vir_led3->MODER &= (~(3<<16));

    vir_led3->MODER |= (1<<16;

    vir_led3->ODR &= (~(1<<8));

    printk("寄存器初始化成功\n");

    return 0;

    }

    static int __init mycdev_init(void)

    {

        int ret;

        //为字符设备驱动对象申请空间

        cdev=cdev_alloc();

        if(cdev==NULL)

        {

            printk(" 字符设备驱动对象申请空间失败\n");

            ret=-EFAULT;

            goto out1;

           

        }

        printk("申请对象空间成功");

        //初始化字符设备驱动对象

        cdev——init(cdev,&fops);

        //申请设备号

        if(major>0)//静态指定设备号

        {

            ret=register_chrdev_region(MKDEV(major,minor),3,"myled");

            if(ret)

            {

                printk("静态申请设备号失败\n");

                goto out2;

            }

        }

        else if(major==0)//动态申请设备号

        {

           ret=register_chrdev_region(MKDEV(major,minor),3,"myled");

            if(ret)

            {

                printk("动态申请设备号失败\n");

                goto out2;

            }

            major=MAJOR(devno);//获取主设备号

            major=MINOR(devno);//获取次设备号

        }

        printk("申请设备号成功\n");

       

        mutex_init(&mutex);//初始化互斥体  

        //字符设备驱动对象注册

        ret=cdev_add(cdev,MKDEV(major,minor),3);

        if(ret)

        {

            printk("字符设备驱动对象注册失败\n");

            goto out3;

        }

        printk("字符设备驱动对象注册成功\n");

        //寄存器映射以及初始化

        all_led_init();

        //向上提交目录

        cls=class_create(THIS_MODULE,"myled");

        if(IS_ERR(cls))

        {

            printk("向上提交目录失败\n");

            return -PTR_ERR(cls);

            goto out4;

        }

        printk("向上提交目录成功\n");

        //向上提交设备节点信息

        int i;

        for(i=0;i<3;i++)

        {

            dev=device_create(cls,NULL,MKDEV(major,i)NULL,"mychrdevv%d",i);

            if(IS_ERR(dev))

            {

                printk("向上提交设备节点信息失败\n");

                return -PTR_ERR(dev);

            }

        }

        printk("向上提交设备节点信息成功\n");

        return 0;

    }

    out5:

         //释放前一次提交成功的设备信息

         for(--i;i>=0;i--)

         {

            device_destory(cls,MKDEV(major,i));

         }

         class_destory(cls);//释放目录

    out4:

        cdev_del(cdev);

    out3:

         unregister_chrdev_region(MKDEV(major,minor),3);

    out2:

        kfree(cdev);

    out1:

        return ret;

    static void __exit mycdev_exit(void)

    {

        //销毁设备节点信息

        int i;

        for(i=0;i<3;i++)

        {

            device_destory(cls,MKDEV(major,i));

        }

        //销毁目录信息

        class_destory(cls);

        //取消地址映射

        iounmap(vir_led1);

        iounmap(vir_led2);

        iounmap(vir_rcc);

        //注销字符设备驱动对象

        cdev_del(cdev);

        //释放设备号

        unregister_chrdev_region(MKDEV(major,minor),3);

        //释放对象空间

        kfree(cdev);

       

    }

    module_init(mycdev_init);

    module_exit(mycdev_exit);

    MODULE_LICENSE("GPL");

  • 相关阅读:
    java元注解
    TinyOs操作系统---第0章 课程概述
    QT+OSG/osgEarth编译之二十四:SpatiaLite+Qt编译(一套代码、一套框架,跨平台编译,版本:SpatiaLite-5.0.1)
    PWA 踩坑 - 第一次加载页面后无法获取CacheStorage某些资源
    企业管理系统有哪些?
    REDIS00_SpringBoot整合redis、RedisTemplate使用、工具类的抽取
    CCRC-DSA数据安全评估师:加快构建大网络安全工作格局
    【一生一芯】Chap.0 IC常用网站论坛门户 & 如何提出一个技术问题 并尝试解决 | 提问的智慧
    容器内存溢出排障思路
    选择最佳的项目管理工具:推荐哪一个?
  • 原文地址:https://blog.csdn.net/weixin_72099373/article/details/132863586