环境
U-Boot版本:官方2023.04
开发板:ZYNQ 7000 ZC702Kit Rev1.1
使能参数
CONFIG_DM=y
CONFIG_DM_EVENT=y
CONFIG_OF_CONTROL=y
CONFIG_SYS_MALLOC_F_LEN=0x800
运行流程
initf_dm
+---bootstage_start
+---dm_init_and_scan
| +---dm_init
| | +---device_bind_by_name
| | | +---lists_driver_lookup_name
| | | \---device_bind_common
| | +---dev_set_ofnode
| | \---device_probe
| +---dm_scan
| | +---dm_scan_plat
| | +---dm_extended_scan
| | +---dm_scan_other
| | \---dm_probe_devices
| \---event_notify_null
\---bootstage_accum
bootstage
辅助性记录启动相关信息,比如当前 boot 阶段和某一阶段耗时。
bootstage_start
设置 gd->bootstage
变量标记当前启动阶段,并记下当前定时器计数值;bootstage_accum
再次读取计数值统计该阶段耗时(时钟数)。
dm_init_and_scan
struct global_data {
...
struct udevice *dm_root;
struct udevice *dm_root_f;
struct list_head uclass_root_s;
struct list_head *uclass_root;
...
}
全局变量 gd
定义了 dm 和 uclass 的根节点,通过 dm_init
初始化 root
节点,dm_scan
扫描设备树 gd->fdt_blob
定义的所有设备完成初始化。
dm_init
gd->uclass_root = &DM_UCLASS_ROOT_S_NON_CONST;
INIT_LIST_HEAD(DM_UCLASS_ROOT_NON_CONST);
device_bind_by_name(NULL, false, &root_info,
&DM_ROOT_NON_CONST);
dev_set_ofnode(DM_ROOT_NON_CONST, ofnode_root());
device_probe(DM_ROOT_NON_CONST);
根据配置参数精简后实际执行以上代码。
先设置 uclass_root,挂载到 gd->uclass_root_s,然后初始化链表。
device_bind_by_name
完成两项功能:lists_driver_lookup_name
通过 name 字段遍历 driver 列表查找 U_BOOT_DRIVER(root_driver) 定义的 root_driver 地址;device_bind_common
会创建 新的 udevice 和 uclass 作为 root 设备,完成和 root_driver 之间的绑定。
device_probe
对节点设备深度处理(TODO…)。
dm_scan
static int dm_scan(bool pre_reloc_only)
{
dm_scan_plat(pre_reloc_only);
dm_extended_scan(pre_reloc_only);
dm_scan_other(pre_reloc_only);
dm_probe_devices(gd->dm_root, pre_reloc_only);
}
- dm_scan_plat
扫描所有通过 U_BOOT_DRVINFO(_name) 创建的设备并且完成驱动绑定,然后链接到根节点。 - dm_extended_scan
扫描设备树定义的设备并且完成驱动绑定,然后链接到根节点。 - dm_scan_other
自定义的扫描部分。