当前位置: 首页 > news >正文

linux 驱动的platform机制:

添加设备阶段:

设备注册的时候Platform_device_register()→platform_device_add()→(pdev→dev.bus = &platform_bus_type)→device_add(),就这样把设备给挂到虚拟的总线上

详细解析这个阶段流程:

在 Linux 中,platform 机制是一种用于管理无明确硬件总线关系的设备(通常是 SoC 上的设备)的框架。platform_device 是 Linux 内核中的一种设备类型,通常用于描述嵌入式系统中的设备。这些设备通常没有标准的硬件总线(如 PCI 或 USB),所以使用虚拟的 platform_bus 来管理。

以下详细解析 Platform_device_register() 添加设备阶段的流程:


1. Platform_device_register()

Platform_device_register() 是注册平台设备的函数,它的实现实际上会调用 platform_device_add()

C

int platform_device_register(struct platform_device *pdev) { device_initialize(&pdev->dev); // 初始化设备结构体 return platform_device_add(pdev); // 添加设备到 platform 总线 }

关键步骤
  1. 调用 device_initialize(&pdev->dev)

    • 初始化设备结构体 pdev->dev,这是一个通用的设备结构体(类型为 struct device)。
    • 主要是准备设备的生命周期管理机制(如 kobject 的引用计数等)。
  2. 调用 platform_device_add(pdev)

    • 将 pdev 添加到 platform_bus 中。

2. platform_device_add()

核心功能是将 platform_device 添加到平台总线中。

函数实现如下:

C

int platform_device_add(struct platform_device *pdev) { int ret; if (!pdev) return -EINVAL; // 设置 platform_device 的总线类型为 platform_bus pdev->dev.bus = &platform_bus_type; // 设置设备名字 if (!pdev->dev.release) { dev_set_name(&pdev->dev, "%s", pdev->name); } // 添加设备到设备模型 ret = device_add(&pdev->dev); // 关键步骤 if (ret == 0) platform_device_add_resources(pdev, pdev->resource, pdev->num_resources); return ret; }

关键步骤
  1. 检查 pdev 的有效性

    • 确保 pdev 非空,否则返回错误。
  2. 设置设备的总线类型

    • 将 pdev->dev.bus 设置为 &platform_bus_type,表示该设备属于 platform_bus 类型。
    • platform_bus_type 是一个全局变量,定义了 platform 总线的行为。

    C

    struct bus_type platform_bus_type = { .name = "platform", .match = platform_match, // 用于设备与驱动匹配 };

  3. 设置设备名字

    • 如果设备没有定义 release 回调函数,则调用 dev_set_name() 给设备设置一个名字(一般是 pdev->name)。
  4. 调用 device_add(&pdev->dev)

    • 最关键的步骤:将设备添加到设备模型中,建立与内核设备模型的关联。

3. device_add()

device_add() 是设备模型的核心函数,用于将设备注册到内核的设备层。

函数实现如下(核心部分):

C

int device_add(struct device *dev) { int ret; // 检查设备相关字段是否有效 if (!dev->p || !dev->bus) return -EINVAL; // 设置设备的子系统层次关系 dev->parent = get_device(dev->parent); kobject_set_name(&dev->kobj, dev_name(dev)); // 添加设备到设备层 ret = kobject_add(&dev->kobj, dev->parent ? &dev->parent->kobj : NULL, dev_name(dev)); if (ret < 0) goto Error; // 设备和总线关联 ret = device_add_class_symlinks(dev); if (ret) goto Error; ret = bus_add_device(dev); if (ret) goto Error; // 通知驱动和用户层 ret = device_add_groups(dev, dev->groups); if (ret) goto Error; // 通知系统有新设备添加 kobject_uevent(&dev->kobj, KOBJ_ADD); return 0; Error: kobject_put(&dev->kobj); return ret; }

关键步骤
  1. 检查设备字段是否有效

    • 确保设备结构体中的必要字段(如 dev->p 和 dev->bus)已经初始化。
  2. 设置设备的层次关系

    • 如果设备有父设备,则设置父子关系。
    • 通过 kobject_set_name() 给设备设置一个唯一的名字。
  3. 添加设备到设备模型

    • 调用 kobject_add() 将设备的 kobject 添加到内核的设备层次结构中。
  4. 设备与总线关联

    • 调用 bus_add_device() 将设备添加到总线中。
    • 对于平台设备,总线类型是 platform_bus_type

    C

    int bus_add_device(struct device *dev) { struct bus_type *bus = dev->bus; int error = 0; if (bus->p->drivers_autoprobe) { error = device_attach(dev); // 自动匹配驱动 } return error; }

  5. 通知驱动和用户层

    • 调用 device_add_groups() 添加设备属性(如 sysfs 文件)。
    • 调用 kobject_uevent() 发送 KOBJ_ADD 事件通知用户层。

4. 总线与设备的关联

当调用 device_add() 时,设备会被挂到总线 platform_bus 下:

  • pdev->dev.bus = &platform_bus_type 表示设备属于 platform_bus
  • device_add() 会调用 bus_add_device() 将设备挂到总线。
  • 在 platform_bus 的结构中定义了 match 函数,用于匹配设备和驱动。

总结流程

  1. 调用 platform_device_register()

    • 初始化设备结构体,调用 platform_device_add()
  2. 调用 platform_device_add()

    • 设置设备的总线类型为 platform_bus_type
    • 调用 device_add() 将设备添加到内核设备模型。
  3. 调用 device_add()

    • 将设备添加到内核的设备层次结构中。
    • 与总线关联,触发设备与驱动的匹配流程。
    • 发送 KOBJ_ADD 事件通知用户层。

通过这些步骤,设备最终被挂到虚拟的 platform_bus 总线上,并且可以被匹配到合适的驱动程序。

http://www.lryc.cn/news/587927.html

相关文章:

  • SQL ORM映射框架深度剖析:从原理到实战优化
  • SPL 轻量级多源混算实践
  • Redis集群方案——Redis分片集群
  • Linux 消息队列接收与处理线程实现
  • python的微竞网咖管理系统
  • P2802 回家
  • 国家互联网信息办公室关于发布第十二批深度合成服务算法备案信息的公告
  • 力扣算法--数青蛙与外观数列问题
  • 3.2 WPF 画散点图
  • 【Python3教程】Python3高级篇之MySQL - mysql-connector 驱动介绍及示例
  • 【WPF】WPF 自定义控件 实战详解,含命令实现
  • 深地之下的智慧触角:Deepoc具身智能如何为矿业机器人铸就“感知之核”
  • Mac (m1) Java 加载本地C共享库函数 .dylib 函数 Unable to load library ‘liblicense‘
  • 【爬虫】Python实现爬取京东商品信息(超详细)
  • 来时路,零帧起手到Oracle大师
  • FilterRegistationBean报错does not have type parameters。idea启动日志无明显报错提示冲突 kaki的博客
  • IDEA实现纯java项目并打包jar(不使用Maven,Spring)
  • Linux的相关学习
  • Oracle物化视图函数使用注意事项
  • Oracle 递归函数及 其他数据库 CTE 使用小计
  • SpringBoot集成SAP,本地IDEA启动和Windows服务器部署
  • 企业培训笔记:axios 发送 ajax 请求
  • iOS高级开发工程师面试——RunLoop
  • [Nagios Core] struct监控对象 | 配置.cfg加载为内存模型
  • CSS `:root` 伪类深入讲解
  • Reactor 模式详解
  • spring shell 基础使用
  • Transformer江湖录 第五章:江湖争锋 - BERT vs GPT
  • 20250714让荣品RD-RK3588开发板在Android13下长按关机
  • Bash常见条件语句和循环语句