zoukankan      html  css  js  c++  java
  • 4412 Linux设备总线

    总线_设备_驱动注册流程详解

    注册流程图


    设备一般都需要先注册,才能注册驱动
    现在越来越多的热拔插设备,反过来了。先注册驱动,设备来了再注册

    设备

    本节使用的命令
    查看总线的命令#ls /sys/bus/
    查看设备号的命令#cat /proc/devices
    设备都有主设备号和次设备号,否则255个设备号不够用
    查看杂项设备号的命令#cat /proc/misc

     

    二、总线设备注册

    关于注册设备的一点说明

    早先的Linux会使用单独的文件注册设备,现在大多是使用引入的虚拟平台,使用虚拟平台来注册设备会容易很多
    如果大家在网上看到大段的注册设备的代码,可简单了解一下,知道有这么个东西就成,不用去深究。不要去学习屠龙技,现在基本都是直接在平台文件中注册设备
    注册设备
    注册设备使用结构体platform_device,该结构体在头文件vim include/linux/platform_device.h中。头文件中也有注册设备和卸载设备的函数,了解即可

    操作过程

    注册设备。将设备结构体放到平台文件中,会自动注册设备,不用去调用注册设备的函数。

    vim arch/arm/mach-exynos/mach-itop4412.c

    添加设备注册

    #ifdef CONFIG_HELLO_CTL
    struct platform_device s3c_device_hello_ctl = {
            .name   = "hello_ctl",
            .id             = -1,
    };
    #endif
    
    #ifdef CONFIG_LEDS_CTL
    struct platform_device s3c_device_leds_ctl = {
            .name   = "leds",
            .id             = -1,
    };
    #endif

    和这个

    #ifdef CONFIG_HELLO_CTL
        &s3c_device_hello_ctl,
    #endif
    
    #ifdef CONFIG_LEDS_CTL
        &s3c_device_leds_ctl,
    #endif


    Kconfig文件中添加编译HELLO设备的宏定义(前面教程中已经添加)
    配置menuconfig中的HELLO宏定义,生成新的.config文件
    生成新的zImage
    注册完之后在虚拟平台总线下可以查到注册的设备
    ls /sys/devices/platform/

     中间遇到的问题:编译make zImage的时候提示

    arch/arm/mach-exynos/mach-itop4412.c:2997: error: 's3c_device_hello_ctl' undeclared here (not in a function)

    这个的没有写正确

    #ifdef CONFIG_HELLO_CTL
    struct
    platform_device s3c_device_hello_ctl = {

    三、总线驱动注册

    头文件

    驱动注册使用结构体platform_driver,该结构体在头文件vim include/linux/platform_device.h
    驱动注册platform_driver_register,驱动卸载函数 platform_driver_unregister也在这个头文件中
    这两个函数的参数都只有结构体platform_driver

    struct platform_driver {
        int (*probe)(struct platform_device *);
        int (*remove)(struct platform_device *);
        void (*shutdown)(struct platform_device *);
        int (*suspend)(struct platform_device *, pm_message_t state);
        int (*resume)(struct platform_device *);
        struct device_driver driver;
        const struct platform_device_id *id_table;
    };

    注册结构体

    驱动常见的几种状态,初始化,移除,休眠,复位
    就像PC一样,有的驱动休眠之后无法使用,有的可以使用;有的系统唤醒之后,驱动需要重新启动才能正常工作,也有直接就可以使用等等
    probe函数platform_match函数匹配之后,驱动调用的初始化函数
    remove函数: 移除驱动函数
    suspend函数: 悬挂(休眠)驱动函数

    resume函数: 休眠后恢复驱动
    device_driver数据结构的两个参数
    name和注册的设备name要一致
    owner一般赋值THIS_MODULE

    #include <linux/module.h>
    #include <linux/init.h>
    
    /* device register header file, include device and driver struct
     * register and remove function */
    #include <linux/platform_device.h>
    
    #define DRIVER_NAME "hello_ctl"
    
    MODULE_LICENSE("Dual BSD/GPL");
    MODULE_AUTHOR("TOPEET");
    
    static int hello_probe(struct platform_driver *pdv)
    {
        printk(KERN_EMERG "	initialized
    ");
        return 0;
    }
    
    static int hello_remove(struct platform_driver *pdv)
    {
        return 0;
    }
    
    static void hello_shutdown(struct platform_driver *pdv)
    {
    
    }
    
    static int hello_suspend(struct platform_driver *pdv)
    {
        return 0;
    }
    
    static int hello_resume(struct platform_driver *pdv)
    {
        return 0;
    }
    
    struct platform_driver hello_driver = {
        .probe    = hello_probe,    
        .remove   = hello_remove,
        .shutdown = hello_shutdown,
        .suspend  = hello_suspend,
        .resume   = hello_resume,
        .driver = {
            .name  = DRIVER_NAME,
            .owner = THIS_MODULE,
        }
    };
    
    static int hello_init(void)
    {
        int DriverState;
    
        printk(KERN_EMERG "Hello world enter!
    ");
        DriverState = platform_driver_register(&hello_driver);
    
        printk(KERN_EMERG "	DriverState is %d
    ", DriverState);
        return 0;
    }
    
    static void hello_exit(void)
    {
        printk(KERN_EMERG "Hello world exit!
    ");
        platform_driver_unregister(&hello_driver);
    }
    
    module_init(hello_init);
    module_exit(hello_exit);
    register driver

    实验

    mini_linux_module的基础上添加驱动注册部分
    编译,在开发板上加载和卸载驱动

    mount -t nfs -o nolock 192.168.2.147:/home/topeet/linux /mnt/nfs

    挂载了nfs后,加载内核后

    [root@iTOP-4412]# insmod probe_linux_module.ko                                                                     
    [ 8454.570719] Hello world enter!
    [ 8454.572614]  initialized
    [ 8454.582781]  DriverState is 
    [root@iTOP-4412]# rmmod probe_linux_module                                                                         
    [ 8647.985422] Hello world exit!
    无欲速,无见小利。欲速,则不达;见小利,则大事不成。
  • 相关阅读:
    java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or.....
    cas单点登录防止登出退出后刷新后退ticket失效报500错
    IDEA远程调试服务器代码
    阿里的fastJson.jar jsonArray 和 list 互转
    获取多<a/>标签id值的点击事件
    redis常用命令
    SuperDiamond在JAVA项目中的三种应用方法实践总结
    Redis 集群环境的搭建
    eclipse中一些常见svn图标的含义
    【转】Windows下PATH等环境变量详解
  • 原文地址:https://www.cnblogs.com/ch122633/p/9437536.html
Copyright © 2011-2022 走看看