zoukankan      html  css  js  c++  java
  • linux总线设备驱动模型

    本篇文章通过平台总线设备模型为例,讲解总线设备驱动模型:

    platform_device_register的作用:
    1.把device放入bus的device链表
    2.从bus的driver链表中取出每一个driver,用bus的match函数判断driver能否支持这个device
    3.若可以支持,调用driver的probe函数
    platform_driver_register的作用:
    1.将driver放入bus的driver链表
    2.从bus的device链表中取出每一个device,用bus的match函数判断这个driver能否支持这个device
    3.若可以支持,调用driver的probe函数
     
    一、device驱动程序
    1.构造并初始化平台设备资源结构体resource
    struct resource led_resource[] = {
         [0] = {
              .start = 0x56000000,
              .end = 0x56000000 + 8 - 1,
              .flags = IORESOURCE_MEM,
         },
         [1] = {
              .start = 5,
              .end = 5,
              .flags = IORESOUCE_IRQ,
         },
    };
    2.构造并初始化平台设备结构体platform_device
    struct platform_device led_dev = {
         .name = "myled";
         .id      = -1;
         .num_resource = ARRAY_SIZE(led_resource);
         .resource = led_resource,
         .dev = {
              .release = led_release,
         },
    };
    /* release函数可以什么都不做,但是不能为空 */
    static void led_release(struct device * dev)
    {
    }
    3.注册平台device
    platform_device_register(&led_dev);
    二、driver驱动程序
    1.构造并初始化平台驱动结构体platform_driver
    struct platform_driver led_drv = {
         .probe = led_probe,
         .remove = led_remove,
         .driver = {
              .name = "myled",
         },
    };
    2.构造并初始化file_operations结构体
    static struct file_operations led_fops = {
         .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
         .open   =   led_open,
         .write    =   led_write,
    };
    static int led_open(struct inode *inode, struct file *file)
    {
         //printk("first_drv_open
    ");
         /* 配置为输出 */
         *gpio_con &= ~(0x3<<(pin*2));
         *gpio_con |= (0x1<<(pin*2));
         return 0;    
    }
    
    static ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
    {
         int val;
    
         //printk("first_drv_write
    ");
    
         copy_from_user(&val, buf, count); //     copy_to_user();
    
         if (val == 1)
         {
              // 点灯
              *gpio_dat &= ~(1<<pin);
         }
         else
         {
              // 灭灯
              *gpio_dat |= (1<<pin);
         }
        
         return 0;
    }
    3.实现platform_driver结构的probe函数
    static int led_probe(struct platform_device *pdev)
    {
         struct resource *res;
     
         *platform_get_resource
         *@dev:platformdevice
         *@type:resourcetype
         *@num:resourceindex
         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
         gpio_con = ioremap(res->start,res->end-res->start+1);
         gpio_dat = gpio_con + 1;
         res = platform_get_resource(pdev, IORESOURCE_IRQ, 0)
         pin = res->start;
         major = register_chrdev(0, "myled", &led_fops);
         cls = class_create(THIS_MODULE, "myled");
         device_create(cls, NULL, MKDEV(major,0), NULL, "led");
    }
    4.注册平台driver驱动程序
    platform_driver_register(&led_drv);
  • 相关阅读:
    Django Rest Framework(认证、权限、限制访问频率)
    MySql 三大知识点——索引、锁、事务
    django聚合查询
    Python装饰器用法
    linux上ssh免密登录原理及实现
    为github公开项目单独设置用户名
    golang协程池设计
    Django-Signals信号量
    linux tcp相关参数
    记一次性能优化,限制tcp_timewait数量,快速回收和重用
  • 原文地址:https://www.cnblogs.com/zpehome/p/3811158.html
Copyright © 2011-2022 走看看