简介
uboot是如何实现在不同的文件中调用U_BOOT_DRIVER(name)
接口注册驱动,就可以在初始化时找到对应驱动进行初始化。
注册驱动
API:U_BOOT_DRIVER(name)
/* Declare a new U-Boot driver */
#define U_BOOT_DRIVER(__name) \
ll_entry_declare(struct driver, __name, driver)
#define ll_entry_declare(_type, _name, _list) \
_type _u_boot_list_2_##_list##_2_##_name __aligned(4) \
__attribute__((unused)) \
__section(".u_boot_list_2_"#_list"_2_"#_name)
将驱动结构体编译为名称带有u_boot_list_2
的段,查看u-boot.map可以看到
.u_boot_list_2_driver_2_ccf_clk_divider
0x0000000093e805a0 0x78 drivers/clk/clk-divider.o
0x0000000093e805a0 _u_boot_list_2_driver_2_ccf_clk_divider
.u_boot_list_2_driver_2_ccf_clk_mux
0x0000000093e80618 0x78 drivers/clk/clk-mux.o
0x0000000093e80618 _u_boot_list_2_driver_2_ccf_clk_mux
.u_boot_list_2_driver_2_clk_composite
0x0000000093e80690 0x78 drivers/clk/clk-composite.o
0x0000000093e80690 _u_boot_list_2_driver_2_clk_composite
通过上述的过程,可以将每个注册的驱动分为不同的段,但是在运行时如何遍历找到所有的驱动段呢?
看到上面的u_boot_list_2_driver_2,对这个2有没有点奇怪,为什么是2,而不是其它值。
uboot找到注册驱动代码段的方法就是,设置一个驱动段的起始标记,再设置一个结束标记,通过查看u-boot.map看到,在注册驱动的起始处有.u_boot_list_2_driver_1
段,在结束处有u_boot_list_2_uclass_driver_3
段。
那怎么确保.u_boot_list_2_driver_1
一定在起始处,u_boot_list_2_uclass_driver_3
一定在结束处。方法是通过链接脚本实现
30 . = ALIGN(8);
31 . = .;
32 . = ALIGN(8);
33 .u_boot_list : {
34 KEEP(*(SORT(.u_boot_list*)));
35 }
其中,KEEP((SORT(.u_boot_list)));可以将名称前缀为u_boot_list的段进行排序,因此.u_boot_list_2_driver_1
会排最前面,u_boot_list_2_driver_2_xx
排在中间,.u_boot_list_2_driver_1
排在最后。