uboot版本:uboot-201711 要分析uclass之前,首先得搞清楚兩個巨集U_BOOT_DRIVER及U_BOOT_DEVICE的作用: 1.U_BOOT_DRIVER及U_BOOT_DEVICE巨集定義如下: 下麵具體分析如下: 例如: 根據上述巨集定義展開得到: 從上面我們可以看到聲明他們 ...
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之間的關係