zoukankan      html  css  js  c++  java
  • linux驱动分离分层的概念

    这个分离分层的概念和输入子系统有点像,但不是完全一样的。为什么会再弄一个这个模型出来我也没有搞懂,现在我的学习还停留在把知识学懂的层面上。至于为什么会产生这种知识,现在我还无从解释,还需时日成长。

    这次先上代码在解释整体构架。

    devic.c

    #include <linux/module.h>
    #include <linux/version.h>
    
    #include <linux/init.h>
    
    #include <linux/kernel.h>
    #include <linux/types.h>
    #include <linux/interrupt.h>
    #include <linux/list.h>
    #include <linux/timer.h>
    #include <linux/init.h>
    #include <linux/serial_core.h>
    #include <linux/platform_device.h>
    
    static void led_release(struct device * dev)
    {
    }
    
    
    
    static struct resource led_resource[] = {
        [0] = {
            .start = 0x56000010,             /* TQ2440的LED是GPB5,6,7,8, GPBCON地址是0x56000010 */
            .end   = 0x56000010 + 8 - 1,
            .flags = IORESOURCE_MEM,
        },
        [1] = {
            .start = 5,                      /* LED1 */
            .end   = 5,
            .flags = IORESOURCE_IRQ,
        }
    };
    
    //////首先要声明这么一个结构体   并且填充里面的一些东西     name是很重要的  
    //////它是两个文件相互匹配的依据 第二总要的就是resource 这个是声明你的硬件资源的
    static
    struct platform_device led_dev = { .name = "myled", .id = -1, .num_resources = ARRAY_SIZE(led_resource), .resource = led_resource, .dev = { .release = led_release, }, }; static int led_dev_init(void) { platform_device_register(&led_dev); return 0; } static void led_dev_exit(void) { platform_device_unregister(&led_dev); return ; } module_init(led_dev_init); module_exit(led_dev_exit); MODULE_LICENSE("GPL");

    drive.c

    #include <linux/module.h>
    #include <linux/version.h>
    
    #include <linux/init.h>
    #include <linux/fs.h>
    #include <linux/interrupt.h>
    #include <linux/irq.h>
    #include <linux/sched.h>
    #include <linux/pm.h>
    #include <linux/sysctl.h>
    #include <linux/proc_fs.h>
    #include <linux/delay.h>
    #include <linux/platform_device.h>
    #include <linux/input.h>
    #include <linux/irq.h>
    #include <asm/uaccess.h>
    #include <asm/io.h>
    
    static struct class *cls;
    static struct class_device    *dev;
    static volatile unsigned long *gpio_con;
    static volatile unsigned long *gpio_dat;
    static int pin;
    int major;
    
    static int led_open(struct inode *inode, struct file *file)
    {
        *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;
    }
    
    
    static struct file_operations led_fops = {
        .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
        .open   =   led_open,     
        .write    =    led_write,       
    };
    
    
    static int led_probe(struct platform_device *pdev)
    {
        printk("led_probe!
    ");
    
        /*从这里获取在dev文件里面注册的资源*/
        struct resource * res;
        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");
    
        dev = class_device_create(cls, NULL, MKDEV(major, 0), NULL, "led");
        
        return 0;
    }
    
    static int led_remove(struct platform_device *pdev)
    {
        printk("led_remove!
    ");
        
        class_device_unregister(dev);
    
        class_destroy(cls);
        
        unregister_chrdev(major, "myled");
        iounmap(gpio_con);
        return 0;
    }
    
    ///填充 这个结构体
    struct
    platform_driver led_drv = { .probe = led_probe, .remove = led_remove, .driver = { .name = "myled", } }; static int led_drv_init(void) { platform_driver_register(&led_drv); return 0; } static void led_drv_exit(void) { platform_driver_unregister(&led_drv); return ; } module_init(led_drv_init); module_exit(led_drv_exit); MODULE_LICENSE("GPL");


    首先  这个模型是依赖于内核里面的platform.c这个文件的。

    和输入子系统相比    这个模型的两边都要我们自己写。

    先看看device这边,这边全部都是与硬件相关的代码。

    我们可以看到  这个文件主要就是声明了一个结构体  然后填充结构体里面的一些值

    最重要的就是两个东西   一个name 一个就是resource

    填充完了之后告诉给这个模型的老大     也就是platform.c这个文件啦  

    再看drive这边。  drive这边也填充了一个结构体  并且向老大注册了这个结构体(platform_driver)

    我们知道   如果匹配两边的name匹配上了之后就会调用drive里面的led_probe 函数

    在看看led_probe函数:

    在里面取出了再device那边注册的硬件资源   然后再做各种处理 

    余下的就和一般的驱动程序没什么区别啦

    这说的也是一点皮毛   要深入的了解还是要看内核的代码   :

    platform.c

  • 相关阅读:
    python 包管理工具 pip 的配置
    Python 变量作用域 LEGB (下)—— Enclosing function locals
    Python 变量作用域 LEGB (上)—— Local,Global,Builtin
    2020 Java 面试题 小结 (答案慢慢补上,有错误请指出)
    mysql 根据日期(date)做年,月,日分组统计查询
    jvm指令
    正则表达式 分割地址 获取省市区详细地址
    .Net 异常记录
    WCF设计服务协议(一)
    plsql ORA-01789:查询块具有不正确的结果列数
  • 原文地址:https://www.cnblogs.com/pslfree/p/3355531.html
Copyright © 2011-2022 走看看