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

本文深入解析U-Boot中的U_BOOT_DRIVER与U_BOOT_DEVICE宏定义,探讨其作用及如何组织驱动列表。通过具体实例说明宏如何展开,并解释链接脚本中关于驱动列表的处理,为理解U-Boot驱动架构提供清晰视角。

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

转载地址:https://www.cnblogs.com/gs1008612/p/8252845.html

uboot版本:uboot-201711

要分析uclass之前,首先得搞清楚两个宏U_BOOT_DRIVER及U_BOOT_DEVICE的作用:

1.U_BOOT_DRIVER及U_BOOT_DEVICE宏定义如下:

复制代码

 1 #define U_BOOT_DRIVER(__name)                        \
 2     ll_entry_declare(struct driver, __name, driver)
 3 
 4 #define U_BOOT_DEVICE(__name)                        \
 5     ll_entry_declare(struct driver_info, __name, driver_info)
 6 
 7 #define ll_entry_declare(_type, _name, _list)                \
 8     _type _u_boot_list_2_##_list##_2_##_name __aligned(4)        \
 9             __attribute__((unused,                \
10             section(".u_boot_list_2_"#_list"_2_"#_name)))

复制代码

下面具体分析如下:

例如:

复制代码

 1 U_BOOT_DRIVER(serial_s5p) = {
 2     .name    = "serial_s5p",
 3     .id    = UCLASS_SERIAL,
 4     .of_match = s5p_serial_ids,
 5     .ofdata_to_platdata = s5p_serial_ofdata_to_platdata,
 6     .platdata_auto_alloc_size = sizeof(struct s5p_serial_platdata),
 7     .probe = s5p_serial_probe,
 8     .ops    = &s5p_serial_ops,
 9     .flags = DM_FLAG_PRE_RELOC,
10 };

复制代码

根据上述宏定义展开得到:

复制代码

 1 ll_entry_declare(struct driver, serial_s5p, driver)
 2         struct driver _u_boot_list_2_driver_2_serial_s5p __aligned(4) __attribute__((unused, section(".u_boot_list_2_driver_2_serial_s5p"))) = {
 3             .name    = "serial_s5p",
 4             .id    = UCLASS_SERIAL,
 5             .of_match = s5p_serial_ids,
 6             .ofdata_to_platdata = s5p_serial_ofdata_to_platdata,
 7             .platdata_auto_alloc_size = sizeof(struct s5p_serial_platdata),
 8             .probe = s5p_serial_probe,
 9             .ops    = &s5p_serial_ops,
10             .flags = DM_FLAG_PRE_RELOC,
11         };

复制代码

从上面我们可以看到声明他们的时候对它们做了如下要求:

1.要求它们存放的时候4字节对齐,这通常是为了更方便的访问处理它们;
2.要求它们存放在一个各自独有的段里面

在链接脚本arch/arm/cpu/u-boot.lds中有如下定义:

1 . = ALIGN(4);  
2             .u_boot_list : {  
3             KEEP(*(SORT(.u_boot_list*)));  
4      }  

所有以.u_boot_list开头的段多将在这里存放,KEEP关键字是为了保证所有的段多被加进来,不要被链接器自作聪明的把某些它认为没有的段舍弃;
用宏U_BOOT_DRIVER和U_BOOT_DEVICE声明的变量将被分配到自己一个特有的段下,在链接的时候被组织到一起,具体可以在uboot编译成功后生成的u-boot.map中查看到u_boot_list段的相关信息如下:

注意到u_boot_list_2_driver_1和u_boot_list_2_driver_3,这段地址范围内即为驱动函数列表集合

 

搞清楚这两个关键宏后下篇将具体分析uclass,uclass_driver,udevice,driver之间的关系

### 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、付费专栏及课程。

余额充值