生成设备节点-格式替换

1、注册驱动、设备将会把驱动的name、设备的name相互比较,系统自动调用platform_match()设备都有主设备号,和次设备号;

   设备注册包含的结构体platform_device

struct platform_device {
        const char      * name;   // 注册设备名称
        int             id;               // 注册设备的ID号 这两个会用的比频繁
        struct device   dev;      
        u32             num_resources;
        struct resource * resource;
        const struct platform_device_id *id_entry;
        // MFD cell pointer 
        struct mfd_cell *mfd_cell;
        // arch specific additions 
        struct pdev_archdata    archdata;
      };

在这里的注册设备都注册平台设备,所以在arch/arm/mach-exynos/mach-itop4412.c文件下注册,注册设备、驱动,都是注册到linux内核中,添加一段链表结点到platform平台的链表上

2、设备注册的一般流程,假设注册一个hello_ctl设备

      1、打开文件 vim  driver/char/Kconfig,并添加如下代码(可以搜索LEDS,并仿照LEDS的格式),并保存退出

config HELLO_CTL    // 设备节点名称
       tristate "Enable HELLO config"    // 可编译三种选择 不编译、编译模块、编译成节点
       default y   // 默认编译成节点
       help
         Enable HELLO config
// 添加如上代码

  2、执行make menuconfig 选择将hello_ctl编译进内核,或者编译成模块

      3、打开文件 vim arch/arm/mach-exynos/mach-itop4412.c,添加如下代码,可仿照其他代码格式(可搜索LEDS)

#ifdef CONFIG_HELLO_CTL(仿照其他代码格式)
       struct platform_device s3c_device_hello_ctl = {
          .name   = "hello_ctl",
          .id             = -1,
    };
    #endif

  4、继续搜索,LEDS找到宏定义位置,仿照其格式添加如下代码,保存退出

#ifdef CONFIG_HELLO_CTL
        &s3c_device_hello_ctl,
    #endif

  5、执行make zImage编译成镜像,使用fastboot烧写到板子里

       6、查看注册的设备ls /sys/devices/platform/

3、驱动注册,注册hello_ctl对应的驱动

      1、所需的头文件#include <linux/platform_device.h>,在vim include/linux/platform_driver.h

      2、注册驱动函数extern int platform_driver_register(struct platform_driver *);

      3、卸载驱动函数extern void platform_driver_unregister(struct platform_driver *);

      4、注册驱动参数struct 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;
    };

4、驱动注册代码基本实现,hello_ctl驱动注册

// 驱动注册所需头文件 包含结构体,注册和卸载所需的函数
      #include <linux/platform_device.h>
      #include <linux/module.h>
      #include <linux/init.h>

      #define DRIVER_NAME "hello_ctl"

      MODULE_LICENSE("Dual BSD/GPL"); 
      MODULE_AUTHOR("TOPEET");

      // 4、结构体函数完善
      // int (*probe)(struct platform_device *);
      // 初始化相关动作
      static int hello_probe(struct platform_device *p)
      {
            printk(KERN_EMERG "\t initialized\n");
            return 0;
      }
      //  int (*remove)(struct platform_device *);
      static int hello_remove(struct platform_device *p)
      {
         return 0;
      }
      // int (*suspend)(struct platform_device *, pm_message_t state);
      static int hello_suspend(struct platform_device *p)
      {
            return 0;    
      }
      //  int (*resume)(struct platform_device *);
      static int hello_resume(struct platform_device *p)
      {
            return 0;    
      }
      //  void (*shutdown)(struct platform_device *);
      static void hello_shutdown(struct platform_device *p)
      {
        
      }

      // 3、结构体数据初始化
      // 注册驱动传入的结构体
      struct platform_driver hello_driver = {
            .probe = hello_probe,    // 用于初始化模块
            .remove = hello_remove,  // 移除模块时,执行的动作
            .suspend = hello_suspend,// 模块挂起时,执行的动作
            .resume = hello_resume,  // 挂起的模块,恢复运行执行动作
            .shutdown = hello_shutdown,
            .driver = {
               .name = DRIVER_NAME, // 驱动名称
               .owner = THIS_MODULE,// 驱动所有者,THIS_MODULE宏定义
             },
      }; 
      // 2、模块初始化相关实现         
      // 模块的入口函数 加载模块执行动作     
      static int hello_init(void)
      {
            int DriverState;
            printk(KERN_EMERG "HELLO WORLD enter!\n");
            DriverState = platform_driver_register(&hello_driver);  // 注册驱动 转而执行初始化动作
            printk(KERN_EMERG "\tDriverState is %d\n", DriverState); // 注册驱动执行状态
    
            return 0;
      }
      // 模块退出函数  卸载模块所执行
      static void hello_exit(void)
      {
            printk(KERN_EMERG "HELLO WORLD exit!\n");
            platform_driver_unregister(&hello_driver);   // 卸载驱动函数
      }

      //1、 入口函数module_nint
      module_init(hello_init);
      module_exit(hello_exit);

5、上面注册设备,设备注册需要编译到镜像中,再将镜像烧写进内核中;module方式注册设备则不需要重新编译镜像;

6、以module方式注册设备

#include <linux/module.h>
      #include <linux/init.h>
      #include <linux/platform_device.h>

      #define DRIVER_NAME  "hello_ctl"

      MODULE_LICENSE("Dual BSD/GPL"); 
      MODULE_AUTHOR("TOPEET");

      static void leds_release(struct device *dev)
      {
            printk("leds_release");
      }
      struct platform_device platform_device_hello = {
            .name    = "my_code_led",
            .id         = -1,
            .dev      = {
                  .release = leds_release,
            },
      };

      static int hello_init(void)
      {
            printk(KERN_EMERG "HELLO WORLD enter!\n");
            platform_device_register(&platform_device_hello);
            return 0;
      }
      static void hello_exit(void)
      {
            printk(KERN_EMERG "HELLO WORLD exit!\n");
            platform_device_unregister(&platform_device_hello);
      }

      //1、 入口函数module_nint
      module_init(hello_init);
      module_exit(hello_exit);

7、在调试时候,想要获取注册设备驱动的信息

// 驱动注册所需头文件 包含结构体,注册和卸载所需的函数
      #include <linux/platform_device.h>
      #include <linux/module.h>
      #include <linux/init.h>

      #define DRIVER_NAME "my_code_led"

      MODULE_LICENSE("Dual BSD/GPL"); 
      MODULE_AUTHOR("TOPEET");

      // int (*probe)(struct platform_device *);
      static int hello_probe(struct platform_device *pdv)
      {
            printk(KERN_EMERG "\t initialized\n");
    
            printk("pdv->name is %s\n",pdv->name);
            printk("pdv->id is %d\n",pdv->id);
            pdv->dev.release(&pdv->dev);
        return 0;
      }
      //  int (*remove)(struct platform_device *);
      static int hello_remove(struct platform_device *p)
      {
            return 0;
      }
      // int (*suspend)(struct platform_device *, pm_message_t state);
      static int hello_suspend(struct platform_device *p)
      {
    return 0;    
      }
      //  int (*resume)(struct platform_device *);
      static int hello_resume(struct platform_device *p)
      {
    return 0;    
      }
      //  void (*shutdown)(struct platform_device *);
      static void hello_shutdown(struct platform_device *p)
      {
        
      }

      // 注册驱动传入的结构体
      struct platform_driver hello_driver = {
            .probe = hello_probe,
            .remove = hello_remove,
            .suspend = hello_suspend,
            .resume = hello_resume,
            .shutdown = hello_shutdown,
            .driver = {
              .name = DRIVER_NAME,
              .owner = THIS_MODULE,
            },
      };
       
      static int hello_init(void)
      {
            int DriverState;
    
        printk(KERN_EMERG "HELLO WORLD enter!\n");
            DriverState = platform_driver_register(&hello_driver);  // 注册驱动 转而执行初始化动作
            printk(KERN_EMERG "\tDriverState is %d\n", DriverState);
    
            return 0;
      }
      static void hello_exit(void)
      {
            printk(KERN_EMERG "HELLO WORLD exit!\n");
            platform_driver_unregister(&hello_driver);   // 卸载驱动函数
      }

      //1、 入口函数module_nint
      module_init(hello_init);
      module_exit(hello_exit);

 

posted @ 2020-08-08 14:24  笑不出花的旦旦  阅读(111)  评论(0)    收藏  举报