1. linux驱动开发设备树和总线之间的关系
在 Linux 系统中,设备树(Device Tree)是一种数据结构,它用于描述硬件结构,帮助内核在启动时确定硬件设备的位置和如何使用它们。在设备树中,节点表示硬件设备,而边表示设备之间的关系。
总线(Bus)是用于在计算机系统中传输数据的通道。它通常是一组连接设备的线路,并允许设备之间交换数据。在 Linux 中,总线也在设备树中表示为节点,并且设备节点与总线节点之间存在边。
因此,在 Linux 系统中,设备树用于描述硬件结构,其中包含设备和总线,以及它们之间的关系。在驱动程序开发中,开发人员通常使用设备树来确定特定设备的位置和如何与其通信。
2. 如何修改设备树中的电源信息
首先,按照yocto 查询方法中的dts查询的方法找到对应的dts文件,或者在BSP版本、设备树、config文件对照表 / BSP version, device tree, config file cross reference table中查找。如果在 imx6qdl-phytec-peb-wlbt-01.dtsi 文件中,修改了 imx6dl.dtsi 中的一个配置,则该配置由 imx6qdl-phytec-peb-wlbt-01.dtsi 中的配置为准。同样的道理,该文件的后面也是对其他文件中的一些配置进行一些修改。
3. 璁惧囨爲鍩烘湰璇娉曞強灞炴у垎鏋
鍦ㄧ‖浠朵笘鐣屼腑锛岃惧囨爲锛圖evice Tree锛夊氨鍍忎竴搴х粨鏋勫寲鐨勬ˉ姊侊紝杩炴帴鐫鎿嶄綔绯荤粺涓庣‖浠躲傚畠鏄涓绉嶅己澶х殑鏁版嵁妯″瀷锛屼互C璇瑷缁撴瀯浣撶殑褰㈠紡锛屼负Linux鍐呮牳鍒濆嬪寲璁惧囨彁渚涗簡鍏抽敭淇℃伅銆傝╂垜浠涓璧锋帰绱㈠畠鐨勮捣婧愩侀噸瑕佹т互鍙婂唴鏍镐腑涓嶅彲鎴栫己鐨勬枃浠躲
鑷2011骞磋捣锛岃惧囨爲鍦ˋRM Linux鍐呮牳涓宕闇插ご瑙掞紝瀹冪殑寮曞叆鏄涓轰簡绠鍖栦唬鐮佺$悊锛岃В鍐冲唴鏍3.x涔嬪墠骞冲彴鏂囦欢鎻忚堪纭浠剁殑鍐椾綑闂棰樸傜幇鍦锛岃惧囨爲鎴愪负浜嗛┍鍔ㄧ▼搴忎笌纭浠朵氦浜掔殑鏍稿績缁勪欢锛屾棤璁烘槸dts锛圖evice Tree Source锛屾簮鏂囨湰锛夌殑ASCII鏂囨湰鎻忚堪锛岃繕鏄缂栬瘧鍚庣殑dtb锛圖evice Tree Blob锛屼簩杩涘埗鏂囦欢锛夛紝閮藉湪鏋勫缓鍜岀淮鎶ょ‖浠惰惧囩殑鐢熸佺郴缁熶腑鍙戞尌鐫鍏抽敭浣滅敤銆
璁惧囨爲鐢变竴绯诲垪鑺傜偣鏋勬垚锛屾瘡涓鑺傜偣閮芥湁鍏剁嫭鐗圭殑鍚嶇О瑙勫垯銆傝妭鐐瑰悕鐢卞瓧绗︺佹暟瀛楀拰鈥-鈥濈粍鎴愶紝闀垮害闄愬埗鍦31涓瀛楃︿互鍐咃紝閫氬父鍙嶆槧鍑鸿惧囩被鍨嬶紝鑰寀nit-address鍒欐爣璁拌惧囩殑鐗╃悊浣嶇疆銆備緥濡傦細
閫氳繃鑺傜偣鐨刢ompatible灞炴э紙濡傗渄avicom,dm9000鈥濓級锛岄┍鍔ㄧ▼搴忓彲浠ョ簿纭鍖归厤璁惧囧拰椹卞姩銆俛ddress灞炴х敤浜庢弿杩板湴鍧锛屽#address-cells鍜#size-cells瀹氫箟浜嗗瓙鑺傜偣reg灞炴х殑鍦板潃鍗曞厓鍜岄暱搴︺俰nterrupt灞炴у垯绠$悊涓鏂淇″彿锛岄氳繃interrupt-parent鍜宨nterrupts鏉ラ厤缃涓鏂鎺у埗鍣ㄣ
涓句釜渚嬪瓙锛屽綋鎻忚堪鐗囬夊拰鍦板潃鏄犲皠鏃讹紝濡傜墖閫0鍋忕Щ0鏄犲皠鍒癈PU鍦板潃绌洪棿0x10100000~0x10110000锛屼腑鏂鎺у埗鍣ㄧ殑璁剧疆閫氳繃#interrupt-cells鏉ュ畾涔変腑鏂鎻忚堪绗︾殑缁撴瀯銆
GPIO鎺у埗鍣ㄧ殑绠$悊閫氳繃gpio-controller灞炴у0鏄庯紝#gpio-cells鍒欏畾涔変簡GPIO鑺傜偣灞炴х殑鍗曞厓鍐呭癸紝鍖呮嫭寮曠敤GPIO鑺傜偣鍒鍚嶃佹爣鍙峰拰宸ヤ綔妯″紡銆傚湪鐗╄仈缃戠殑澶嶆潅涓栫晫閲岋紝姝g‘鐞嗚В鍜屼娇鐢ㄨ繖浜涘睘鎬ф槸鍏抽敭锛屼互纭淇濊惧囩殑楂樻晥杩愪綔鍜屽伐璧勫為暱銆
4. linux鍔犺浇dts鐨勬椂鍊欎細鍒涘缓璁惧囪妭鐐瑰悧
From:http://m.blog.csdn.net/blog/liliyaya/9188193
1. 鍦\kernel\of\fdt.c 涓鏈夊備笅鍒濆嬪寲鍑芥暟 娉ㄩ噴涓婏細灞曞紑璁惧囨爲锛屽垱寤篸evice_nodes鍒板叏灞鍙橀噺allnodes涓
void __init unflatten_device_tree(void)
{
__unflatten_device_tree(initial_boot_params, &allnodes,
early_init_dt_alloc_memory_arch);
/* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
of_alias_scan(early_init_dt_alloc_memory_arch);
}
unflatten_device_tree鍑芥暟琚玸etup_arch鍑芥暟璋冪敤锛
鍥犱负鎴戜滑浣跨敤寰楁槸arm骞冲彴鎵浠ュ瓨鍦\kernel\arch\arm\kernel\setup.c涓
void __init setup_arch(char **cmdline_p)
{
unflatten_device_tree()
}
setup_arch鍑芥暟鍦╧ernel鍚鍔ㄦ槸琚璋冪敤锛屽備笅鍚鍔╧ernel瀛樺湪\kernel\init\main.c涓
asmlinkage void __init start_kernel(void)
{
setup_arch(&command_line);
}
杩欎簺宸ヤ綔瀹屾垚瑙f瀽DTS鏂囦欢銆備繚瀛樺埌鍏ㄥ眬閾捐〃allnodes涓銆
2銆佸湪makefile涓鏈夎繖娈佃瘽鏉ョ紪璇慸ts鏂囦欢锛
$(obj)/A20%.dtb: $(src)/dts/A20%.dts FORCE
$(call if_changed_dep,dtc)
$(obj)/A68M%.dtb: $(src)/dts/A68M%.dts FORCE
$(call if_changed_dep,dtc)
鍜.c鏂囦欢鐢熸垚.o鏂囦欢涓鏍 鍥炵敓鎴.dtb鏂囦欢銆傚湪
/home/liyang/workspace/SZ_JB-mr1-8628-bsp-1012/out/target/proct/msm8226/obj/KERNEL_OBJ/arch/arm/boot
鐩褰曚笅锛屼笌zimage涓涓鐩褰曘
3銆
鍦 board-8226.c涓鏈夊垵濮嬪寲鍑芥暟-->鍚鍔ㄨ嚜鍔ㄦ帀鐢
void __init msm8226_init(void)
{
of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
}
of_platform_populate鍦╧ernel\driver\of\platform.c涓瀹氫箟锛屽洖鏌ヨ
root = root ? of_node_get(root) : of_find_node_by_path("/");
for_each_child_of_node(root, child)
{
rc = of_platform_bus_create(child, matches, lookup, parent, true);
if (rc)
break;
}
of_node_put(root);
鍦ㄨ繖閲岀敤鍒板緱鍑芥暟of_find_node_by_path浼氭渶缁堣皟鐢ㄥ埌kernel\driver\of\base.c涓寰楀嚱鏁
struct device_node *of_find_node_by_path(const char *path)
{
閬嶅巻绗1姝ヤ腑寰梐llnodes鎵惧埌鏍硅妭鐐
}
of_platform_bus_create()鍑芥暟涓鍒涘缓寰楀唴瀹瑰瓨鍦ㄤ簡 adata涓銆
浠ヤ笅鍐呭逛负杞杞斤細
锛2锛変娇鐢―TS娉ㄥ唽鎬荤嚎璁惧囩殑杩囩▼
浠ラ珮閫8974骞冲彴涓轰緥锛屽湪娉ㄥ唽i2c鎬荤嚎鏃讹紝浼氳皟鐢ㄥ埌qup_i2c_probe()鎺ュ彛锛岃ユ帴鍙g敤浜庣敵璇锋荤嚎璧勬簮鍜屾坊鍔爄2c閫傞厤鍣ㄣ傚湪鎴愬姛娣诲姞i2c閫傞厤鍣ㄥ悗锛屼細璋冪敤of_i2c_register_devices()鎺ュ彛銆傛ゆ帴鍙d細瑙f瀽i2c鎬荤嚎鑺傜偣鐨勫瓙鑺傜偣锛堟寕杞藉湪璇ユ荤嚎涓婄殑i2c璁惧囪妭鐐癸級锛岃幏鍙杋2c璁惧囩殑鍦板潃銆佷腑鏂鍙风瓑纭浠朵俊鎭銆傜劧鍚庤皟鐢╮equest_mole()鍔犺浇璁惧囧瑰簲鐨勯┍鍔ㄦ枃浠讹紝璋冪敤i2c_new_device()锛岀敓鎴恑2c璁惧囥傛ゆ椂璁惧囧拰椹卞姩閮藉凡鍔犺浇锛屼簬鏄痙rvier閲岄潰鐨刾robe鏂规硶灏嗚璋冪敤銆傚悗闈㈡祦绋嬪氨鍜屼箣鍓嶄竴鏍蜂簡銆
绠鑰岃█涔嬶紝Linux閲囩敤DTS鎻忚堪璁惧囩‖浠朵俊鎭鍚庯紝鐪佸幓浜嗗ぇ閲忔澘鏂囦欢鍨冨溇淇℃伅銆侺inux鍦ㄥ紑鏈哄惎鍔ㄩ樁娈碉紝浼氳В鏋怐TS鏂囦欢锛屼繚瀛樺埌鍏ㄥ眬閾捐〃allnodes涓锛屽湪鎺夌敤.init_machine鏃讹紝浼氳窡鎹產llnodes涓鐨勪俊鎭娉ㄥ唽骞冲彴鎬荤嚎鍜岃惧囥傚煎緱娉ㄦ剰鐨勬槸锛屽姞杞芥祦绋嬪苟涓嶆槸鎸夋壘浠庢爲鏍瑰埌鏍戝彾鐨勬柟寮忛掑綊娉ㄥ唽锛岃屾槸鍙娉ㄥ唽鏍硅妭鐐逛笅鐨勭涓绾у瓙鑺傜偣锛岀浜岀骇鍙婁箣鍚庣殑瀛愯妭鐐规殏涓嶆敞鍐屻侺inux绯荤粺涓嬬殑璁惧囧ぇ澶氶兘鏄鎸傝浇鍦ㄥ钩鍙版荤嚎涓嬬殑锛屽洜姝ゅ湪骞冲彴鎬荤嚎琚娉ㄥ唽鍚庯紝浼氭牴鎹產llnodes鑺傜偣鐨勬爲缁撴瀯锛屽幓瀵绘壘璇ユ荤嚎鐨勫瓙鑺傜偣锛屾墍鏈夌殑瀛愯妭鐐瑰皢琚浣滀负璁惧囨敞鍐屽埌璇ユ荤嚎涓娿
5. 如何在Yocto中使用自己的设备树dts和内核配置
LinuxandtheDeviceTreeLinux内核设备树数据使用模型。OpenFirmwareDeviceTree(DT)是一个数据结构,也是一种描述硬件的语言。准确地说,它是一种能被操作系统解析的描述硬件的语言,这样操作系统就不需要把硬件平台的细节在代码中写死。从结构上来说,DT是一个树形结构,或者有名结点组成的非循环图,结点可能包含任意数量的有名属性,有名属性又可以包含任意数量的数据。同样存在一种机制,可以创建从一个结点到正常树形结构之外的链接。从概念上讲,一套通用的使用方法,即bindings。Bindings定义了数据如何呈现在设备树中,怎样描述典型的硬件特性,包括数据总线,中断线,GPIO连接以及外设等。尽可能多的硬件被描述从而使得已经存在的bindings最大化地使用源代码,但是由于属性名和结点名是简单字符串,可以通过定义新结点和属性的方式很方便地扩展已经存在的bindings或者创建一个新的binding。在没有认真了解过已经存在的bindings的情况下,创建一个新的binding要慎之又慎。对于I2C总线,通常有两种不同的,互不相容的bindings出现,就是因为新的binding创建时没有研究I2C设备是如何在当前系统中被枚举的。1.历史略2.数据模型请参考DeviceTreeUsage章节2.1HighLevelView必须要认识到的是,DT是一个描述硬件的数据结构。它并没有什么神奇的地方,也不能把所有硬件配置的问题都解决掉。它只是提供了一种语言,将硬件配置从LinuxKernel支持的boardanddevicedriver中提取出来。DT使得board和device变成数据驱动的,它们必须基于传递给内核的数据进行初始化,而不是像以前一样采用hardcoded的方式。观念上说,数据驱动平台初始化可以带来较少的代码重复率,使得单个内核映像能够支持很多硬件平台。Linux使用DT的三个主要原因:1)平台识别(PlatformIdentification)2)实时配置(RuntimeConfiguration)3)设备植入(DevicePopulation)2.2平台识别第一且最重要的是,内核使用DT中的数据去识别特定机器。最完美的情况是,内核应该与特定硬件平台无关,因为所有硬件平台的细节都由设备树来描述。然而,硬件平台并不是完美的,所以内核必须在早期初始化阶段识别机器,这样内核才有机会运行特定机器相关的初始化序列。大多数情况下,机器识别是与设备树无关的,内核通过机器的核心CPU或者SOC来选择初始化代码。以ARM平台为例,setup_arch()会调用setup_machine_fdt(),后者遍历machine_desc链表,选择最匹配设备树数据的machine_desc结构体。它是通过查找设备树根结点的compatible属性并与machine_desc->dt_compat进行比较来决定哪一个machine_desc结构体是最适合的。Compatible属性包含一个有序的字符串列表,它以确切的机器名开始,紧跟着一个可选的board列表,从最匹配到其他匹配类型。以TIBeagleBoard的compatible属性为例,BeagleBoardxMBoard可能描述如下:compatible="ti,omap3-beagleboard","ti,omap3450","ti,omap3";compatible="ti,omap3-beagleboard-xm","ti,omap3450","ti,omap3";在这里,”ti,omap3-beagleboard-xm”是最匹配的模型,"ti,omap3450"次之,"ti,omap3"再次之。机敏的读者可能指出,BeaglexM也可以声明匹配"ti,omap3-beagleboard",但是要注意的是,板级层次上,两个机器之间的变化比较大,很难确定是否兼容。从顶层上来看,宁可小心也不要去声明一个board兼容另外一个。值得注意的情况是,当一个board承载另外一个,例如一个CPU附加在一个board上。(两种CPU支持同一个board的情况)