




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
1、Linux 設(shè)備驅(qū)動開發(fā)詳解第 1 章、設(shè)備驅(qū)動概述第 1 章設(shè)備驅(qū)動概述本章將帶您走進 Linux 設(shè)備驅(qū)動的精彩世界。1.1 節(jié)講解了設(shè)備驅(qū)動的概念和作用。1.2 節(jié)和 1.3 節(jié)分別講述無操作系統(tǒng)和有操作系統(tǒng)情況下設(shè)備驅(qū)動的設(shè)計方法,通過分析講解設(shè)備驅(qū)動與硬件和操作系統(tǒng)的關(guān)系。1.4 節(jié)對 Linux 操作系統(tǒng)的設(shè)備驅(qū)動進行了概要性的介紹,講解設(shè)備驅(qū)動與系統(tǒng)軟硬件的關(guān)系,分析了 Linux 設(shè)備驅(qū)動的重點難點和學(xué)習(xí)方法。本章的最后給出了一個設(shè)備驅(qū)動的“Hello World”實例,即最簡單的 LED 驅(qū)動在無操作系統(tǒng)情況下和 Linux 操作系統(tǒng)下的實現(xiàn)。嵌入式學(xué)院華清遠(yuǎn)見旗下品牌:Li
2、nux 設(shè)備驅(qū)動開發(fā)詳解第 1 章、設(shè)備驅(qū)動概述設(shè)備驅(qū)動的作用任何一個計算機系統(tǒng)的運行都是系統(tǒng)中軟硬件協(xié)作的結(jié)果,沒有硬件的軟件是空中樓閣,而沒有軟件的硬件則只是一堆廢鐵。硬件是底層基礎(chǔ),是所有軟件得以運行的平臺,代碼最終會落實為硬件上的組合邏輯與時序邏輯;軟件則實現(xiàn)了具體應(yīng)用,它按照各種不同的業(yè)務(wù)需求而設(shè)計,滿足了用戶的需求。硬件較固定,軟件則很靈活,可以適應(yīng)各種復(fù)雜多變的應(yīng)用。可以說,計算機系統(tǒng)的軟硬件互相成就了對方。但是,軟硬件之間同樣存在著悖論,那就是軟件和硬件不應(yīng)該互相滲透到對方的領(lǐng)地。為了盡可能快速地完成設(shè)計,應(yīng)用軟件工程師不想也不必關(guān)心硬件,而硬件工程師也難有足夠的閑暇和能力來顧
3、及軟件。例如,應(yīng)用軟件工程師在調(diào)用套接字發(fā)送和接收數(shù)據(jù)包的時候,他不必關(guān)心網(wǎng)卡上的中斷、寄存器、存儲空間、I/O 端口、片選以及其他任何硬件詞匯;在使用 printf()函數(shù)輸出信息的時候,他不用知道底層究竟是怎樣把相應(yīng)的信息輸出到屏幕或串口。也就是說,應(yīng)用軟件工程師需要看到一個沒有硬件的純粹的軟件世界,硬件必須被透明地呈現(xiàn)給他們。誰來實現(xiàn)硬件對應(yīng)用軟件工程師的隱形?這個艱巨的任務(wù)就落在了驅(qū)動工程師的頭上。對設(shè)備驅(qū)動最通俗的解釋就是“驅(qū)使硬件設(shè)備行動”。設(shè)備驅(qū)動與底層硬件直接打交道,按照硬件設(shè)備的具體工作方式讀寫設(shè)備寄存器,完成設(shè)備的輪詢、中斷處理、DMA 通信,進行物理內(nèi)存向虛擬內(nèi)存的映射,
4、最終使通信設(shè)備能夠收發(fā)數(shù)據(jù),使顯示設(shè)備能夠顯示文字和畫面,使存儲設(shè)備能夠記錄文件和數(shù)據(jù)。由此可見,設(shè)備驅(qū)動充當(dāng)了硬件和應(yīng)用軟件之間的紐帶,它使得應(yīng)用軟件只需要調(diào)用系統(tǒng)軟件的應(yīng)用編程接口(API)就可讓硬件去完成要求的工作。在系統(tǒng)中沒有操作系統(tǒng)的情況下,工程師可以根據(jù)硬件設(shè)備的特點自行定義接口,如對串口定義SerialSend()、SerialRecv();對 LED 定義 LightOn()、LightOff();以及對 Flash 定義FlashWrite()、FlashRead()等。而在有操作系統(tǒng)的情況下,設(shè)備驅(qū)動的架構(gòu)則由相應(yīng)的操作系統(tǒng)定義,驅(qū)動工程師必須按照相應(yīng)的架構(gòu)設(shè)計設(shè)備驅(qū)動,這
5、樣,設(shè)備驅(qū)動才能良好地整合到操作系統(tǒng)的內(nèi)核中。驅(qū)動程序溝通著硬件和應(yīng)用軟件,而驅(qū)動工程師則溝通著硬件工程師和應(yīng)用軟件工程師。隨著通信、電子行業(yè)的迅速發(fā)展,全世界每天都會有大量的新芯片被生產(chǎn),大量的新電路板被設(shè)計,因此,也會有大量設(shè)備驅(qū)動需要開發(fā)。這些設(shè)備驅(qū)動,或運行在簡單的單任務(wù)環(huán)境中,或運行在 VxWorks、 Linux、Windows等多任務(wù)操作系統(tǒng)環(huán)境中,發(fā)揮著不可替代的作用。無操作系統(tǒng)時的設(shè)備驅(qū)動嵌入式學(xué)院華清遠(yuǎn)見旗下品牌:Linux 設(shè)備驅(qū)動開發(fā)詳解第 1 章、設(shè)備驅(qū)動概述并不是任何一個計算機系統(tǒng)都一定要運行操作系統(tǒng),在許多情況下操作系統(tǒng)是不必要的。對于功能比較單一、控制并不復(fù)雜的
6、系統(tǒng),如公交車刷卡機、電冰箱、微波爐、簡單的手機和小靈通等,并不需要多任務(wù)調(diào)度、文件系統(tǒng)、內(nèi)存管理等復(fù)雜功能,用單任務(wù)架構(gòu)完全可以很好地支持它們的工作。一個無限循環(huán)中夾雜對設(shè)備中斷的檢測或者對設(shè)備的輪詢是這種系統(tǒng)中軟件的典型架構(gòu),如代碼清單 1.1 所示。代碼清單 1.1 單任務(wù)軟件典型架構(gòu)1 int main(int argc, char* argv)2 345678while (1)if (serialInt = 1)/*有串口中斷*/ProcessSerialInt(); /*處理串口中斷*/91011121314151617181920212223serialInt = 0;if (k
7、eyInt = 1)/*有按鍵中斷*/ProcessKeyInt();keyInt = 0;status = CheckXXX();switch (status)./*中斷標(biāo)志變量清零*/*處理按鍵中斷*/*中斷標(biāo)志變量清零*/24 在這樣的系統(tǒng)中,雖然不存在操作系統(tǒng),但是設(shè)備驅(qū)動是必須存在的。一般情況下,對每一種設(shè)備驅(qū)動都會定義為一個軟件模塊,包含.h 文件和.c 文件,前者定義該設(shè)備驅(qū)動的數(shù)據(jù)結(jié)構(gòu)并聲明外部函數(shù),后者進行設(shè)備驅(qū)動的具體實現(xiàn)。代碼清單 1.2定義了一個串口的驅(qū)動。代碼清單 1.2 無操作系統(tǒng)情況下串口的驅(qū)動1 /*23*serial.h文件*/4 extern void Se
8、rialInit(void);5 extern void SerialSend(const char buf*,int count);嵌入式學(xué)院華清遠(yuǎn)見旗下品牌:Linux 設(shè)備驅(qū)動開發(fā)詳解第 1 章、設(shè)備驅(qū)動概述678910111213141516171819202122232425262728293031extern void SerialRecv(char buf*,int count);/*serial.c文件*/*初始化串口*/void SerialInit(void)./*串口發(fā)送*/void SerialSend(const char buf*,int count)./*串口接收
9、*/void SerialRecv(char buf*,int count)./*串口中斷處理函數(shù)*/void SerialIsr(void).serialInt = 1;其他模塊需要使用這個設(shè)備的時候,只需要包含設(shè)備驅(qū)動的頭文件 serial.h,然后調(diào)用其中的外部接口函數(shù)即可。如我們要從串口上發(fā)送字符串“Hello World”,使用函數(shù) SerialSend( " Hello World",11)即可。由此可見,在沒有操作系統(tǒng)的情況下,設(shè)備驅(qū)動的接口被直接提交給了應(yīng)用軟件工程師,應(yīng)用軟件沒有跨越任何層次就直接訪問了設(shè)備驅(qū)動的接口。設(shè)備驅(qū)動包含的接口函數(shù)也與硬件的功能直
10、接吻合,沒有任何附加功能。圖 1.1 所示為無操作系統(tǒng)情況下硬件、設(shè)備驅(qū)動與應(yīng)用軟件的關(guān)系。有的工程師把單任務(wù)系統(tǒng)設(shè)計成了如圖 1.2 所示的結(jié)構(gòu),即設(shè)備驅(qū)動和具體的應(yīng)用軟件模塊處于同一層次,這顯然是不合理的,不符合軟件設(shè)計中高內(nèi)聚低耦合的圖 1.1 無操作系統(tǒng)時硬件、設(shè)備驅(qū)動和應(yīng)用軟件的關(guān)系要求。另一種不合理的設(shè)計是直接在應(yīng)用中操作硬件的寄存器,而不單獨設(shè)計驅(qū)動模塊,如圖 1.3 所示。這種設(shè)計意味著系統(tǒng)中不存在或未能充分利用可被重用的驅(qū)動代碼。嵌入式學(xué)院華清遠(yuǎn)見旗下品牌:Linux 設(shè)備驅(qū)動開發(fā)詳解第 1 章、設(shè)備驅(qū)動概述圖 1.2 設(shè)備驅(qū)動與應(yīng)用高耦合的不合理設(shè)計圖 1.3 應(yīng)用直接訪問
11、硬件的不合理設(shè)計有操作系統(tǒng)時的設(shè)備驅(qū)動1.2 節(jié)中的設(shè)備驅(qū)動直接運行在硬件之上,不與任何操作系統(tǒng)關(guān)聯(lián)。當(dāng)系統(tǒng)中包含操作系統(tǒng)后,設(shè)備驅(qū)動會變得怎樣?首先,無操作系統(tǒng)時設(shè)備驅(qū)動的硬件操作工作仍然是必不可少的,沒有這一部分,設(shè)備驅(qū)動不可能與硬件打交道。其次,我們還需要將設(shè)備驅(qū)動融入內(nèi)核。為了實現(xiàn)這種融合,必須在所有的設(shè)備驅(qū)動中設(shè)計面向操作系統(tǒng)內(nèi)核的接口,這樣的接口由操作系統(tǒng)規(guī)定,對一類設(shè)備而言結(jié)構(gòu)一致,獨立于具體的設(shè)備。由此可見,當(dāng)系統(tǒng)中存在操作系統(tǒng)的時候,設(shè)備驅(qū)動變成了連接硬件和內(nèi)核的橋梁。如圖 1.4 所示,操作系統(tǒng)的存在勢必要求設(shè)備驅(qū)動附加更多的代碼和功能,把單一的“驅(qū)使硬件設(shè)備行動”變成了操
12、作系統(tǒng)內(nèi)與硬件交互的模塊,它對外呈現(xiàn)為操作系統(tǒng)的API,不再給應(yīng)用軟件工程師直接提供接口。有了操作系統(tǒng)之后,設(shè)備驅(qū)動反而變得復(fù)雜,那要操作系統(tǒng)干什么?首先,一個復(fù)雜的軟件系統(tǒng)需要處理多個并發(fā)的任務(wù),沒有操作系統(tǒng),想完成多任務(wù)并發(fā)是很困難的。其次,操作系統(tǒng)給我們提供內(nèi)存管理機圖 1.4 硬件、設(shè)備驅(qū)動、操作系統(tǒng)和應(yīng)用程序的關(guān)系制。一個典型的例子是,對于多數(shù)含 MMU的處理器而言,Windows、Linux 等操作系統(tǒng)可以讓每個進程都獨立地訪問 4GB 的內(nèi)存空間。上述優(yōu)點似乎并沒有體現(xiàn)在設(shè)備驅(qū)動身上,操作系統(tǒng)的存在給設(shè)備驅(qū)動究竟帶來了什么好處呢?嵌入式學(xué)院華清遠(yuǎn)見旗下品牌:Linux 設(shè)備驅(qū)動開
13、發(fā)詳解第 1 章、設(shè)備驅(qū)動概述簡而言之,操作系統(tǒng)通過給設(shè)備驅(qū)動制造麻煩來達到給上層應(yīng)用提供便利的目的。如果設(shè)備驅(qū)動都按照操作系統(tǒng)給出的獨立于設(shè)備的接口而設(shè)計,應(yīng)用程序?qū)⒖墒褂媒y(tǒng)一的系統(tǒng)調(diào)用接口來訪問各種設(shè)備。對于類 UNIX 的 VxWorks、Linux 等操作系統(tǒng)而言,應(yīng)用程序通過 write()、read()等函數(shù)讀寫文件就可以訪問各種字符設(shè)備和塊設(shè)備,而不用管設(shè)備的具體類型和工作方式,是非常方便的。Linux 設(shè)備驅(qū)動設(shè)備的分類及特點計算機系統(tǒng)的硬件主要由 CPU、存儲器和外設(shè)組成。隨著 IC 制造工藝的發(fā)展,目前,芯片的集成度越來越高,往往在 CPU 內(nèi)部就集成了存儲器和外設(shè)適配器。
14、ARM、PowerPC、MIPS 等處理器都集成了 UART、I2C 控制器、USB 控制器、SDRAM 控制器等,有的處理器還集成了片內(nèi) RAM 和 Flash。驅(qū)動針對的對象是存儲器和外設(shè)(包括 CPU 內(nèi)部集成的存儲器和外設(shè)),而不是針對 CPU 核。Linux 將存儲器和外設(shè)分為 3 個基礎(chǔ)大類:lll字符設(shè)備;塊設(shè)備;網(wǎng)絡(luò)設(shè)備。字符設(shè)備指那些必須以串行順序依次進行訪問的設(shè)備,如觸摸屏、磁帶驅(qū)動器、鼠標(biāo)等。塊設(shè)備可以用任意順序進行訪問,以塊為單位進行操作,如硬盤、軟驅(qū)等。字符設(shè)備不經(jīng)過系統(tǒng)的快速緩沖,而塊設(shè)備經(jīng)過系統(tǒng)的快速緩沖。但是,字符設(shè)備和塊設(shè)備并沒有明顯的界限,如 Flash 設(shè)
15、備符合塊設(shè)備的特點,但是我們?nèi)匀豢梢园阉鳛橐粋€字符設(shè)備來訪問。字符設(shè)備和塊設(shè)備的驅(qū)動設(shè)計呈現(xiàn)出很大的差異,但是對于用戶而言,他們都使用文件系統(tǒng)的操作接口 open()、close()、read()、write()等函數(shù)進行訪問。在 Linux 系統(tǒng)中,網(wǎng)絡(luò)設(shè)備面向數(shù)據(jù)包的接收和發(fā)送而設(shè)計,它并不對應(yīng)于文件系統(tǒng)的節(jié)點。內(nèi)核與網(wǎng)絡(luò)設(shè)備的通信和內(nèi)核與字符設(shè)備、塊設(shè)備的通信方式完全不同。另外,TTY 驅(qū)動、I2C 驅(qū)動、USB 驅(qū)動、PCI 驅(qū)動、LCD 驅(qū)動等本身大體可歸納入 3 個基礎(chǔ)大類,但是對于這些復(fù)雜的設(shè)備,Linux 系統(tǒng)還定義了獨特的驅(qū)動體系結(jié)構(gòu)。Linux 設(shè)備驅(qū)動與整個軟硬件系統(tǒng)的
16、關(guān)系如圖 1.5 所示,除網(wǎng)絡(luò)設(shè)備外,字符設(shè)備與塊設(shè)備都被映射到 Linux 文件系統(tǒng)的文件和目錄,通過文件系統(tǒng)的系統(tǒng)調(diào)用接口 open()、write()、read()、close()等函數(shù)即可訪問字符設(shè)備和塊設(shè)備。所有的字符設(shè)備和塊設(shè)備都被統(tǒng)一地呈現(xiàn)給用戶。塊設(shè)備比字符設(shè)備復(fù)雜,在它上面會首先建立一個磁盤/Flash 文件系統(tǒng),如 FAT、Ext3、YAFFS、JFFS 等。FAT、Ext3、YAFFS、JFFS 規(guī)范了文件和目錄在存儲介質(zhì)上的組織。嵌入式學(xué)院華清遠(yuǎn)見旗下品牌:Linux 設(shè)備驅(qū)動開發(fā)詳解第 1 章、設(shè)備驅(qū)動概述應(yīng)用程序可以使用 Linux 的系統(tǒng)調(diào)用接口編程,也可以使用
17、C 庫函數(shù),出于代碼可移植性的考慮,后者更值得推薦。C 庫函數(shù)本身也通過系統(tǒng)調(diào)用接口而實現(xiàn),如 C庫函數(shù)中的 fopen()、fwrite()、fread()、fclose()分別會調(diào)用操作系統(tǒng) API 的 open()、write()、read()、close()函數(shù)。圖 1.5 Linux 設(shè)備驅(qū)動與整個軟硬件系統(tǒng)的關(guān)系編寫 Linux 設(shè)備驅(qū)動的技術(shù)基礎(chǔ)Linux 設(shè)備驅(qū)動的學(xué)習(xí)是一項浩大的工程,讀者需要首先掌握以下基礎(chǔ)。llll編寫 Linux 設(shè)備驅(qū)動要求工程師具有良好的硬件基礎(chǔ),懂得 SRAM、Flash、SDRAM、磁盤的讀寫方式,UART、I2C、USB 等設(shè)備的接口,輪詢、中
18、斷、DMA 的原理,PCI 總線的工作方式以及 CPU 的內(nèi)存管理單元(MMU)等。編寫 Linux 設(shè)備驅(qū)動要求工程師具有良好的 C 語言基礎(chǔ),能靈活地運用 C 語言的結(jié)構(gòu)體、指針、函數(shù)指針及內(nèi)存動態(tài)申請和釋放等。編寫 Linux 設(shè)備驅(qū)動要求工程師具有一定的 Linux 內(nèi)核基礎(chǔ),雖然并不要求工程師對內(nèi)核各個部分有深入的研究,但至少要了解設(shè)備驅(qū)動與內(nèi)核的接口,尤其是對于塊設(shè)備、網(wǎng)絡(luò)設(shè)備、Flash 設(shè)備、串口設(shè)備等復(fù)雜設(shè)備。編寫 Linux 設(shè)備驅(qū)動要求工程師具有良好的多任務(wù)并發(fā)控制和同步的基礎(chǔ),因為在設(shè)備驅(qū)動中會大量使用自旋鎖、互斥、信號量、等待隊列等并發(fā)與同步機制。本書對以上內(nèi)容都進行
19、了詳細(xì)的講解,以使讀者快速掌握編寫 Linux 設(shè)備驅(qū)動的基礎(chǔ)。嵌入式學(xué)院華清遠(yuǎn)見旗下品牌:Linux 設(shè)備驅(qū)動開發(fā)詳解第 1 章、設(shè)備驅(qū)動概述Linux 設(shè)備驅(qū)動的學(xué)習(xí)方法動手實踐永遠(yuǎn)是學(xué)習(xí)任何軟件開發(fā)的最好方法,學(xué)習(xí) Linux 設(shè)備驅(qū)動也不例外。因此,您最好有一塊可以實際練手的電路板來構(gòu)造嵌入式開發(fā)環(huán)境。如果您暫時沒有,則可以用 VmWare 搭建兩臺虛擬機,兩臺虛擬機上都運行 Linux 操作系統(tǒng),一臺作為開發(fā)主機,另一臺作為目標(biāo)機。目前的 PC 上往往只有 1 個串口,但是調(diào)試要求主機和目標(biāo)機之間使用串口通信,這要求 2 個串口。在虛擬機中我們可以用管道虛擬串口。在主機端設(shè)置“終端是
20、客戶機”,并選擇“其他終端是一個虛擬機”。在目標(biāo)機端設(shè)置“終端是服務(wù)器”,同樣選擇“其他終端是一個虛擬機”,但是要啟用輪詢。主機和目標(biāo)機的串口設(shè)置分別如圖1.6 和圖 1.7 所示。圖 1.6 VmWare 中主機串口設(shè)置嵌入式學(xué)院華清遠(yuǎn)見旗下品牌:Linux 設(shè)備驅(qū)動開發(fā)詳解第 1 章、設(shè)備驅(qū)動概述圖 1.7 VmWare 中目標(biāo)機串口設(shè)置另外,為了使 VmWare 中安裝的多個 Linux 系統(tǒng)之間以及 Linux 與 Windows 系統(tǒng)之間的網(wǎng)絡(luò)互通,可以設(shè)置 VmWare 中的 Linux 系統(tǒng)使用 VMnet1(僅主機),如圖 1.8所示。打開 VMnet1 虛擬網(wǎng)卡的連接共享,將
21、 Linux 系統(tǒng)的網(wǎng)關(guān)設(shè)置為 VMnet1 的 IP地址“”,Linux 系統(tǒng)將通過這個地址連接外網(wǎng)。圖 1.8 VmWare 中虛擬機網(wǎng)卡的設(shè)置為了使 VmWare 中的 Linux 系統(tǒng)具有較高的顯示分辨率,并能與主機上的 Windows之間通過 hgfs 文件系統(tǒng)共享文件,最好在 Linux 中安裝 VmWare tools。源代碼是學(xué)習(xí) Linux 驅(qū)動的最權(quán)威資料,閱讀 Linux 源代碼的最佳工具是 SourceInsight,在其中建立一個工程,并將 Linux 內(nèi)核的所有源代碼加入該工程,同步這個工程之后,我們將可以非常方便地在代碼之間進行關(guān)聯(lián)閱讀,如圖 1.9 所示。嵌入式
22、學(xué)院華清遠(yuǎn)見旗下品牌:Linux 設(shè)備驅(qū)動開發(fā)詳解第 1 章、設(shè)備驅(qū)動概述圖 1.9 在 Source Insight 中閱讀 Linux 源代碼網(wǎng)站 提供了 、 、 、 、 版本內(nèi)核和 i386、Alpha、ARM、IA-64、m68k、MIPS、MIPS64、PowerPC、IBMS/390、SH、SPARC、SPARC64、x86-64體系結(jié)構(gòu)下 Linux 源代碼的“Cross-Referencing”,在其中輸入 Linux 內(nèi)核中的函數(shù)、數(shù)據(jù)結(jié)構(gòu)或變量的名稱就可以直接得到以超鏈接形式給出的定義和引用它的所有位置。如搜索 內(nèi)核、i386 體系結(jié)構(gòu)下的 sys_write()函數(shù),得到
23、如下信息:sys_writeDefined as a function in:* fs/read_write.c, line 374Defined as a function prototype in:* include/linux/syscalls.h, line 380Referenced (in 11 files total) in:* arch/mips/kernel/irixioctl.c, line 236* arch/mips/kernel/sysirix.c:o line 1046o line 1531* arch/s390/kernel/compat_linux.c, lin
24、e 955* arch/sparc/kernel/sys_sunos.c, line 1093* arch/sparc64/kernel/sys_sunos32.c, line 1239* fs/read_write.c, line 374* include/asm-x86_64/unistd.h, line 18嵌入式學(xué)院華清遠(yuǎn)見旗下品牌:Linux 設(shè)備驅(qū)動開發(fā)詳解第 1 章、設(shè)備驅(qū)動概述* include/asm-xtensa/unistd.h, line 48* include/linux/syscalls.h, line 380* init/do_mounts_rd.c:o line
25、 239o line 373* init/initramfs.c:o line 305o line 311o line 552除此之外,閱讀經(jīng)典書籍和參與 Linux 社區(qū)的討論也是非常好的學(xué)習(xí)方法。Linux內(nèi)核源代碼中包含了一個 Documentation 目錄,其中包含了一批內(nèi)核設(shè)計的文檔,全部是文本文件。很遺憾,這些文檔的組織不太好,內(nèi)容也不夠細(xì)致。學(xué)習(xí) Linux 設(shè)備驅(qū)動的一個注意事項是要避免管中窺豹、只見樹木不見森林,因為各類 Linux 設(shè)備驅(qū)動都從屬于一個 Linux 設(shè)備驅(qū)動的架構(gòu),單純而片面地學(xué)習(xí)幾個函數(shù)、幾個數(shù)據(jù)結(jié)構(gòu)是不可能理清設(shè)備驅(qū)動中各組成部分之間的關(guān)系的。因此,L
26、inux驅(qū)動的分析方法是點面結(jié)合,將對函數(shù)和數(shù)據(jù)結(jié)構(gòu)的理解放在整體架構(gòu)的背景之中,而這正是本書各章節(jié)講解驅(qū)動的方法。設(shè)備驅(qū)動的 Hello World:LED 驅(qū)動無操作系統(tǒng)時的 LED 驅(qū)動在嵌入式系統(tǒng)的設(shè)計中,LED 一般直接由 CPU 的 GPIO(通用可編程 I/O 口)控制。GPIO 一般由兩組寄存器控制,即一組控制寄存器和一組數(shù)據(jù)寄存器。控制寄存器可設(shè)置 GPIO 口的工作方式為輸入或輸出。當(dāng)引腳被設(shè)置為輸出時,向數(shù)據(jù)寄存器的對應(yīng)位寫入 1 和 0 會分別在引腳上產(chǎn)生高電平和低電平;當(dāng)引腳設(shè)置為輸入時,讀取數(shù)據(jù)寄存器的對應(yīng)位可獲得引腳上相應(yīng)的電平信號。在本例子中,我們屏蔽具體 CP
27、U 的差異,假設(shè)在 GPIO_REG_CTRL 物理地址處的控制寄存器處的第 n 位寫入 1 可設(shè)置 GPIO 為輸出,在 GPIO_REG_DATA 物理地址處的數(shù)據(jù)寄存器的第 n 位寫入 1 或 0 可在引腳上產(chǎn)生高或低電平,則在無操作系統(tǒng)的情況下,設(shè)備驅(qū)動代碼如清單 1.3 所示。代碼清單 1.3 無操作系統(tǒng)時的 LED 驅(qū)動1 #define reg_gpio_ctrl *(volatile int *)(ToVirtual(GPIO_REG_CTRL)2 #define reg_gpio_data *(volatile int *)(ToVirtual(GPIO_REG_DATA)3
28、 /*初始化 LED*/4 void LightInit(void)5 6reg_gpio_ctrl |= (1 << n); /*設(shè)置 GPIO為輸出*/嵌入式學(xué)院華清遠(yuǎn)見旗下品牌:Linux 設(shè)備驅(qū)動開發(fā)詳解第 1 章、設(shè)備驅(qū)動概述7 89 /*點亮 LED*/10 void LightOn(void)11 12reg_gpio_data |= (1 << n); /*在 GPIO上輸出高電平*/13 1415 /*熄滅 LED*/16 void LightOff(void)17 18reg_gpio_data &= (1 << n); /*在
29、GPIO上輸出低電平*/19 上述程序中的 LightInit()、LightOn()、LightOff()等函數(shù)都將作為 LED 驅(qū)動提供給應(yīng)用程序的外部接口函數(shù)。程序中 ToVirtual()等函數(shù)的作用是當(dāng)系統(tǒng)啟動了硬件 MMU之后,根據(jù)物理地址和虛擬地址的映射關(guān)系,將寄存器的物理地址轉(zhuǎn)化為虛擬地址。Linux 系統(tǒng)下的 LED 驅(qū)動在 Linux 操作系統(tǒng)下編寫 LED 設(shè)備的驅(qū)動時,操作硬件的 LightInit()、LightOn()、LightOff()這些函數(shù)仍然需要,但是,需要遵循 Linux 編程的命名習(xí)慣,重新將其命名為 light_init()、light_on()、l
30、ight_off()。這些函數(shù)將被 LED 驅(qū)動中獨立于設(shè)備的針對內(nèi)核的接口進行調(diào)用,代碼清單 1.4 給出了 Linux 系統(tǒng)下的 LED 驅(qū)動,現(xiàn)在讀者并不需要能讀懂這些代碼。代碼清單 1.4 Linux 系統(tǒng)下的 LED 驅(qū)動12345678#include ./*包含內(nèi)核中的多個頭文件*/*設(shè)備結(jié)構(gòu)體*/struct light_devstruct cdev cdev; /*字符設(shè)備 cdev結(jié)構(gòu)體*/unsigned char value; /*LED亮?xí)r為 1,熄滅時為 0,用戶可讀寫此值*/;910 struct light_dev *light_devp;11 int ligh
31、t_major = LIGHT_MAJOR;1213 MODULE_AUTHOR("Song Baohua");14 MODULE_LICENSE("Dual BSD/GPL");1516 /*打開和關(guān)閉函數(shù)*/嵌入式學(xué)院華清遠(yuǎn)見旗下品牌:Linux 設(shè)備驅(qū)動開發(fā)詳解第 1 章、設(shè)備驅(qū)動概述17 int light_open(struct inode *inode, struct file *filp)18 192021222324struct light_dev *dev;/*獲得設(shè)備結(jié)構(gòu)體指針 */dev = container_of(inode-&
32、gt;i_cdev, struct light_dev, cdev);/*讓設(shè)備結(jié)構(gòu)體作為設(shè)備的私有信息 */filp->private_data = dev;return 0;25 26 int light_release(struct inode *inode, struct file *filp)27 28return 0;29 3031 /*寫設(shè)備:可以不需要 */32count,33ssize_t light_read(struct file *filp, char _ _user *buf, size_tloff_t*f_pos)34 3536373839404142 43s
33、truct light_dev *dev = filp->private_data; /*獲得設(shè)備結(jié)構(gòu)體 */if (copy_to_user(buf, &(dev->value), 1)return - EFAULT;return 1;44ssize_t light_write(struct file *filp, const char _ _user *buf,size_t count,4546 4748495051525354loff_t *f_pos)struct light_dev *dev = filp->private_data;if (copy_fro
34、m_user(&(dev->value), buf, 1)return - EFAULT;/*根據(jù)寫入的值點亮和熄滅 LED*/if (dev->value = 1)嵌入式學(xué)院華清遠(yuǎn)見旗下品牌:Linux 設(shè)備驅(qū)動開發(fā)詳解第 1 章、設(shè)備驅(qū)動概述5556575859light_on();elselight_off();return 1;60 6162 /* ioctl函數(shù) */63 int light_ioctl(struct inode *inode, struct file *filp, unsigned intcmd,6465 66676869707172737475
35、7677787980818283unsigned long arg)struct light_dev *dev = filp->private_data;switch (cmd)case LIGHT_ON:dev->value = 1;light_on();break;case LIGHT_OFF:dev->value = 0;light_off();break;default:/*不能支持的命令 */return - ENOTTY;return 0;84 8586 struct file_operations light_fops =87 888990919293.owne
36、r = THIS_MODULE,.read = light_read,.write = light_write,.ioctl = light_ioctl,.open = light_open,.release = light_release,嵌入式學(xué)院華清遠(yuǎn)見旗下品牌:Linux 設(shè)備驅(qū)動開發(fā)詳解第 1 章、設(shè)備驅(qū)動概述94 ;9596 /*設(shè)置字符設(shè)備 cdev結(jié)構(gòu)體*/97 static void light_setup_cdev(struct light_dev *dev, int index)98 99100101102103104105106int err, devno = MKDE
37、V(light_major, index);cdev_init(&dev->cdev, &light_fops);dev->cdev.owner = THIS_MODULE;dev->cdev.ops = &light_fops;err = cdev_add(&dev->cdev, devno, 1);if (err)printk(KERN_NOTICE "Error %d adding LED%d", err, index);107 108109 /*模塊加載函數(shù)*/110 int light_init(void)111 112113114115116117118119120121122123124125126127int result;dev_t dev = MKDEV(light_major, 0);/*申請字符設(shè)備號*/if (light_major)result = register_chrd
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二網(wǎng)銷售培訓(xùn)體系構(gòu)建
- 超市員工溝通培訓(xùn)
- 地下水水文地質(zhì)工程地質(zhì)重點基礎(chǔ)知識點
- 培訓(xùn)課件花卉生產(chǎn)管理
- 道路事故協(xié)議書范本
- 變電運維系統(tǒng)培訓(xùn)大綱
- 退款售后協(xié)議書范本
- 智能制造協(xié)議書
- 轉(zhuǎn)讓平板木床合同協(xié)議
- 郵件自取協(xié)議書范本
- 2024年全國統(tǒng)一高考英語試卷(新課標(biāo)Ⅰ卷)含答案
- 工程竣工驗收報告及五方驗收表
- 常用試敏藥品操作規(guī)程表
- 學(xué)位論文寫作及其學(xué)術(shù)規(guī)范課件
- 三年級數(shù)學(xué)-《年月日》整理和復(fù)習(xí)課件
- 兼職教師任職承諾書
- 懸挑式腳手架驗收表范本
- TSG Z7002-2022 特種設(shè)備檢測機構(gòu)核準(zhǔn)規(guī)則
- 上海市2020年中考化學(xué)試卷(word版含解析)
- 史上最全的數(shù)列通項公式的求法15種
- 配電室高低壓運行記錄表
評論
0/150
提交評論