Linux設(shè)備樹詳解_第1頁
Linux設(shè)備樹詳解_第2頁
Linux設(shè)備樹詳解_第3頁
Linux設(shè)備樹詳解_第4頁
Linux設(shè)備樹詳解_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、1、 ARM Linux 社區(qū)為什么要引入設(shè)備樹Linux之父Linus Torvalds閑來無事,在翻看 ARM Linux代碼的時(shí)候,有一天終于忍不住了。他在2011 年 3 月 17 日的 ARM Linux 郵件列表中說道:"This whole ARM thing is a f*cking pain in the ass 。這句話迫使ARM Linux社區(qū)引入了設(shè)備樹。Linus Torvalds為什么會發(fā)飆呢而ARM Linux社區(qū)的牛人為什么又乖乖地聽話了你得首先理解Linux設(shè)備驅(qū)動框架中一個(gè)非常好的設(shè)計(jì):設(shè)備信息和驅(qū)動分離。為了說明設(shè)備信息和驅(qū)動分離的概念,這里用一

2、個(gè)簡單的模擬代碼來解釋:【例-1】實(shí)現(xiàn)一個(gè)代碼,把要使用的信息簡單寫死在代碼中:int add() /*模擬驅(qū)動代碼*/return 3+5; /*模擬設(shè)備信息*/優(yōu)點(diǎn):簡單缺點(diǎn):一旦加數(shù)和被加數(shù)發(fā)生變化就得改代碼改進(jìn)設(shè)計(jì)如下:【例-2】實(shí)現(xiàn)一個(gè)代碼,把要使用的信息和操作代碼分離開來:struct devint id;int x;int y;/*模擬設(shè)備信息結(jié)構(gòu)*/strcut drvint id;int (*add)(struct dev *info); /*模擬驅(qū)動結(jié)構(gòu)*/int add(struct dev *info) /* 模擬驅(qū)動代碼 */return info->x + i

3、nfo->y; /* 模擬設(shè)備信息-通過參數(shù)彳遞進(jìn)來*/struct drv drv = .id = 1,.add = add,;/*模擬設(shè)備信息*/struct dev dev = .id = 1,.x = 3,.y = 5, ; /*模擬總線初始化匹配設(shè)備信息和驅(qū)動代碼*/int bus() if(dev.id = drv.id) return drv.add(&dev); . 優(yōu)點(diǎn):不管加數(shù)和被加數(shù)怎么變化,不需要修改代碼,僅需要修改信息缺點(diǎn):結(jié)構(gòu)比較復(fù)雜那這個(gè)設(shè)備信息和驅(qū)動分離的設(shè)計(jì)跟驅(qū)動有什么關(guān)系呢熟悉硬件編程的同學(xué)都知道,硬件一般的構(gòu) 成可以使用下圖簡單表述:操作外設(shè)

4、的驅(qū)動代碼邏輯,只要硬件是一樣的,就不會變化。但是外設(shè)掛到不同的主機(jī)上,可能會 存在I/O地址的變化,如果有中斷也是一樣的,中斷號也可能不同。 這些I/O地址和中斷號就是設(shè)備信息,使用這些信息來操作控制硬件的代碼就是驅(qū)動。如果采用【例-1】的設(shè)計(jì)方式,那么同一個(gè)硬件外設(shè)接到不同的主機(jī),或是換了地址線/中斷線,設(shè)備信息就變化了,得去修改驅(qū)動。但是采用【例 -2】的方式進(jìn)行設(shè)計(jì),問題就迎刃而解:不管同樣的外設(shè) 硬件接到哪里或是那個(gè)平臺,其驅(qū)動代碼邏輯并不需要改動,而僅僅需要改變下設(shè)備信息,主要的就是I/O地址和中斷號。說了這么半天,跟引入設(shè)備樹有什么關(guān)系呢華清教學(xué)使用的開發(fā)板 (A8/A9)都使用

5、DM9000網(wǎng)卡芯片。DM9000驅(qū)動是開源的,在主線內(nèi)核源碼中就有。我們每次基于A8/A9板子移植的時(shí)候,DM9000驅(qū)動并沒有修改過,僅僅是選配了下,主要的工作是在板級文件中添加了設(shè)備信息。DM9000驅(qū)動使用的是platform框架,所以添加了一份 DM9000網(wǎng)卡芯片的platform_device 信息。問題來了,如果使用 C代碼的形式來 描述設(shè)備信息,則在內(nèi)核源碼中,將會有多份DM9000的platform_device 設(shè)備信息,造成了內(nèi)核代碼冗余。解決這個(gè)問題的辦法就是引入設(shè)備樹,改造【例 -2】來說明設(shè)備樹的作用?!纠?3】實(shí)現(xiàn)一個(gè)代碼,不僅把要使用的信息和操作代碼分離開來,

6、而且信息不是 C代碼編寫的, 而是文本配置文件保存的:struct devint id;int x;int y;;/*模擬設(shè)備信息結(jié)構(gòu)*/strcut drvint id;int (*add)(struct dev *info); /*模擬驅(qū)動結(jié)構(gòu)*/int add(struct dev *info) /* 模擬驅(qū)動代碼 */return info->x + info->y; /* 模擬設(shè)備信息-通過參數(shù)彳遞進(jìn)來*/struct drv drv = .id = 1,.add = add,;/*模擬設(shè)備樹-一個(gè)特殊的配置文件,xxx.dtbs的文本文件*/Dm9000x = 3;y

7、= 5;/*模擬總線初始化匹配設(shè)備信息和驅(qū)動代碼*/int bus()/*模擬設(shè)備樹初始化處理*/讀文件(xxx.dtbs);解析文彳內(nèi)容(根據(jù)設(shè)備樹的規(guī)則來解析);生成struct dev設(shè)備信息;if(dev.id = drv.id)return drv.add(&dev);如果像【例-3這樣,就可以解決大量設(shè)備信息的代碼冗余問題。推而廣之,系統(tǒng)的軟硬件信息都可以使用設(shè)備樹來描述。這樣的話, ARM Linux社區(qū)就不會因?yàn)橹?持板子和驅(qū)動越來越多造成內(nèi)核源碼中出現(xiàn)很多冗余代碼(主要是板級文件),僅僅需要移植者,把系統(tǒng)的軟硬件信息通過設(shè)備樹提供出來,選配一下內(nèi)核代碼,就可以了。2、

8、設(shè)備樹的概述2.1、 參考資料內(nèi)核源碼目錄Documentationdevicetree設(shè)備樹說明文檔內(nèi)核源碼drivers/of/源碼分析2.2、 基本概念設(shè)備樹是描述軟/硬件信息的,包含節(jié)點(diǎn)和屬性的一個(gè)樹形結(jié)構(gòu)。節(jié)點(diǎn)用以歸類描述了一個(gè)硬件信息 或是軟件信息(好比文件系統(tǒng)的目錄)。節(jié)點(diǎn)內(nèi)描述了一個(gè)或多個(gè)屬性,屬性是鍵值對,描述具體的軟/硬信息。簡單形式如下:/node property=value;.child_nodechild_property=value;.;.;.;說明如下:/:根節(jié)點(diǎn),節(jié)點(diǎn)使用“的語法描述作用范圍node :根節(jié)點(diǎn)下的一個(gè)子節(jié)點(diǎn)child_node : node節(jié)點(diǎn)

9、下的一個(gè)子節(jié)點(diǎn)property : node節(jié)點(diǎn)內(nèi)描述的屬性,value就是屬性的值(任意字節(jié)數(shù)據(jù),可以是整型、字符串、數(shù) 組、等等)。描述行以“結(jié)束在ARM Linux社區(qū)為什么要引入設(shè)備樹中,已經(jīng)討論過設(shè)備樹的使用方式。簡而言之:內(nèi)核初始化時(shí),以配置的文件形式讀取設(shè)備樹文件的內(nèi)容,并解析后生成相應(yīng)的軟/硬件信息,以供相應(yīng)的內(nèi)核代碼使用。編寫設(shè)備樹文件是以.dts的文本文件存儲的,主要是為了修改、添加編輯方便。那么問題來了,如果純文本解析的話,顯然比較慢且麻煩。譬如如果屬性值是一個(gè)I/O地址:,如果是字符串的形式存儲,那么就是一個(gè)字符串,內(nèi)核代碼解析這個(gè)信息的時(shí)候還得轉(zhuǎn)換成整型數(shù),不僅僅是慢

10、,無形設(shè)備樹文件大小還會增加不少,還得增加更多的初始化代碼。所以.dts的設(shè)備樹文件,在內(nèi)核使用前需要轉(zhuǎn)換一次,主要是把繁復(fù)的語法形式及屬性值轉(zhuǎn)換成字節(jié)數(shù)據(jù)(特殊的數(shù)據(jù)結(jié)構(gòu)),而非符號。.dts文件轉(zhuǎn)換后是.dtb的二進(jìn)制文件。3、節(jié)點(diǎn)3.1、 命名節(jié)點(diǎn)的命名以字母、數(shù)字、_、等等符號構(gòu)成。常見的命令方式如下:A、以設(shè)備名”為節(jié)點(diǎn)名,范例:DM9000命名如下:/.dm9000.;.;B、以 設(shè)備I/O地址”為節(jié)點(diǎn)名I/O地址”,范例:DM9000在主機(jī)端的I/O地址為0x8000 0000 ,可以命名如下:/.;.;C、以設(shè)備類型I/O地址”為節(jié)點(diǎn)名I/O地址”,范例:DM9000在主機(jī)端的

11、I/O地址為0x8000 0000 ,可以命名如下:/;3.2、 節(jié)點(diǎn)路徑A、/.dm9000.;.;節(jié)點(diǎn)名:dm9000節(jié)點(diǎn)路徑:/dm9000B、/.;.;節(jié)點(diǎn)名:dm9000節(jié)點(diǎn)路徑:C、/.;.;節(jié)點(diǎn)名:ethernet節(jié)點(diǎn)路徑:3.3、 節(jié)點(diǎn)引用/aliases demo = &demo;;.;.;節(jié)點(diǎn)名:demo節(jié)點(diǎn)路徑:引用路徑:demo(等價(jià),解決路徑名過程的問題)設(shè)備樹中引用節(jié)點(diǎn)的范例:&demo.;3.4、 節(jié)點(diǎn)查找有時(shí)候,分享內(nèi)核代碼或是編寫內(nèi)核代碼的時(shí)候,可能會涉及使用查找節(jié)點(diǎn)函數(shù)。內(nèi)核提供很多內(nèi) 核函數(shù)來查找(解析設(shè)備樹)一個(gè)指定節(jié)點(diǎn):A、路徑查找/*

12、 功能:通過路徑查找指定節(jié)點(diǎn)* 參數(shù):* const char *path - 節(jié)點(diǎn)路徑,可以是路徑,也可以是路徑引用* 返回值:* 成功:得到節(jié)點(diǎn)對象的首地址;失敗:NULL* /struct device_node *of_find_node_by_path(const char *path);B、節(jié)點(diǎn)名查找/* 功能:通過節(jié)點(diǎn)名查找指定節(jié)點(diǎn)* 參數(shù):* struct device_node *from -指向開始路徑的節(jié)點(diǎn),如果為 NULL ,則從根節(jié)點(diǎn)開始* const char *name- 節(jié)點(diǎn)名* 返回值:*成功:得到節(jié)點(diǎn)對象的首地址;失?。篘ULL* /struct devic

13、e_node *of_find_node_by_name(struct device_node *from, const char *name);C、通過compatible 屬性查找/* 功能:通過compatible屬性查找指定節(jié)點(diǎn)* 參數(shù):* struct device_node *from -指向開始路徑的節(jié)點(diǎn),如果為 NULL ,則從根節(jié)點(diǎn)開始* const char *type -節(jié)點(diǎn)類型,可以為 NULL* const char *compat - 指向節(jié)點(diǎn)的 compatible 屬性的值(字符串)的首地址* 返回值:* 成功:得到節(jié)點(diǎn)對象的首地址;失?。篘ULL* /stru

14、ct device_node *of_find_compatible_node(struct device_node *from,const char *type, const char *compat);設(shè)備ID表結(jié)構(gòu)struct of_device_id char name32; /* 設(shè)備名 */char type32;/* 設(shè)備類型 */char compatible128;/* 用于與設(shè)備樹 compatible 屬性值匹配的字符串*/const void *data; /* 私有數(shù)據(jù) */;/* 功能:通過compatible屬性查找指定節(jié)點(diǎn)* 參數(shù):* struct device

15、_node *from -指向開始路徑的節(jié)點(diǎn),如果為 NULL ,則從根節(jié)點(diǎn)開始* const struct of_device_id *matches - 指向設(shè)備 ID 表* 注意ID表必須以NULL結(jié)束* 范例: const struct of_device_id mydemo_of_match口 = .compatible = "fs4412,mydemo", ,;* 返回值:* 成功:得到節(jié)點(diǎn)對象的首地址;失?。篘ULL* /struct device_node *of_find_matching_node(struct device_node *from,con

16、st struct of_device_id *matches);D、查找子節(jié)點(diǎn)/* 功能:查找指定節(jié)點(diǎn)的子節(jié)點(diǎn)* 參數(shù):* const struct device_node *node -指向要查找子節(jié)點(diǎn)的父節(jié)點(diǎn)* const char *name -子節(jié)點(diǎn)名* 返回值:* 成功:得到子節(jié)點(diǎn)對象的首地址佚?。篘ULL* /struct device_node *of_get_child_by_name(const struct device_node *node,const char *name);3.5、 節(jié)點(diǎn)內(nèi)容合并有時(shí)候,一個(gè)硬件設(shè)備的部分信息不會變化,但是部分信息是可能會變化的,就出

17、現(xiàn)了節(jié)點(diǎn)內(nèi)容合 并。即:先編寫好節(jié)點(diǎn),僅僅描述部分屬性值;使用者后加一部分屬性值。在同級路徑下,節(jié)點(diǎn)名相同的兩個(gè)'節(jié)點(diǎn)實(shí)際是一個(gè)節(jié)點(diǎn)。/*參考板的已經(jīng)編寫好的 node節(jié)點(diǎn)*/nodeitem1=value;/*移植者添加的node節(jié)點(diǎn)*/nodeitem2=value;等價(jià)于:/nodeitem1=value;item2=value;;3.6、 節(jié)點(diǎn)內(nèi)容替換有時(shí)候,一個(gè)硬件設(shè)備的部分屬性信息可能會變化,但是設(shè)備樹里面已經(jīng)描述了所有的屬性值,使 用者可以添加已有的屬性值,以替換原有的屬性值,就出現(xiàn)了節(jié)點(diǎn)內(nèi)容替換。另外,節(jié)點(diǎn)的內(nèi)容即使不會變化,但是可能不會使用。在同級路徑下,節(jié)點(diǎn)名相同的

18、 兩個(gè)'節(jié)點(diǎn)實(shí)際是一個(gè)節(jié)點(diǎn)。內(nèi)容替換的常見形式之一:/*參考板的已經(jīng)編寫好的 node節(jié)點(diǎn)*/nodeitem=value1;;/*移植者添加的node節(jié)點(diǎn)*/nodeitem=value2;;等價(jià)于:/nodeitem=value2;;內(nèi)容替換的常見形式之二:/*參考板的已經(jīng)編寫好的 node節(jié)點(diǎn)*/nodeitem=value;status = "disabled";;/*移植者添加的node節(jié)點(diǎn)*/nodestatus = "okay";等價(jià)于:/nodeitem=value;status = "okay";3.7、 節(jié)點(diǎn)內(nèi)容引用有時(shí)候,一個(gè)節(jié)點(diǎn)需要使用到別的節(jié)點(diǎn)的屬性值,就需要引用的概念。有時(shí)候在設(shè)備樹編寫時(shí),要 替換節(jié)點(diǎn)屬性值,或是合并節(jié)點(diǎn)的屬性值,也會使用引用。A、引用節(jié)點(diǎn)完成屬性值的替換及合并:/*參考板的已經(jīng)編寫好的 node節(jié)點(diǎn)*/node :item1=value;status = &

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論