uboot驱动模型(DM)分析(二)

本文深入剖析U-Boot设备模型中的关键概念如uclass、uclass_driver、udevice及driver的关系,并通过代码实例展示了这些组件如何在初始化过程中相互作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上篇分析了两个关键宏U_BOOT_DRIVER及U_BOOT_DEVICES的作用,有了上篇的基础,本文将分析:

1.上篇中的uboot_list段中的信息如何被用起来?

2.uclass,uclass_driver,udevice,driver之间的关系?

 

从board_r.c中的initr_dm函数开始分析:

1 static const struct driver_info root_info = {
2     .name        = "root_driver",
3 };

 1 /* This is the root driver - all drivers are children of this */
 2 U_BOOT_DRIVER(root_driver) = {
 3     .name    = "root_driver",
 4     .id    = UCLASS_ROOT,
 5     .priv_auto_alloc_size = sizeof(struct root_priv),
 6 };
 7 
 8 /* This is the root uclass */
 9 UCLASS_DRIVER(root) = {
10     .name    = "root",
11     .id    = UCLASS_ROOT,
12 };

 

initr_dm

  ret = dm_init_and_scan(false);

    dm_init

      INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST);  //#define DM_UCLASS_ROOT_NON_CONST (((gd_t *)gd)->uclass_root) 创建头结点gd->uclass_root

      ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);

        drv = lists_driver_lookup_name(info->name);  //lists_driver_lookup_name("root_driver")  

             struct driver *drv =ll_entry_start(struct driver, driver);  //通过上篇分析,此处得到的是uboot_list_2_driver_1的地址

              const int n_ents = ll_entry_count(struct driver, driver);  //uboot_list_2_driver_3-uboot_list_2_driver_1即得到长度

              for (entry = drv; entry != drv + n_ents; entry++) {    //遍历,通过name字段匹配,匹配成功得到driver结构体地址

                if (!strcmp(name, entry->name))
                   return entry;
              }

           device_bind_common(parent, drv, info->name, (void *)info->platdata, 0, ofnode_null(), platdata_size, devp);

            ret = uclass_get(drv->id, &uc);            

              struct uclass *uc;

              uc = uclass_find(id);              

              if (!uc)

                return uclass_add(id, ucp); //通过上面得到的drv中的id字段(UCLASS_ROOT)进行匹配,匹配成功得到对应的uclass_driver结构体地址

              uc->uc_drv = uc_drv;  //uclass root的uclass_driver指向uclass_driver root   

              INIT_LIST_HEAD(&uc->sibling_node);
              INIT_LIST_HEAD(&uc->dev_head);
              list_add(&uc->sibling_node, &DM_UCLASS_ROOT_NON_CONST);

            .......

            //关键代码如下

            INIT_LIST_HEAD(&dev->sibling_node);
            INIT_LIST_HEAD(&dev->child_head);
            INIT_LIST_HEAD(&dev->uclass_node);

            dev->name = name;

            dev->node = node;

            dev->parent = parent;

            dev->driver = drv;

            dev->uclass = uc;

            ......

            ret = uclass_bind_device(dev);

              uc = dev->uclass;

              list_add_tail(&dev->uclass_node, &uc->dev_head);

---------------------------------------------------------------------------------------------------------------------------------------------

经过上述源码阅读,下面将上述关系用图的形式更直观的表现出来:

 

        

  

        

 

转载于:https://www.cnblogs.com/gs1008612/p/8253213.html

### U-Boot 设备模型 (dm) 驱动文档和实例 #### 理解 U-Boot 的设备模型框架 U-Boot 中引入了设备模型(Device Model, DM),旨在提供一种统一的方式来管理和配置硬件资源。DM 提供了一种抽象层,使得不同类型的设备可以被一致地处理[^1]。 #### 初始化过程中的角色 当 U-Boot 进入其主要执行阶段时,会经历一系列复杂的初始化操作,在此期间设备模型扮演着重要角色。特别是对于那些需要早期启动支持的组件来说,DM 能够确保这些外设得到恰当设置并准备就绪[^2]。 #### 编写自定义驱动程序指南 为了创建一个新的基于 DM 架构下的驱动模块,开发者应当遵循如下原则: - **注册新平台数据结构**:通过 `uclass_driver` 结构体来描述特定类别的通用行为; - **实现 probe 函数**:这是每个具体设备都必需提供的入口点之一;它负责完成实际硬件资源配置工作以及任何必要的软件状态初始化。 - **利用宏简化开发**:如 `DECLARE_GLOBAL_DATA_PTR` 可帮助访问全局变量而无需显式传递指针参数。 下面给出一段简单的 LED 控制器驱动代码片段作为例子: ```c // drivers/led/uclass.c static int led_bind(struct udevice *dev) { printf("Binding %s\n", dev->name); return 0; } static const struct udevice_id led_ids[] = { { .compatible = "example-led" }, { } }; U_BOOT_DRIVER(led_example) = { .name = "led_example", .id = UCLASS_LED, .of_match = led_ids, .bind = led_bind, }; ``` 上述代码展示了如何声明一个名为 `"led_example"` 的驱动,并将其绑定到兼容字符串为 `"example-led"` 的节点上。这里还实现了基本的日志输出功能用于调试目的。 #### 使用命令行接口测试驱动 一旦完成了驱动编写之后,则可以通过 U-Boot 命令提示符来进行交互式的验证。例如,假设已经加载了一个 SPI NOR Flash 存储芯片的支持库,则可通过输入相应指令查看当前连接情况或者读取指定地址处的数据内容。 ```shell => sf probe 0 # 探测第零号SPI flash设备 SF: Detected w25q80bv with page size 256 Bytes, erase size 4 KiB, total 1 MiB. ``` 以上命令将会尝试识别编号为 0 的 SPI NOR Flash 并打印出检测结果摘要信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值