Linux内核——字符型驱动到platform驱动的华丽转身

跟着简叔学的,可以B站搜索 简说linux

platform驱动

platform驱动是一种模拟的总线驱动。将字符型驱动包装成platform驱动有两大好处。

  • 把设备都挂接在一个pseudo总线上,便于管理,同时也符合Linux的设备模型机制。其结果是,配套的sysfs节点、设备电源管理都成为可能;
  • 隔离设备和驱动。在BSP中定义platform设备和它使用的资源、设备的具体配置信息;而在驱动中,只需要通过通用的API去获取资源和数据,做到了BSP相关代码和驱动代码的分离,使得驱动具有更好的可扩展性和跨平台性。

不在总线上的驱动都可一包装成platform驱动

什么是BSP(14条消息) 嵌入式中的BSP—-BSP到底是什么?_芯片bsp_shangtang的博客-CSDN博客

内核里分别用device和driver来表示设备和驱动,面向对象的思想,device是所有设备的基类,driver是所有驱动的基类。将我们瞎写的字符型驱动改造成platform驱动比较规范话,

改造

  1. 首先需要添加头文件

    1
    #include <linux/platform_device.h>
  2. hello_init函数 要改成

    1
    static int hello_probe(struct platform _device *pdev)
  3. 卸载函数改成

    1
    static int hellodev_remove(struct platform_device *pdev)
  4. 定义设备资源

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #define LEDBASE 0x56000010
    #define LENDLEN 0x0c
    static struct resource hello_dev_resource[] = {
    [0] = {
    .start = LEDBASE,
    .end = LEDBASE + LEDLEN - 1,
    .flags = IORESOURCE_MEM, //内存资源
    }
    };
  5. 定义设备

    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct platform_device hello_device = {
    .name = "hello-device", //设备名
    .id = -1,
    .num_resources = ARRAY_SIZE(hello_dev_resource), //指定资源 可以是io资源 内存资源 还有ARQ资源?
    .resource = hello_dev_resource,
    .dev = {
    .release = hello_plat_release,
    }
    };
  6. 定义驱动

    在这里指定驱动模块插入和删除的操作是哪个。并且给驱动起个名字。

    1
    2
    3
    4
    5
    6
    7
    8
    static struct platform_driver hellodev_driver = {
    .probe = hellodev_probe,
    .remove = hellodev_remove,
    .driver = {
    .owner = THIS_MODULE,
    .name = "hello-device",
    },
    };
  1. 最后定义内核才插入和删除该设备时 的操作。 注册设备 注册驱动 删除设备 删除驱动

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    int charDrvInit(void)
    {
    platform_device_register(&hello_device);
    return platform_driver_register(&hellodev_driver);
    }

    void __exit charDrvExit(void)
    {
    platform_device_unregister(&hello_device);
    platform_driver_unregister(&hellodev_driver);
    return;
    }
    module_init(charDrvInit);
    module_exit(charDrvExit);
    MODULE_LICENSE("GPL");

  2. 编译安装

    1678101131204

Platform驱动设备 匹配注册机制

  1. 几个重要的结构体一看就能懂。

    1678101331998

    device是linux内核所有设备的基类 resouce就是资源。

    1678101429981

    驱动就是行为,所以大部分都是函数。插入删除关闭休眠唤醒。device_driver 就是所有驱动的基类。

    *id_table

    1678102019401

    一般匹配就是通过bus去匹配

  2. 注册函数 的实现

    设备初始化包括资源初始化,如果设备父设备为空那么会指定一个叫platform的虚拟设备,用来表示总线设备是虚拟的,类型是platformbus,然后使用device_add函数将设备加入内核。

    驱动的注册就是把那几个函数地址赋值。bus用于匹配,都是platform类型的就

    平台设备是一条链,平台驱动是一条链表,他们都挂在platform bus这个东西上上。那么驱动和设备的匹配就是遍历链表一个一个匹配。只有某一个设备和某一个驱动匹配上了,才会成功地插入驱动。

其实这块可以细究一下的,但是最近没什么时间了。。。。。发现学内核很需要心境