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 网络驱动开发概述 U-Boot 是种广泛使用的引导加载程序,其核心功能之是支持多种硬件设备的初始化和配置。在网络驱动方面,U-Boot 提供了个模块化的框架来实现对不同网络芯片的支持[^1]。 #### 1. 网络驱动的基础架构 U-Boot 中的网络驱动基于 Device Model (DM) 架构设计。Device Model 是 U-Boot 的个重要特性,它提供了种统的方式来管理设备及其驱动程序。对于网络驱动而言,开发者可以通过 DM 框架注册新的网卡驱动并完成必要的初始化工作[^2]。 以下是典型的 U-Boot 网络驱动开发流程: #### 2. 创建自定义网络驱动 为了支持个新的网络接口控制器(NIC),需要编写相应的驱动代码。通常情况下,这涉及以下几个部分: - **头文件声明**:定义数据结构以及函数原型。 - **驱动实现**:包括 `probe` 函数用于初始化硬件资源;`send` 和 `recv` 方法分别处理发送和接收包的操作。 - **设备树绑定**:描述该 NIC 所需的寄存器地址范围和其他属性。 下面展示段简化版的伪代码作为参考: ```c #include <common.h> #include <dm.h> // 定义私有数据结构体 struct my_net_dev { void *base_addr; }; static int my_probe(struct udevice *dev) { struct my_net_dev *priv = dev_get_priv(dev); priv->base_addr = dm_ioremap(dev, CONFIG_MY_NET_BASE_ADDR); if (!priv->base_addr) return -ENOMEM; // 初始化硬件... return 0; } static const struct eth_ops my_eth_ops = { .start = my_start, .stop = my_stop, .sendpacket = my_send_packet, .recvpacket = my_recv_packet, }; static const struct udevice_id my_ids[] = { { .compatible = "mycompany,my-net-controller" }, { } }; U_BOOT_DRIVER(my_network_driver) = { .name = "my_network", .id = UCLASS_ETH, .of_match = my_ids, .ops = &my_eth_ops, .priv_auto_alloc_size = sizeof(struct my_net_dev), .probe = my_probe, }; ``` 上述代码片段展示了如何构建个基本的网络驱动程序,并利用 DM API 进行内存映射、中断设置等功能调用。 #### 3. 设备树中的配置 除了驱动本身外,还需要更新设备树源文件(DTS)。例如,在 DTS 文件中添加如下节点即可指定新加入的以太网控制器参数: ```dts ethernet@80000000 { compatible = "mycompany,my-net-controller"; reg = <0x80000000 0x1000>; /* 基础物理地址及长度 */ interrupts = <17>; }; ``` 此段落说明了如何通过修改 `.dts` 来适配具体的硬件平台需求[^3]。 #### 4. 测试与验证 编译完成后,可通过命令行工具测试网络连接状态。常用指令如 `ping`, `dhcp` 或者手动配置 IP 地址等方式确认通信正常运行。 --- ### 总结 综上所述,针对 U-Boot 下的新网络驱动开发主要围绕着 DM 模型展开,从驱动编码到设备树调整均不可或缺。借助官方文档和技术社区分享的经验案例能够加速整个过程的学习曲线[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值