版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第12章擴(kuò)展實(shí)驗(yàn)本章包括8個(gè)擴(kuò)展實(shí)驗(yàn),以設(shè)備驅(qū)動(dòng)模塊的編寫(xiě)、編譯、加載和卸載為主要內(nèi)容,對(duì)實(shí)驗(yàn)箱自帶的比較復(fù)雜的模塊進(jìn)行訪(fǎng)問(wèn)和控制。目錄12.1小鍵盤(pán)實(shí)驗(yàn)12.2嵌入式WEB服務(wù)器12.3利用GDBServer在下位機(jī)中調(diào)試執(zhí)行程序12.4設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)實(shí)驗(yàn)12.5字符設(shè)備驅(qū)動(dòng)實(shí)例-觸摸屏驅(qū)動(dòng)實(shí)驗(yàn)12.6LCD驅(qū)動(dòng)控制實(shí)驗(yàn)12.7音頻驅(qū)動(dòng)及應(yīng)用實(shí)驗(yàn)12.8SD卡使用實(shí)驗(yàn)12.1.1實(shí)驗(yàn)?zāi)康牧私怄I盤(pán)的工作原理,掌握開(kāi)發(fā)板上小鍵盤(pán)的控制和驅(qū)動(dòng)技術(shù),學(xué)習(xí)鍵盤(pán)相關(guān)的編程方法,將按下的數(shù)字鍵通過(guò)LED顯示。12.1.2
實(shí)驗(yàn)設(shè)備
1臺(tái)已安裝Linux的PC機(jī)作為宿主機(jī)(上位機(jī)),1臺(tái)已燒寫(xiě)ARMLinux的博創(chuàng)經(jīng)典UP-TECH-S2410/P270-DVP實(shí)驗(yàn)箱作為目標(biāo)板(下位機(jī))。12.1.3實(shí)驗(yàn)內(nèi)容1.學(xué)習(xí)鍵盤(pán)的工作原理,掌握鍵盤(pán)的驅(qū)動(dòng)及編程技術(shù)。2.編程控制7段LED顯示小鍵盤(pán)所按鍵數(shù)字字符。12.1小鍵盤(pán)實(shí)驗(yàn)1.鍵盤(pán)接口(1)鍵盤(pán)接口設(shè)計(jì)鍵盤(pán)是由若干個(gè)按鍵組成的開(kāi)關(guān)矩陣。在嵌入式系統(tǒng)的鍵盤(pán)接口設(shè)計(jì)時(shí),需要根據(jù)應(yīng)用的具體要求,設(shè)計(jì)鍵盤(pán)接口的硬件電路,同時(shí)還需要完成識(shí)別按鍵動(dòng)作、生成按鍵鍵碼和按鍵具體功能的程序設(shè)計(jì)。(2)矩陣鍵盤(pán)接口程序需處理的問(wèn)題對(duì)于由機(jī)械開(kāi)關(guān)組成的矩陣鍵盤(pán),其接口程序必須處理三個(gè)問(wèn)題:去抖動(dòng)、防串鍵和產(chǎn)生鍵值。1)抖動(dòng)抖動(dòng)是指當(dāng)鍵按下時(shí),開(kāi)關(guān)簧片的閉合有一個(gè)從斷開(kāi)到不穩(wěn)定接觸,最后到可靠接觸的過(guò)程。同樣的現(xiàn)象在按鍵釋放時(shí)也存在。去抖動(dòng)的方法主要采用軟件延時(shí)和硬件延時(shí)電路。2)串鍵串鍵是指多個(gè)鍵同時(shí)按下時(shí)產(chǎn)生的問(wèn)題。解決的方法也是有軟件方法和硬件方法兩種。3)產(chǎn)生鍵值產(chǎn)生鍵值是指鍵盤(pán)接口必須把按下的鍵翻譯成有限位二進(jìn)制代碼,以便微處理器識(shí)別。12.1.4實(shí)驗(yàn)原理(3)鍵盤(pán)接口程序處理方法及其流程下面用一個(gè)6ⅹ4陣列的鍵盤(pán)(如圖12-1)為例來(lái)說(shuō)明鍵盤(pán)接口的“行掃描”處理方式及其流程。圖12-16ⅹ4陣列鍵盤(pán)該鍵盤(pán)陣列由6行4列構(gòu)成,控制器采用“行掃描”方式來(lái)識(shí)別按鍵,具體過(guò)程如下:1)首先判斷鍵盤(pán)中有無(wú)鍵按下將全部行線(xiàn)0-5置低電平,然后檢測(cè)列線(xiàn)的狀態(tài)。只要有一列的電平為低,則表示鍵盤(pán)中有鍵被按下,而且閉合的鍵位于低電平線(xiàn)與6根行線(xiàn)相交叉的幾個(gè)按鍵之中。若所有列線(xiàn)均為高電平,則鍵盤(pán)中無(wú)鍵按下。2)判斷按鍵所在的位置在確認(rèn)有鍵按下后,即可進(jìn)入確定具體閉合鍵的過(guò)程。其方法是:首先將0行線(xiàn)置為低電平,其它1-5行線(xiàn)為高電平,然后依次檢測(cè)各列線(xiàn)的電平狀態(tài)。若某列為低,則該列線(xiàn)與第0行交叉處的按鍵就是按下的鍵;若所有列均為高電平,則第0行沒(méi)有鍵按下。然后再將第1行置為低電平,其它行線(xiàn)為高電平,使用上述方法檢測(cè)該行是否有鍵按下。這樣依次掃描其余行,直到找到該按鍵,得到其所在行碼及列碼。3)產(chǎn)生鍵值可以根據(jù)行碼及列碼查鍵值表確定按鍵,也可以通過(guò)行線(xiàn)和列線(xiàn)的狀態(tài)計(jì)算得到鍵值,然后進(jìn)行處理。2.S3C2410經(jīng)典開(kāi)發(fā)平臺(tái)板載的17鍵小鍵盤(pán)(1)小鍵盤(pán)的硬件連接及按鍵布局經(jīng)典開(kāi)發(fā)平臺(tái)上17鍵小鍵盤(pán)和PS2接口、IC卡接口都由一片ATMEGA8單片機(jī)控制,通過(guò)IIC總線(xiàn)接到CPU,如圖12-3所示。電路中對(duì)IICSDA和IICSCL兩個(gè)信號(hào)都接有3.3K上拉電阻,其按鍵布局如圖12-4所示。圖12-3開(kāi)發(fā)平臺(tái)17鍵小鍵盤(pán)的連接圖12-4小鍵盤(pán)按鍵布局結(jié)構(gòu)(2)小鍵盤(pán)編程由圖12-3可以看出,小鍵盤(pán)是由一片ATMEGA8單片機(jī)控制,通過(guò)IIC總線(xiàn)接到下位機(jī)的CPU,用戶(hù)編程時(shí)需要事先加載其驅(qū)動(dòng)程序“i2c-tomega8.o”。然后在宿主機(jī)目錄“/labsl/Lab_10”找到Linux下的小鍵盤(pán)驅(qū)動(dòng)程序“keyboard.c”,其中定義了如open、close、read等鍵盤(pán)操作的方法及掃描碼和鍵值對(duì)應(yīng)的鍵值表。本次實(shí)驗(yàn)用戶(hù)程序處理流程如圖12-5所示,調(diào)用其驅(qū)動(dòng)程序提供的方法讀取小鍵盤(pán)上的按鍵,驅(qū)動(dòng)LED顯示按鍵信息。圖12-5用戶(hù)程序處理流程1.使用命令“cd/labsl/Lab_10”進(jìn)入本次實(shí)驗(yàn)?zāi)夸洠褂胿i編輯器閱讀理解源代碼。2.運(yùn)行“make”命令產(chǎn)生可執(zhí)行文件“key_led”。]3.切換到下位機(jī)的minicom窗口,使用NFSmount上位機(jī)的“/labsl”目錄到“/host”目錄,然后進(jìn)入“/host/Lab_10/drivers”目錄,使用命令“insmodi2c-tomega8.o”插入ATMEGA8單片機(jī)驅(qū)動(dòng),使用命令“insmods3c2410-led.o”插入led驅(qū)動(dòng)。4.執(zhí)行“./key_led”命令,在小鍵盤(pán)上按鍵,查看8字?jǐn)?shù)碼管顯示按鍵信息。12.1.5實(shí)驗(yàn)步驟1.修改用戶(hù)程序,完成簡(jiǎn)單的鍵盤(pán)計(jì)算、LED顯示結(jié)果。2.重新定義小鍵盤(pán)健值,完成對(duì)應(yīng)功能鍵的處理。12.1.6習(xí)題12.2.1實(shí)驗(yàn)?zāi)康恼莆赵贏RM開(kāi)發(fā)板實(shí)現(xiàn)一個(gè)簡(jiǎn)單WEB服務(wù)器的過(guò)程,學(xué)習(xí)在ARM開(kāi)發(fā)板上的SOCKET網(wǎng)絡(luò)編程,學(xué)習(xí)Linux下的signal()函數(shù)的使用。12.2.2
實(shí)驗(yàn)設(shè)備
1臺(tái)已安裝Linux的PC機(jī)作為宿主機(jī)(上位機(jī)),1臺(tái)已燒寫(xiě)ARMLinux的博創(chuàng)經(jīng)典UP-TECH-S2410/P270-DVP實(shí)驗(yàn)箱作為目標(biāo)板(下位機(jī))。12.2.3實(shí)驗(yàn)內(nèi)容1.學(xué)習(xí)使用socket進(jìn)行通訊編程的過(guò)程。2.了解一個(gè)實(shí)際的網(wǎng)絡(luò)通訊應(yīng)用程序整體設(shè)計(jì),閱讀HTTP協(xié)議的相關(guān)內(nèi)容,學(xué)習(xí)幾個(gè)重要的網(wǎng)絡(luò)函數(shù)的使用方法。3.讀懂HTTPD.C源代碼,在此基礎(chǔ)上增加一些其他功能。4.在PC計(jì)算機(jī)上使用瀏覽器測(cè)試嵌入式WEB服務(wù)器的功能。12.2嵌入式WEB服務(wù)器
1.HTTP協(xié)議簡(jiǎn)介
HTTP協(xié)議是一個(gè)屬于應(yīng)用層的面向?qū)ο蟮膮f(xié)議,由于其簡(jiǎn)捷、快速的方式,適用于分布式超媒體信息系統(tǒng)。它于1990年提出,經(jīng)過(guò)幾年的使用與發(fā)展,得到不斷地完善和擴(kuò)展。目前在WWW中使用的是HTTP/1.1。
HTTP協(xié)議的主要特點(diǎn)可概括如下:(1)支持客戶(hù)/服務(wù)器模式。(2)簡(jiǎn)單快速:客戶(hù)向服務(wù)器請(qǐng)求服務(wù)時(shí),只需傳送請(qǐng)求方法和路徑。請(qǐng)求方法常用的有GET、HEAD、POST。每種方法規(guī)定了客戶(hù)與服務(wù)器聯(lián)系的類(lèi)型不同。由于HTTP協(xié)議簡(jiǎn)單,使得HTTP服務(wù)器的程序規(guī)模小,因而通信速度很快。(3)靈活:HTTP允許傳輸任意類(lèi)型的數(shù)據(jù)對(duì)象。正在傳輸?shù)念?lèi)型由Content-Type加以標(biāo)記。(4)無(wú)連接:無(wú)連接的含義是限制每次連接只處理一個(gè)請(qǐng)求。服務(wù)器處理完客戶(hù)的請(qǐng)求,并收到客戶(hù)的應(yīng)答后,即斷開(kāi)連接。采用這種方式可以節(jié)省傳輸時(shí)間。(5)無(wú)狀態(tài):HTTP協(xié)議是無(wú)狀態(tài)協(xié)議。無(wú)狀態(tài)是指協(xié)議對(duì)于事務(wù)處理沒(méi)有記憶能力。缺少狀態(tài)意味著如果后續(xù)處理需要前面的信息,則它必須重傳,這樣可能導(dǎo)致每次連接傳送的數(shù)據(jù)量增大。另一方面,在服務(wù)器不需要先前信息時(shí)它的應(yīng)答就較快。12.2.4實(shí)驗(yàn)原理2.實(shí)驗(yàn)原理(1)軟件需求說(shuō)明,如圖12-8所示。圖12-8軟件需求(2)功能需求詳細(xì)說(shuō)明獲取服務(wù)器當(dāng)前目錄文件列表:將服務(wù)器當(dāng)前目錄下所有文件的信息發(fā)送給客戶(hù)端,信息包括:文件名、大小、日期。獲取指定文件:將客戶(hù)請(qǐng)求的文件發(fā)送給客戶(hù)。獲取HTML類(lèi)型文件:將客戶(hù)請(qǐng)求的HTML類(lèi)型文件發(fā)送給客戶(hù)。獲取純文本文件:將客戶(hù)請(qǐng)求的純文本發(fā)送給客戶(hù)。獲取JPG圖像文件:將客戶(hù)請(qǐng)求的JPG圖像文件發(fā)送給客戶(hù)。獲取GIF圖像文件:將客戶(hù)請(qǐng)求的GIF圖像文件發(fā)送給客戶(hù)。解析用戶(hù)請(qǐng)求:分析客戶(hù)的請(qǐng)求,將請(qǐng)求信息解析為幾個(gè)變量,包括:請(qǐng)求的命令、請(qǐng)求的文件名、請(qǐng)求的文件類(lèi)型。(3)數(shù)據(jù)流圖(DFD),如圖12-9所示。圖12-9數(shù)據(jù)流圖
(4)系統(tǒng)結(jié)構(gòu)圖,如圖12-10所示。圖12-10系統(tǒng)結(jié)構(gòu)圖1.使用命令“cd/labs/Lab_11”切換到本次實(shí)驗(yàn)?zāi)夸?,使用vi編輯器閱讀理解源代碼。2.運(yùn)行“make”命令編譯應(yīng)用程序“httpd.c”,產(chǎn)生可執(zhí)行文件httpd。3.切換到下位機(jī)的“minicom”窗口,使用NFS服務(wù)方式將HTTPD下載到開(kāi)發(fā)板上,并拷貝測(cè)試用的網(wǎng)頁(yè)進(jìn)行調(diào)試,本實(shí)驗(yàn)中用的是index測(cè)試網(wǎng)頁(yè)。在下位機(jī)上執(zhí)行“./httpd”,顯示以下信息:startinghttpd...pressqtoquit.waitforconnection.
4.在上位機(jī)的瀏覽器中輸入“http://21”(即下位機(jī)的IP地址),觀察在客戶(hù)機(jī)的瀏覽器中的連接請(qǐng)求結(jié)果,點(diǎn)擊其中的超級(jí)鏈接“A/D數(shù)據(jù)采集”,則顯示采集到的下位機(jī)A/D轉(zhuǎn)換結(jié)果。12.2.5實(shí)驗(yàn)步驟1.閱讀源程序,擴(kuò)展其功能,用于在瀏覽器上監(jiān)控開(kāi)發(fā)板各部件工作。2.自定義一些功能,使用網(wǎng)絡(luò)TCP協(xié)議實(shí)現(xiàn)。12.2.6習(xí)題12.3.1實(shí)驗(yàn)?zāi)康膶⑦\(yùn)行在上位機(jī)中的GDB工具通過(guò)網(wǎng)絡(luò)與運(yùn)行在下位機(jī)中的GDBServer進(jìn)行連接,實(shí)現(xiàn)通過(guò)上位機(jī)來(lái)調(diào)試執(zhí)行運(yùn)行在下位機(jī)中的程序。12.3.2
實(shí)驗(yàn)設(shè)備
1臺(tái)已安裝Linux的PC機(jī)作為宿主機(jī)(上位機(jī)),1臺(tái)已燒寫(xiě)ARMLinux的博創(chuàng)經(jīng)典UP-TECH-S2410/P270-DVP實(shí)驗(yàn)箱作為目標(biāo)板(下位機(jī))。12.3.3實(shí)驗(yàn)內(nèi)容1.閱讀控制點(diǎn)陣式LED顯示的程序gdb_led.c和Makefile文件;2.通過(guò)交叉編譯生成運(yùn)行在下位機(jī)上的可執(zhí)行文件gdb_led。3.在下位機(jī)中運(yùn)行GDBServer;4.在上位機(jī)中運(yùn)行GDB;5.通過(guò)GDB連接GDBServer;4.調(diào)試執(zhí)行運(yùn)行在下位機(jī)上的程序gdb_led;12.3利用GDBServer在下位機(jī)中調(diào)試執(zhí)行程序
1.使用命令“cd/labs/Lab_12”進(jìn)入本次實(shí)驗(yàn)?zāi)夸?,閱讀理解源代碼文件gdb_led.c,體會(huì)按行逐列點(diǎn)亮點(diǎn)陣式LED的方法。2.查看Makefile文件內(nèi)容,注意編譯時(shí)所加的參數(shù)“-g”。3.運(yùn)行“make”命令產(chǎn)生可執(zhí)行文件“test_led”。4.切換到下位機(jī)的minicom窗口,使用命令“mount–t52:/labs/host”掛載上位機(jī)的“/labs”目錄到下位機(jī)的“/host”目錄,然后進(jìn)入“/host/Lab_12”目錄,使用命令“insmods3c2410-led.o”加載LED的驅(qū)動(dòng)程序,然后用lsmod查看裝載的結(jié)果。5.在minicom中執(zhí)行命令“./gdbserver21:4000gdb_led”,在下位機(jī)中啟動(dòng)GDBServer。其中,“21”為下位機(jī)的IP地址,“4000”為GDBServer的監(jiān)聽(tīng)端口,“gdb_led”為要調(diào)試執(zhí)行的程序。6.在上位機(jī)中進(jìn)入“/labs/Lab_12”目錄,執(zhí)行命令“./armv4l-linux-gdbgdb_led”,在上位機(jī)中啟動(dòng)GDB工具,進(jìn)入GDB界面。其中,“gdb_led”為要調(diào)試執(zhí)行的程序。12.3.4實(shí)驗(yàn)步驟7.在上位機(jī)的GDB界面中執(zhí)行命令“targetremote21:4000”,連接GDBServer,連接成功后,下位機(jī)界面如圖12-15所示,上位機(jī)界面如圖12-16所示。圖12-15GDBServer窗口圖12-16GDB窗口list1//從第一行開(kāi)始分頁(yè)顯示源程序,每頁(yè)10行,按回車(chē)鍵顯示下一頁(yè)。break36//在第36行處,即語(yǔ)句“write(fd,mydata,10)”處創(chuàng)建斷點(diǎn)。infobreak//顯示斷點(diǎn)信息。continue//繼續(xù)執(zhí)行程序,將執(zhí)行到斷點(diǎn)處暫停,顯示斷點(diǎn)處語(yǔ)句。prints//顯示變量s的值。printmydata//顯示數(shù)組mydata的值。step//逐條語(yǔ)句執(zhí)行程序,將發(fā)現(xiàn)下位機(jī)上點(diǎn)陣式LED的0行0列燈被點(diǎn)亮。whatiss//顯示變量s的類(lèi)型。continue//繼續(xù)執(zhí)行程序,將執(zhí)行到斷點(diǎn)處暫停,顯示斷點(diǎn)處語(yǔ)句。next//逐條語(yǔ)句執(zhí)行程序,將發(fā)現(xiàn)下位機(jī)上點(diǎn)陣式LED的0行1列燈被點(diǎn)亮。printmydata//顯示數(shù)組mydata的值。help//顯示GDB命令的分類(lèi)和功能描述。helpdata//顯示data類(lèi)命令及其功能描述。disable1//使斷點(diǎn)1失效。continue//繼續(xù)執(zhí)行程序,直到結(jié)束。quit//退出GDB環(huán)境。8.在上位機(jī)的GDB界面中執(zhí)行如下命令調(diào)試執(zhí)行運(yùn)行在下位機(jī)中的程序gdb_led。1.在第30行處增加1個(gè)斷點(diǎn),然后調(diào)試執(zhí)行程序。2.將程序gdb_led.c中控制LED顯示的循環(huán)語(yǔ)句放入用戶(hù)自定義函數(shù)“voidshow()”中,使main函數(shù)調(diào)用show函數(shù)來(lái)控制LED的顯示。在main函數(shù)中調(diào)用show函數(shù)處設(shè)置斷點(diǎn),然后調(diào)試運(yùn)行程序,比較GDB中的“step”和“next”命令的不同。3.調(diào)試運(yùn)行過(guò)程中,使用GDB命令“setvariables=63”,修改變量“s”的值為63,觀察點(diǎn)陣式LED的顯示。4.將第32行語(yǔ)句中的“s*=2”修改“s+=s*2”,觀察點(diǎn)陣式LED的顯示,并解釋。12.3.5習(xí)題12.4.1實(shí)驗(yàn)?zāi)康膶W(xué)習(xí)Linux下設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)的基礎(chǔ)知識(shí),掌握使用模塊方式進(jìn)行驅(qū)動(dòng)程序開(kāi)發(fā)、調(diào)試的過(guò)程。
12.4.2
實(shí)驗(yàn)設(shè)備
1臺(tái)已安裝Linux的PC機(jī)作為宿主機(jī)(上位機(jī)),1臺(tái)已燒寫(xiě)ARMLinux的博創(chuàng)經(jīng)典UP-TECH-S2410/P270-DVP實(shí)驗(yàn)箱作為目標(biāo)板(下位機(jī))。12.4.3實(shí)驗(yàn)內(nèi)容1.學(xué)習(xí)設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)相關(guān)知識(shí);2.在宿主機(jī)上編寫(xiě)一個(gè)簡(jiǎn)單的虛擬設(shè)備驅(qū)動(dòng)程序并進(jìn)行調(diào)試;3.編寫(xiě)實(shí)現(xiàn)驅(qū)動(dòng)程序的各個(gè)接口函數(shù),分析并理解驅(qū)動(dòng)程序與應(yīng)用程序的交互過(guò)程。12.4設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)實(shí)驗(yàn)12.4.4實(shí)驗(yàn)原理1.設(shè)備驅(qū)動(dòng)程序簡(jiǎn)介(1)設(shè)備驅(qū)動(dòng)程序在嵌入式系統(tǒng)中,各種硬件設(shè)備繁多,而且各自沒(méi)有統(tǒng)一的標(biāo)準(zhǔn),而控制硬件又是嵌入式系統(tǒng)的核心內(nèi)容。因此,在嵌入式系統(tǒng)中設(shè)備管理分為兩層:上層與設(shè)備無(wú)關(guān),它根據(jù)輸入輸出請(qǐng)求,通過(guò)特定的設(shè)備驅(qū)動(dòng)程序接口,來(lái)與設(shè)備進(jìn)行通信。下層與硬件設(shè)備密切相關(guān),常稱(chēng)為設(shè)備驅(qū)動(dòng)程序,它直接與相應(yīng)設(shè)備打交道,并且向上層提供一組訪(fǎng)問(wèn)接口。
如圖12-17所示,在Linux系統(tǒng)中,系統(tǒng)調(diào)用是內(nèi)核和應(yīng)用程序之間的接口,而驅(qū)動(dòng)程序是內(nèi)核和及其硬件之間的接口。驅(qū)動(dòng)程序?yàn)閼?yīng)用程序屏蔽了硬件細(xì)節(jié)。應(yīng)用程序可將硬件設(shè)備看作一個(gè)設(shè)備文件,象操作普通文件一樣對(duì)硬件設(shè)備進(jìn)行操作。圖12-17內(nèi)核和應(yīng)用程序之間的通信(2)設(shè)備驅(qū)動(dòng)程序的功能設(shè)備驅(qū)動(dòng)程序是內(nèi)核的一部分,主要完成以下功能:對(duì)設(shè)備進(jìn)行初始化和釋放,如對(duì)音頻設(shè)備而言包括向內(nèi)核注冊(cè)設(shè)備、設(shè)置音頻的輸入輸出參數(shù)(如采樣頻率、采樣寬度等)、分配音頻設(shè)備使用的內(nèi)核內(nèi)存等工作。把數(shù)據(jù)從內(nèi)核傳送到硬件和從硬件讀取數(shù)據(jù)并提交給內(nèi)核;讀取應(yīng)用程序傳送給設(shè)備文件的數(shù)據(jù)和回送應(yīng)用程序請(qǐng)求的數(shù)據(jù);檢測(cè)和處理硬件設(shè)備出現(xiàn)的錯(cuò)誤。(3)驅(qū)動(dòng)程序開(kāi)發(fā)的方法驅(qū)動(dòng)程序主要需要考慮下面三個(gè)方面:提供盡量多的選項(xiàng)給用戶(hù),提高驅(qū)動(dòng)程序的速度和效率,盡量使驅(qū)動(dòng)程序簡(jiǎn)單,使之易于維護(hù)。Linux的驅(qū)動(dòng)開(kāi)發(fā)調(diào)試有兩種方法:1)把設(shè)備驅(qū)動(dòng)作為內(nèi)核的一部分,直接編譯到內(nèi)核中,隨同Linux啟動(dòng)時(shí)加載,該方式稱(chēng)為靜態(tài)編譯,這種方式效率較低,但在某些場(chǎng)合是唯一的方法。2)單獨(dú)作為一個(gè)模塊(module),編譯成.o(或2.6內(nèi)核下為.ko)文件,需要時(shí)使用“insmod”動(dòng)態(tài)加載到內(nèi)核中;如果出現(xiàn)故障,可以使用“rmmod”從內(nèi)核中卸載模塊,不需要重新啟動(dòng)內(nèi)核,這使驅(qū)動(dòng)調(diào)試效率大大提高。該方式即動(dòng)態(tài)連接。這種方式控制了內(nèi)核的大小,而模塊一旦被插入內(nèi)核,它就和內(nèi)核其他部分一樣。顯然動(dòng)態(tài)連接比靜態(tài)連接有更多的好處。(4)設(shè)備分類(lèi)目前,Linux系統(tǒng)支持的設(shè)備可分為三種:字符設(shè)備(characterdevice)、塊設(shè)備(blockdevice)和網(wǎng)絡(luò)接口設(shè)備(networkinterface)。當(dāng)然它們之間并不是要嚴(yán)格的加以區(qū)分。1)字符設(shè)備字符設(shè)備的讀寫(xiě)以字節(jié)為單位按順序進(jìn)行,存取時(shí)沒(méi)有緩沖區(qū)。對(duì)字符設(shè)備發(fā)出讀寫(xiě)請(qǐng)求時(shí),實(shí)際的硬件I/O緊接著就發(fā)生了,不支持隨機(jī)讀寫(xiě)。典型的字符設(shè)備包括鼠標(biāo)、鍵盤(pán)及串口等。2)塊設(shè)備塊設(shè)備讀寫(xiě)以塊為單位,典型的塊大小為寫(xiě)512或1024字節(jié),存取時(shí)有緩存支持以提高效率。當(dāng)用戶(hù)進(jìn)程對(duì)設(shè)備發(fā)出讀寫(xiě)請(qǐng)求時(shí),驅(qū)動(dòng)程序先查看緩存中的內(nèi)容,若緩存中的的數(shù)據(jù)能滿(mǎn)足用戶(hù)的要求就返回相應(yīng)的數(shù)據(jù),否則就調(diào)用相應(yīng)的請(qǐng)求函數(shù)來(lái)進(jìn)行實(shí)際的I/O操作。典型的塊設(shè)備主要包括硬盤(pán)、軟盤(pán)、內(nèi)存、Flash等可以容納文件系統(tǒng)的存儲(chǔ)設(shè)備。3)網(wǎng)絡(luò)接口設(shè)備網(wǎng)絡(luò)接口設(shè)備是Linux中比較復(fù)雜的一種設(shè)備,通常是硬件設(shè)備,有時(shí)還可以是一個(gè)軟件設(shè)備(如回環(huán)接口loopback)。它們由內(nèi)核中網(wǎng)絡(luò)子系統(tǒng)驅(qū)動(dòng),負(fù)責(zé)發(fā)送和接收數(shù)據(jù)包,而且它并不需要了解每一項(xiàng)事務(wù)是如何映射到實(shí)際傳送的數(shù)據(jù)包的。網(wǎng)絡(luò)接口設(shè)備由內(nèi)核中的協(xié)議棧來(lái)管理,在Linux中采用給網(wǎng)絡(luò)接口設(shè)備分配一個(gè)唯一名字的方法來(lái)訪(fǎng)問(wèn)該設(shè)備。(5)設(shè)備文件和設(shè)備號(hào)
1)設(shè)備文件Linux使用設(shè)備文件的概念來(lái)統(tǒng)一對(duì)設(shè)備的訪(fǎng)問(wèn)接口,在引入設(shè)備文件系統(tǒng)(devfs)之前Linux將設(shè)備文件放在“/dev”目錄下,設(shè)備的命名一般為設(shè)備文件名+數(shù)字或字母表示的子類(lèi),例如“/dev/hda1”、“/dev/hda2”等。
2)設(shè)備號(hào)傳統(tǒng)的設(shè)備管理中,除了設(shè)備類(lèi)型外,Linux內(nèi)核還需要一對(duì)稱(chēng)作主設(shè)備號(hào)、次設(shè)備號(hào)的參數(shù),才能唯一標(biāo)識(shí)設(shè)備。主設(shè)備號(hào)(magornumber)標(biāo)識(shí)設(shè)備的類(lèi)型,也標(biāo)示設(shè)備對(duì)應(yīng)的驅(qū)動(dòng)程序。主設(shè)備號(hào)相同的設(shè)備使用相同的驅(qū)動(dòng)程序。一個(gè)主設(shè)備號(hào)可能有多個(gè)設(shè)備與之對(duì)應(yīng),這多個(gè)設(shè)備在驅(qū)動(dòng)程序內(nèi)通過(guò)次設(shè)備號(hào)來(lái)進(jìn)一步區(qū)分。次設(shè)備號(hào)(minornumber)標(biāo)識(shí)了使用同一設(shè)備驅(qū)動(dòng)程序的不同硬件設(shè)備。如PC機(jī)中的IDE設(shè)備,一般主設(shè)備號(hào)使用3,WINDOWS下進(jìn)行的分區(qū),一般將主分區(qū)的次設(shè)備號(hào)為1,擴(kuò)展分區(qū)的次設(shè)備號(hào)為2、3、4,邏輯分區(qū)使用5、6、…。設(shè)備操作宏MAJOR()和MINOR()可分別用于獲取主、次設(shè)備號(hào),宏MKDEV()用于將主設(shè)備號(hào)和次設(shè)備號(hào)合并為設(shè)備號(hào),這些宏定義在“include/linux/kdev_t.h”中。設(shè)備文件的主設(shè)備號(hào)必須與設(shè)備驅(qū)動(dòng)程序在注冊(cè)時(shí)申請(qǐng)的主設(shè)備號(hào)一致,否則用戶(hù)進(jìn)程將無(wú)法訪(fǎng)問(wèn)到設(shè)備驅(qū)動(dòng)程。所有已經(jīng)注冊(cè)的硬件設(shè)備的主設(shè)備號(hào)都可以從“/proc/devices”文件中得到。使用“mknod”命令可以創(chuàng)建指定類(lèi)型的設(shè)備文件,同時(shí)為其分配相應(yīng)的主設(shè)備號(hào)和次設(shè)備號(hào)(生成設(shè)備文件需要具有root權(quán)限),如下命令:
mknod/dev/hda1b80其中,/dev/hda1是設(shè)備名,b表示塊設(shè)備,8是主設(shè)備號(hào),0是次設(shè)備號(hào)。(6)設(shè)備文件相關(guān)的數(shù)據(jù)結(jié)構(gòu)設(shè)備文件作為L(zhǎng)inux的一種特殊文件,也可以通過(guò)普通文件的操作函數(shù)訪(fǎng)問(wèn),前提是必須實(shí)現(xiàn)文件操作中的相應(yīng)函數(shù),這些函數(shù)和文件相關(guān)數(shù)據(jù)結(jié)構(gòu)的定義是對(duì)應(yīng)的。
1)file_operations
(文件操作)file_operations是定義文件操作的數(shù)據(jù)結(jié)構(gòu),其中定義了一組I/O操作的接口函數(shù),在驅(qū)動(dòng)程序中編寫(xiě)這些接口函數(shù),之后在執(zhí)行設(shè)備文件操作的時(shí)候,由操作系統(tǒng)調(diào)用相應(yīng)的函數(shù)。該數(shù)據(jù)結(jié)構(gòu)在Linux的“include/linux/fs.h”中定義。struct
file_operations
{structmodule*owner;loff_t(*llseek)(structfile*,loff_t,int);ssize_t(*read)(structfile*,char*,size_t,loff_t*);ssize_t(*write)(structfile*,constchar*,size_t,loff_t*);int(*readdir)(structfile*,void*,filldir_t);unsignedint(*poll)(structfile*,struct
poll_table_struct*);int(*ioctl)(struct
inode*,structfile*,unsignedint,unsignedlong);int(*mmap)(structfile*,struct
vm_area_struct*);int(*open)(struct
inode*,structfile*);int(*flush)(structfile*);int(*release)(struct
inode*,structfile*);int(*fsync)(structfile*,struct
dentry*,int
datasync);int(*fasync)(int,structfile*,int);int(*lock)(structfile*,int,struct
file_lock*);ssize_t(*readv)(structfile*,conststruct
iovec*,unsignedlong,loff_t*);ssize_t(*writev)(structfile*,conststruct
iovec*,unsignedlong,loff_t*);};表12-2file_operations
結(jié)構(gòu)owner
module的擁有者。llseek重新定位讀寫(xiě)位置。read從設(shè)備中讀取數(shù)據(jù)。write向字符設(shè)備中寫(xiě)入數(shù)據(jù)。readdir只用于文件系統(tǒng),對(duì)設(shè)備無(wú)用。ioctl控制設(shè)備,除讀、寫(xiě)操作外的其他控制命令。mmap將設(shè)備內(nèi)存映射到進(jìn)程地址空間,通常只用于塊設(shè)備。open打開(kāi)設(shè)備并初始化設(shè)備。flush清除內(nèi)容,一般只用于網(wǎng)絡(luò)文件系統(tǒng)中。release關(guān)閉設(shè)備并釋放資源。fsync實(shí)現(xiàn)內(nèi)存與設(shè)備的同步,如將內(nèi)存數(shù)據(jù)寫(xiě)入硬盤(pán)。fasync實(shí)現(xiàn)內(nèi)存與設(shè)備之間的異步通訊。lock文件鎖定,用于文件共享時(shí)的互斥訪(fǎng)問(wèn)。readv在進(jìn)行讀操作前要驗(yàn)證地址是否可讀。writev在進(jìn)行寫(xiě)操作前要驗(yàn)證地址是否可寫(xiě)。
在驅(qū)動(dòng)程序中,需要根據(jù)驅(qū)動(dòng)程序需要的功能,編寫(xiě)相應(yīng)的函數(shù),然后將函數(shù)加入到file_operations結(jié)構(gòu)中。對(duì)于不需要的函數(shù)接口可以將其函數(shù)指針直接置為NULL,或者不用賦值。2.內(nèi)核模塊編程驅(qū)動(dòng)程序在Linux內(nèi)核中往往是以模塊形式出現(xiàn)的。與應(yīng)用程序的執(zhí)行過(guò)程不同,模塊通常只是預(yù)先向內(nèi)核注冊(cè)自己,當(dāng)內(nèi)核需要時(shí)響應(yīng)請(qǐng)求。模塊中包含兩個(gè)重要的函數(shù):init_module()和cleanup_module()。前者是模塊的入口,它為模塊調(diào)用做好準(zhǔn)備工作,而后者則是在模塊即將卸載時(shí)被調(diào)用,做一些清掃工作。
下面給出一個(gè)最基本的內(nèi)核模塊的例子,它不提供實(shí)際的功能,但是包含了模塊程序的框架。#include<linux/module.h>#include<linux/kernel.h>#include<linux/init.h>#include<linux/errno.h>staticint__initinit_module(void){/*每個(gè)模塊必須具有初始化函數(shù)*/printk("Testmoduleinit\n");return0;}staticvoid__exitcleanup_module(void){/*每個(gè)模塊必須具有退出函數(shù)*/printk("Hellomoduleexit\n");}module_init(init_module);/*模塊注冊(cè)函數(shù)*/module_exit(cleanup_module);一個(gè)Linux內(nèi)核模塊需包含模塊初始化和模塊卸載函數(shù),前者在insmod的時(shí)候運(yùn)行,后者在rmmod的時(shí)候運(yùn)行。初始化與卸載函數(shù)必須在宏module_init和module_exit使用前定義,否則會(huì)出現(xiàn)編譯錯(cuò)誤。內(nèi)核模塊與應(yīng)用程序運(yùn)行方式存在差別,因此在內(nèi)核模塊編寫(xiě)時(shí)需要注意以下事項(xiàng):(1)內(nèi)存分配函數(shù)在Linux內(nèi)核模式下,不能使用用戶(hù)態(tài)的malloc()和free()函數(shù)申請(qǐng)和釋放內(nèi)存。進(jìn)行內(nèi)核編程時(shí),最常用的內(nèi)存申請(qǐng)和釋放函數(shù)為在“include/linux/kernel.h”文件中聲明的kmalloc()和kfree(),其原型為:void*kmalloc(unsigned
int
len,intpriority);voidkfree(void*__ptr);
(2)內(nèi)核空間和用戶(hù)空間的數(shù)據(jù)交換Linux把存儲(chǔ)器分為“內(nèi)核空間”和“用戶(hù)空間”。操作系統(tǒng)內(nèi)核和驅(qū)動(dòng)程序在內(nèi)核空間中運(yùn)行,而用戶(hù)程序在用戶(hù)空間中運(yùn)行。二者之間不能直接訪(fǎng)問(wèn)對(duì)方的內(nèi)存,而應(yīng)該使用Linux中的用戶(hù)空間和內(nèi)核空間的數(shù)據(jù)交換函數(shù)。主要有:unsignedlongcopy_from_user(void*to,constvoid*from,unsignedlongn);/*從用戶(hù)空間拷貝數(shù)據(jù)到內(nèi)核空間*/unsignedlongcopy_to_user(void*to,void*from,unsignedlonglen);/*從內(nèi)核空間拷貝數(shù)據(jù)到用戶(hù)空間*/copy_from_user、copy_to_user函數(shù)返回不能被復(fù)制的字節(jié)數(shù),因此,如果完全復(fù)制成功,返回值為0。此外還有put_user和get_user函數(shù)用于內(nèi)核空間和用戶(hù)空間的單值交互(如char、int、long)。(3)輸出在內(nèi)核編程時(shí),不能使用用戶(hù)態(tài)C庫(kù)函數(shù)中的printf()函數(shù)輸出信息,而只能使用printk()。3.設(shè)備驅(qū)動(dòng)程序的結(jié)構(gòu)一個(gè)典型的Linux設(shè)備驅(qū)動(dòng)程序應(yīng)包含以下幾部分代碼:驅(qū)動(dòng)程序模塊的注冊(cè)與注銷(xiāo)函數(shù);設(shè)備的打開(kāi)、關(guān)閉、讀、寫(xiě)及需要的其它操作函數(shù);設(shè)備的中斷服務(wù)程序。4.驅(qū)動(dòng)程序的調(diào)試下面給出幾種設(shè)備驅(qū)動(dòng)程序調(diào)試的簡(jiǎn)單方法:(1)使用printk
函數(shù)最簡(jiǎn)單的方法是使用printk
函數(shù),printk
函數(shù)中可以使用附加不同的日志級(jí)別或消息優(yōu)先級(jí),如下例子:printk(KERN_DEBUG“Hereis:%s:%i\n”,__FILE,__LINE__);上述例子中宏KERN_DEBUG和后面的””之間沒(méi)有逗號(hào),因?yàn)楹陮?shí)際是字符串,在編譯時(shí)會(huì)由編譯器將它和后面的文本拼接在一起。(2)使用/proc文件系統(tǒng)/proc文件系統(tǒng)是由程序創(chuàng)建的文件系統(tǒng),內(nèi)核利用它向外輸出信息。/proc目錄下的每一個(gè)文件都被綁定到一個(gè)內(nèi)核函數(shù),這個(gè)函數(shù)在此文件被讀取時(shí),動(dòng)態(tài)地生成文件的內(nèi)容。典型的例子就是ps、top命令就是通過(guò)讀取/proc下的文件來(lái)獲取他們需要的信息。(3)使用ioctl
函數(shù)ioctl
系統(tǒng)調(diào)用會(huì)調(diào)用驅(qū)動(dòng)的ioctl
函數(shù),可以通過(guò)設(shè)置不同的命名號(hào)來(lái)編寫(xiě)一些測(cè)試函數(shù),使用ioctl
系統(tǒng)調(diào)用在用戶(hù)級(jí)調(diào)用這些函數(shù)進(jìn)行調(diào)試。5.虛擬設(shè)備驅(qū)動(dòng)程序-demo.c主要代碼分析(1)驅(qū)動(dòng)程序代碼參考驅(qū)動(dòng)程序demo.c中的demo_read、demo_write
函數(shù)完成驅(qū)動(dòng)程序的讀寫(xiě)接口功能,sort函數(shù)實(shí)現(xiàn)將用戶(hù)寫(xiě)入的數(shù)據(jù)選擇排序,通過(guò)讀取函數(shù)demo_read讀取轉(zhuǎn)換后的數(shù)據(jù)。這里只是演示接口的實(shí)現(xiàn)過(guò)程和內(nèi)核驅(qū)動(dòng)對(duì)用戶(hù)的數(shù)據(jù)的處理。demo_ioctl
函數(shù)演示ioctl
調(diào)用接口的實(shí)現(xiàn)過(guò)程。代碼清單12-4驅(qū)動(dòng)程序demo.c中sort函數(shù)staticvoidsort(){int
i,j,k;
int
len=WRI_LENGTH;
chartmp;for(i=0;i<len-1;i++){k=i;for(j=i+1;j<len;j++)if(drv_buf[j]<drv_buf[k])k=j;if(k!=i){tmp=drv_buf[k]; drv_buf[k]=drv_buf[i]; drv_buf[i]=tmp; }}}代碼清單12-5驅(qū)動(dòng)程序demo.c中demo_write()函數(shù)staticssize_tdemo_write(structfile*filp,constchar*buffer,size_tcount){if(count>MAX_BUF_LEN)count=MAX_BUF_LEN;copy_from_user(drv_buf,buffer,count);/*將用戶(hù)空間數(shù)據(jù)拷貝到內(nèi)核空間*/WRI_LENGTH=count;printk("userwritedatatodriver\n");sort(); /*將緩沖區(qū)數(shù)據(jù)排序*/returncount;}代碼清單12-6驅(qū)動(dòng)程序demo.c中demo_read()函數(shù)staticssize_t
demo_read(structfile*filp,char*buffer,size_t
count,loff_t*ppos){if(count>MAX_BUF_LEN)count=MAX_BUF_LEN;copy_to_user(buffer,drv_buf,count);printk("userreaddatafromdriver\n");returncount;}代碼清單12-7驅(qū)動(dòng)程序demo.c中demo_ioctl()函數(shù)staticint
demo_ioctl(struct
inode*inode,structfile*file,unsigned
int
cmd,unsignedlongarg){switch(cmd){/*根據(jù)不同的命令cmd取值,輸出不同的提示信息*/case1:printk("runingcommand1\n");break;case2:printk("runingcommand2\n");break;default:printk("error
cmdnumber\n");break;}return0;}2)用戶(hù)測(cè)試程序test_demo.c主要代碼代碼清單12-8用戶(hù)測(cè)試程序主函數(shù)intmain(){int
fd,i,j,k;charbuf[255];/*初始化緩沖區(qū)數(shù)據(jù)*/for(i=0;i<MAX_LEN;i++){buf[i]=i;}fd=open("/dev/demo",O_RDWR);/*調(diào)用open函數(shù)打開(kāi)設(shè)備文件*/if(fd<0){printf("####DEMOdeviceopenfail####\n");return(-1);}printf("write%dbytesdatato/dev/demo\n",MAX_LEN);showbuf(buf);/*顯示緩沖區(qū)中的數(shù)據(jù)*/write(fd,buf,MAX_LEN);/*調(diào)用write函數(shù)將數(shù)據(jù)寫(xiě)入內(nèi)核空間并逆序排列*/printf("Read%dbytesdatafrom/dev/demo\n",MAX_LEN);read(fd,buf,MAX_LEN);/*調(diào)用read函數(shù)讀取數(shù)據(jù)*/showbuf(buf);ioctl(fd,1,NULL);/*演示ioctl接口功能*/ioctl(fd,4,NULL);close(fd);}代碼清單12-9用戶(hù)測(cè)試程序showbuf函數(shù)voidshowbuf(char*buf){int
i,j=0;for(i=0;i<MAX_LEN;i++){if(i%4==0)printf("\n%4d:",j++);printf("%4d",buf[i]);}printf("\n**********************************************\n");}1.使用命令“cd/labs/Lab_13”進(jìn)入本次實(shí)驗(yàn)?zāi)夸洠褂胿i編輯器閱讀理解源代碼。2.使用“make”命令編譯驅(qū)動(dòng)模塊及測(cè)試程序。3.切換到下位機(jī)的“minicom”窗口,首先使用“insmod
demo.o”加載驅(qū)動(dòng)模塊demo.o,然后可用“l(fā)smod”命令來(lái)查看模塊是否已經(jīng)被插入,在不使用該模塊的時(shí)候還可以用“rmmod”命令來(lái)將模塊卸載。4.執(zhí)行“./test_demo”命令測(cè)試驅(qū)動(dòng)程序,運(yùn)行結(jié)果如圖12-18所示。12.4.5實(shí)驗(yàn)步驟1.添加一些自己的功能,修改源代碼并編譯調(diào)試。2.增加一個(gè)中斷驅(qū)動(dòng)函數(shù),比如PC機(jī)并口,試驗(yàn)中斷驅(qū)動(dòng)的實(shí)現(xiàn)。12.4.6習(xí)題12.5.1實(shí)驗(yàn)?zāi)康牧私庥|摸屏基本概念與工作原理,掌握開(kāi)發(fā)板上實(shí)現(xiàn)觸摸屏驅(qū)動(dòng)程序的基本原理,學(xué)習(xí)Linux字符設(shè)備驅(qū)動(dòng)程序開(kāi)發(fā)的基本過(guò)程,編程實(shí)現(xiàn)對(duì)觸摸屏的控制。12.5.2
實(shí)驗(yàn)設(shè)備
1臺(tái)已安裝Linux的PC機(jī)作為宿主機(jī)(上位機(jī)),1臺(tái)已燒寫(xiě)ARMLinux的博創(chuàng)經(jīng)典UP-TECH-S2410/P270-DVP實(shí)驗(yàn)箱作為目標(biāo)板(下位機(jī))。12.5.3實(shí)驗(yàn)內(nèi)容1.以一個(gè)簡(jiǎn)單的字符設(shè)備驅(qū)動(dòng)程序--觸摸屏驅(qū)動(dòng)程序?yàn)樵?,剖析字符設(shè)備驅(qū)動(dòng)程序的基本結(jié)構(gòu)。2.學(xué)習(xí)觸摸屏基本原理,掌握開(kāi)發(fā)板上觸摸屏控制相關(guān)技術(shù),理解對(duì)觸摸屏進(jìn)行坐標(biāo)定位輸出的編程方法。12.5字符設(shè)備驅(qū)動(dòng)實(shí)例-觸摸屏驅(qū)動(dòng)實(shí)驗(yàn)
12.5.4實(shí)驗(yàn)原理1.Linux字符設(shè)備管理(1)字符設(shè)備字符設(shè)備是指以字節(jié)為單位進(jìn)行順序訪(fǎng)問(wèn)的設(shè)備,它沒(méi)有緩沖區(qū),不支持隨即讀寫(xiě)。普通打印機(jī)、系統(tǒng)的串口以及終端顯示器是比較常見(jiàn)的字符設(shè)備,嵌入式系統(tǒng)中簡(jiǎn)單的按鍵、觸摸屏、手寫(xiě)板等都是字符設(shè)備。(2)字符設(shè)備管理在Linux系統(tǒng)下文件“fs/devices.c”定義了管理字符設(shè)備的數(shù)據(jù)結(jié)構(gòu)。代碼清單12-10管理字符設(shè)備的數(shù)據(jù)結(jié)構(gòu)struct
device_struct{constchar*name;/*指向設(shè)備驅(qū)動(dòng)程序名稱(chēng)*/
struct
file_operations*fops;/*指向設(shè)備文件操作函數(shù)指針*/}staticstruct
device_struct
chrdevs[MAX_CHRDEV];字符設(shè)備的初始化在內(nèi)核啟動(dòng)時(shí)進(jìn)行。某個(gè)字符設(shè)備初始化時(shí),其驅(qū)動(dòng)程序會(huì)構(gòu)造一個(gè)device_struct結(jié)構(gòu),將其作為字符向量數(shù)組chrdevs的一個(gè)元素向Linux內(nèi)核注冊(cè)。使用register_chrdev()函數(shù)注冊(cè)字符設(shè)備。該函數(shù)的主要功能是按照調(diào)用是指定的主設(shè)備號(hào)填寫(xiě)數(shù)組相應(yīng)表項(xiàng)中的設(shè)備名稱(chēng)和文件操作數(shù)據(jù)結(jié)構(gòu)指針。如果輸入的主設(shè)備號(hào)為0,則由系統(tǒng)動(dòng)態(tài)選擇一個(gè)沒(méi)有使用的主設(shè)備號(hào)返回給調(diào)用者。在打開(kāi)文件時(shí),根據(jù)主設(shè)備號(hào)從chrdevs中獲取對(duì)應(yīng)表項(xiàng)的文件操作指針fop,并填寫(xiě)到file結(jié)構(gòu)中。字符設(shè)備注銷(xiāo)時(shí)使用unregister_chrdev()。該函數(shù)的主要功能就是將對(duì)應(yīng)主設(shè)備號(hào)的chrdevs表項(xiàng)中的設(shè)備名稱(chēng)指針和文件操作指針設(shè)置為NULL。
在設(shè)備驅(qū)動(dòng)程序中,根據(jù)字符設(shè)備的硬件特性編寫(xiě)函數(shù)實(shí)現(xiàn)設(shè)備文件操作的各種函數(shù),然后初始化字符設(shè)備驅(qū)動(dòng)的file_operations結(jié)構(gòu)體。2.觸摸屏驅(qū)動(dòng)(1)觸摸屏工作原理觸摸屏按其工作原理的不同分為電阻式、電容式、聲表面波式和紅外線(xiàn)掃描式等類(lèi)型,使用最多的是電阻式觸摸屏。如圖12-19所示,電阻式觸摸屏的屏體部分是一塊與顯示器表面非常配合的多層復(fù)合薄膜,由一層玻璃或有機(jī)玻璃作為基層,表面涂有一層透明的ITO(氧化鋼)導(dǎo)電層,上面再蓋有一層外表面硬化處理、光滑防刮的塑料層,它的內(nèi)表面也涂有一層透明ITO導(dǎo)電層,在兩層導(dǎo)電層之間有許多細(xì)小(小于千分之一英寸)的透明“隔離點(diǎn)”把它們隔開(kāi)絕緣。當(dāng)手指或筆觸摸屏幕時(shí),平常相互絕緣的兩層導(dǎo)電層就在觸摸點(diǎn)位置有了一個(gè)接觸,因其中一面導(dǎo)電層(頂層)接通Y軸(或X軸)方向的5V均勻電壓場(chǎng),使得底層的電壓由零變?yōu)榉橇?,控制器偵測(cè)到這個(gè)接通后,進(jìn)行A/D轉(zhuǎn)換,并將得到的電壓值與5V相比即可得觸摸點(diǎn)的Y軸(或X軸)坐標(biāo)。圖12-19電阻式觸摸屏的結(jié)構(gòu)(2)觸摸屏坐標(biāo)識(shí)別如圖12-20所示,若上層用以讀取Y軸電壓值,下層用以讀取X軸電壓值。在待命狀態(tài)下,輪流將+5V電壓供給上層Y軸與下層X(jué)軸,當(dāng)一層導(dǎo)電時(shí),另一層接地以讀取電壓值。導(dǎo)電層上的電壓值持續(xù)地由A/D轉(zhuǎn)換器做轉(zhuǎn)換,送給控制器進(jìn)行處理。當(dāng)屏幕被觸摸時(shí),上層與下層的ITO導(dǎo)通,控制器檢查到上述動(dòng)作后,進(jìn)行如下處理:首先供給下層X(jué)軸+5V,并將上層Y軸接地;當(dāng)觸摸時(shí),上層將下層X(jué)軸的電壓值送出,A/D轉(zhuǎn)換器將電壓值數(shù)字化,計(jì)算出X軸的坐標(biāo)。接著,供給Y軸+5V,并將下層X(jué)軸接地;當(dāng)觸摸時(shí),下層將上層Y軸的電壓值送出,A/D轉(zhuǎn)換器將電壓值數(shù)字化,計(jì)算出Y軸的坐標(biāo)。圖12-20觸摸屏坐標(biāo)識(shí)別原理(3)S3C2410模數(shù)轉(zhuǎn)換器(ADC)及觸摸屏控制器S3C2410內(nèi)置1個(gè)8信道的10位模數(shù)轉(zhuǎn)換器(ADC),該ADC能以500KSPS的采樣頻率將外部的模擬信號(hào)轉(zhuǎn)換為10位二進(jìn)制數(shù)字代碼。同時(shí)ADC部分能與CPU的觸摸屏控制器協(xié)同工作,完成對(duì)觸摸屏絕對(duì)地址的測(cè)量。圖12-21是S3C2410上的A/D轉(zhuǎn)換器和觸摸屏接口的功能框圖。上拉電阻接在VDDA-ADC和AIN[7]之間。因此,觸摸屏的X+腳應(yīng)該接到S3C2410的AIN[7],Y+腳則接到S3C2410的AIN[5]。
圖12-21ADC及觸摸屏接口結(jié)構(gòu)圖3.觸摸屏驅(qū)動(dòng)程序分析觸摸屏是一個(gè)典型的字符設(shè)備,目錄“/labs”下有其驅(qū)動(dòng)程序s3c2410-ts.c,下面簡(jiǎn)要分析一下觸摸屏驅(qū)動(dòng)程序s3c2410-ts.c。(1)觸摸屏相關(guān)的數(shù)據(jù)結(jié)構(gòu)1)觸摸屏的的file_operations
結(jié)構(gòu)定義如下,該結(jié)構(gòu)給出了內(nèi)核對(duì)驅(qū)動(dòng)的調(diào)用接口。staticstruct
file_operationss3c2410_fops{owner:
THIS_MODULE,open:
s3c2410_ts_open,read:
s3c2410_ts_read,
release:
s3c2410_ts_release,#ifdefUSE_ASYNC
fasync:
s3c2410_ts_fasync,#endifpoll:
s3c2410_ts_poll,};2)觸摸屏的tsdev
結(jié)構(gòu)在觸摸屏驅(qū)動(dòng)程序中,全局變量structTS_DEVtsdev
是很重要的,用來(lái)保存觸摸屏的相關(guān)參數(shù)、等待處理的消息隊(duì)列、當(dāng)前采樣數(shù)據(jù)、上一次采樣數(shù)據(jù)等信息。typedef
struct
{unsignedint
penStatus;/*PEN_UP,PEN_DOWN,PEN_SAMPLE*/TS_RETbuf[MAX_TS_BUF];/*protectagainstoverrun(環(huán)形緩沖區(qū))*/unsignedinthead,tail;/*headandtailforqueuedevents(環(huán)形緩沖區(qū)的頭尾)*/wait_queue_head_t
wq;
/*等待隊(duì)列數(shù)據(jù)結(jié)構(gòu)*/spinlock_tlock;
/*自旋鎖*/#ifdefUSE_ASYNC
struct
fasync_struct*aq;#endif#ifdefCONFIG_PM
struct
pm_dev*pm_dev;#endif}TS_DEV;staticTS_DEVtsdev;(2)模塊初始化函數(shù)模塊初始化函數(shù)是調(diào)用s3c2410_ts_init函數(shù)來(lái)實(shí)現(xiàn)的,主要完成觸摸屏設(shè)備的內(nèi)核模塊加載、初始化系統(tǒng)I/O、中斷注冊(cè)、設(shè)備注冊(cè),為設(shè)備文件系統(tǒng)創(chuàng)建入口等標(biāo)準(zhǔn)的字符設(shè)備初始化工作。(3)模塊的退出函數(shù)模塊的退出函數(shù)為s3c2410_ts_exit,其功能就是清除已注冊(cè)的字符設(shè)備、中斷以及設(shè)備文件系統(tǒng)。(4)觸摸屏打開(kāi)設(shè)備文件函數(shù)該函數(shù)打開(kāi)設(shè)備,完成設(shè)備初始化和使用計(jì)數(shù)增一。(5)讀取設(shè)備文件的接口函數(shù)該函數(shù)是用戶(hù)層要調(diào)用的讀取設(shè)備文件的接口,實(shí)現(xiàn)的任務(wù)是將事件隊(duì)列從設(shè)備緩存中讀到用戶(hù)空間的數(shù)據(jù)緩存中。實(shí)現(xiàn)的過(guò)程主要是通過(guò)一個(gè)循環(huán),只有在事件隊(duì)列的頭、尾指針不重合時(shí),才能成功的從tsdev.tail指向的隊(duì)列尾部讀取到一組觸摸信息數(shù)據(jù),并退出循環(huán),否則調(diào)用讀取函數(shù)的進(jìn)程就要進(jìn)入睡眠。(6)釋放設(shè)備文件的函數(shù)該函數(shù)在定義了筆拖曳的情況下,調(diào)用del_timer
函數(shù)來(lái)刪除定時(shí)器,變量ts_timer
為struct
timer_list
數(shù)據(jù)結(jié)構(gòu),然后調(diào)用MOD_DEC_USE_COUNT;將設(shè)備文件計(jì)數(shù)器減一計(jì)數(shù),并返回。下面總結(jié)一下觸摸屏驅(qū)動(dòng)程序的大致流程:首先在驅(qū)動(dòng)模塊初始化函數(shù)中,除了對(duì)驅(qū)動(dòng)的字符設(shè)備的注冊(cè)外,還要對(duì)中斷進(jìn)行申請(qǐng)。申請(qǐng)了兩個(gè)觸摸屏相關(guān)的中斷,一個(gè)是IRQ_TC中斷,該中斷在筆按下時(shí),由XP管腳產(chǎn)生表示中斷的低電平信號(hào),而筆抬起時(shí)沒(méi)有中斷信號(hào)產(chǎn)生。另一個(gè)是IRQ_ADC_DONE中斷,該中斷是當(dāng)芯片內(nèi)部A/D轉(zhuǎn)換結(jié)束后,通知中斷控制器產(chǎn)生中斷,這時(shí)就可以去讀取轉(zhuǎn)換得到的數(shù)據(jù)。當(dāng)觸摸屏按下后,就會(huì)發(fā)出中斷,這時(shí)會(huì)調(diào)用申請(qǐng)中斷時(shí)附帶的s3c2410_isr_tc中斷回調(diào)函數(shù),該函數(shù)中判斷若為筆抬起則啟動(dòng)x軸坐標(biāo)的A/D轉(zhuǎn)換。當(dāng)轉(zhuǎn)換完畢后就會(huì)產(chǎn)生ADC中斷,這時(shí)就會(huì)調(diào)用申請(qǐng)中斷時(shí)附帶的s3c2410_isr_adc中斷回調(diào)函數(shù),在該函數(shù)中進(jìn)行判斷,若x軸坐標(biāo)轉(zhuǎn)換結(jié)束馬上進(jìn)行y軸坐標(biāo)的A/D轉(zhuǎn)換轉(zhuǎn)換;若y軸坐標(biāo)轉(zhuǎn)換結(jié)束,則重新回到等待中斷模式,然后將坐標(biāo)值寫(xiě)入環(huán)形緩沖區(qū),并環(huán)形等待隊(duì)列中的進(jìn)程。
1.使用命令“cd/labs/Lab_14”進(jìn)入本次實(shí)驗(yàn)?zāi)夸?,使用vi閱讀理解觸摸屏驅(qū)動(dòng)程序“s3c2410-ts.c”。2.使用“make”命令編譯其測(cè)試程序“testTS.c”。3.切換到下位機(jī)的“minicom”窗口,使用NFSmount掛載上位機(jī)的“/labs”目錄到“/host”,進(jìn)入“Lab_14”目錄,執(zhí)行“./testTS”命令測(cè)試觸摸屏驅(qū)動(dòng)程序,顯示相應(yīng)的坐標(biāo)點(diǎn)信息如圖12-22所示。12.5.5實(shí)驗(yàn)步驟1.另外找一個(gè)Linux的設(shè)備驅(qū)動(dòng)程序(在Linux源碼的drivers目錄下),剖析它的結(jié)構(gòu)及工作原理。2.把UP-TECHS2410/P270DVP開(kāi)發(fā)平臺(tái)上的觸摸屏驅(qū)動(dòng)從內(nèi)核中卸載,自己動(dòng)手寫(xiě)一個(gè)類(lèi)似的驅(qū)動(dòng)程序,以新驅(qū)動(dòng)代替舊驅(qū)動(dòng)并編譯進(jìn)內(nèi)核看看運(yùn)行情況。12.5.6習(xí)題12.6.1實(shí)驗(yàn)?zāi)康牧私釲CD基本概念與原理,理解LCD的驅(qū)動(dòng)控制,熟悉用總線(xiàn)方式驅(qū)動(dòng)LCD模塊,熟悉用ARM內(nèi)置的LCD控制器驅(qū)動(dòng)LCD。12.6.2
實(shí)驗(yàn)設(shè)備
1臺(tái)已安裝Linux的PC機(jī)作為宿主機(jī)(上位機(jī)),1臺(tái)已燒寫(xiě)ARMLinux的博創(chuàng)經(jīng)典UP-TECH-S2410/P270-DVP實(shí)驗(yàn)箱作為目標(biāo)板(下位機(jī))。12.6.3實(shí)驗(yàn)內(nèi)容1.學(xué)習(xí)LCD顯示器的基本原理,理解其驅(qū)動(dòng)控制方法。2.掌握開(kāi)發(fā)平臺(tái)內(nèi)置的LCD控制器來(lái)驅(qū)動(dòng)LCD。12.6LCD驅(qū)動(dòng)控制實(shí)驗(yàn)12.6.4實(shí)驗(yàn)原理1.LCD顯示(LiquidCrystalDisplay)原理(1)LCD顯示器LCD顯示器中的液晶體在外加交流電場(chǎng)的作用下排列狀態(tài)會(huì)發(fā)生變化,呈不規(guī)則扭轉(zhuǎn)形狀,形成了一個(gè)個(gè)光線(xiàn)閘門(mén),從而控制液晶顯示器件背后的光線(xiàn)是否穿透,呈現(xiàn)明與暗或者透過(guò)與不透過(guò)的顯示效果,人們才能在LCD屏上看到深淺不一、錯(cuò)落有致的圖像。LCD顯示器中的每個(gè)顯示像素都可以單獨(dú)被電場(chǎng)控制,不同的顯示像素按照控制信號(hào)的“指揮”便可以在顯示屏上組成不同的字符、數(shù)字及圖形。因此,建立顯示所需的電場(chǎng)與顯示像素的組合就成為液晶顯示驅(qū)動(dòng)器和液晶顯示控制器的功能。(2)LCD顯示器的類(lèi)型LCD顯示器的種類(lèi)很多,不同種類(lèi)的LCD顯示器,其顯示的控制方式不同。本實(shí)驗(yàn)只介紹STN(SuperTwistedNematic,超扭曲向列)LCD和TFT(Thin-filmtransistor,薄膜晶體管)LCD兩類(lèi)顯示器的顯示原理。STN-LCD和TFT-LCD都使用“向列型”液晶,利用電場(chǎng)來(lái)控制液晶的方向。通常液晶體夾在兩片玻璃中間,玻璃的表面上先鍍有一層透明而導(dǎo)電的薄膜以作電極之用,然后在有薄膜電極的玻璃上鍍表面配向劑,以使液晶順著一個(gè)特定且平行玻璃表面的方向排列。STN-LCD顯示屏中的液晶,其自然狀態(tài)具有90度的扭曲,利用電場(chǎng)可使液晶旋轉(zhuǎn),液晶的折射系數(shù)隨液晶的方向而改變,光經(jīng)過(guò)STN型液晶后,偏極性發(fā)生變化。只要選擇適當(dāng)?shù)模构獾钠珮O性旋轉(zhuǎn)到180~270度,就可利用兩個(gè)平行偏光片使得光完全不能通過(guò)。若使液晶方向與電場(chǎng)方向平行,這樣光的偏極性就不會(huì)改變,光就可通過(guò)第二個(gè)偏光片。于是,就可控制光的明暗了。而STN液晶之所以能顯示彩色,是因?yàn)樵赟TN液晶顯示器加上一個(gè)彩色濾光片,并將單色顯示矩陣中的每一像素分成三個(gè)子像素,分別通過(guò)彩色濾光片顯示紅、綠、藍(lán)三原色,就可以顯示出色彩了。STN型液晶屬于反射式LCD期間,它的好處是功耗小,但在比較暗的環(huán)境中清晰度很差,需要配備外部照明光源。TFT-LCD液晶顯示技術(shù)采用了“主動(dòng)式矩陣”的方式來(lái)驅(qū)動(dòng),其切面結(jié)構(gòu)圖如圖12-23所示。方法是利用薄膜技術(shù)所做成的電晶體電極,利用掃描的方法“主動(dòng)的”控制任意一個(gè)顯示點(diǎn)的開(kāi)與關(guān)。光源照射時(shí)先通過(guò)下偏光板向上透出,借助液晶分子傳導(dǎo)光線(xiàn)。電極通過(guò)時(shí),液晶分子的排列狀態(tài)發(fā)生變化。此外,由于TFT晶體管具有電容效應(yīng),能夠保持電位狀態(tài),直到下一次TFT電極再加電時(shí)才改變其排列方式。和STN相比,TFT有出色的色彩飽和度、還原能力和更高的對(duì)比度,但是缺點(diǎn)就是比較耗電,而且成本也比較高。圖12-23TFT-LCD的切面結(jié)構(gòu)圖2.LCD的控制器(1)LCD控制器的功能LCD顯示屏的顯示需要LCD驅(qū)動(dòng)器和LCD控制器兩部分硬件邏輯來(lái)控制。LCD驅(qū)動(dòng)器用來(lái)建立顯示所需的電場(chǎng),LCD控制器用來(lái)建立顯示像素與顯示緩沖區(qū)的對(duì)應(yīng)關(guān)系。(2)3C2410芯片內(nèi)置的LCD控制器S3C2410芯片中具有內(nèi)置的LCD控制器,它將系統(tǒng)主存中的顯示緩存中的LCD圖象數(shù)據(jù)傳輸?shù)酵獠縇CD驅(qū)動(dòng)器中。它支持灰度LCD和彩色LCD。在灰度LCD上,可以支持單色、4級(jí)灰度和16級(jí)灰度模式的灰度LCD。在彩色LCD上,可以支持256級(jí)彩色,使用STN-LCD可以支持4096級(jí)彩色。它還支持帶調(diào)色板功能的彩色TFT-LCD顯示器,以及不帶調(diào)色板的真彩TFT-LCD顯示器(其每個(gè)像素用16位或24位二進(jìn)制數(shù)表示)。支持分辯率為640*480、320*240、160*160以及其它規(guī)格的多種LCD。S3C2410中內(nèi)置的LCD控制器的邏輯框圖如圖12-24所示。LCD控制器用于傳輸顯示數(shù)據(jù)并產(chǎn)生必要的控制信號(hào),如VFRAME、VLINE、VCLK和VM等信號(hào)。除了控制信號(hào),還有顯示數(shù)據(jù)的數(shù)據(jù)端口VD[23:0]。
LCD控制器包含REGBANK、LCDCDMA、VIDPRCS、TIMEGEN和LPC3600。圖12-24LCD控制器邏輯框圖3.Linux下LCD驅(qū)動(dòng)(1)幀緩沖設(shè)備Linux工作在保護(hù)模式下,所以用戶(hù)進(jìn)程無(wú)法像DOS那樣使用顯卡BIOS里提供的中斷調(diào)用來(lái)實(shí)現(xiàn)直接寫(xiě)屏。因此,Linux為顯示設(shè)備提供了一個(gè)驅(qū)動(dòng)接口,把顯存抽象為幀緩沖(Framebuffer)設(shè)備,它允許上層應(yīng)用程序在圖像模式下直接對(duì)顯示緩沖區(qū)進(jìn)行讀寫(xiě)操作,用戶(hù)不必關(guān)心物理顯存的位置。幀緩沖驅(qū)動(dòng)程序?qū)崿F(xiàn)兩個(gè)方面的工作:一是對(duì)LCD及其相關(guān)部分的初始化,包括緩沖區(qū)的創(chuàng)建和對(duì)DMA通道設(shè)置;另一方面是對(duì)緩沖區(qū)的讀寫(xiě)及控制,具體到代碼為read、write、ioctl等系統(tǒng)調(diào)用接口。至于將緩沖區(qū)中的顯示內(nèi)容輸出到LCD顯示屏上,則由硬件自動(dòng)完成。對(duì)于軟件來(lái)說(shuō)是透明的。當(dāng)對(duì)DMA通道和緩沖區(qū)設(shè)置完成后,DMA開(kāi)始正常工作,并將緩沖區(qū)的內(nèi)容不斷發(fā)送到LCD上。這個(gè)過(guò)程就是通過(guò)DMA方式對(duì)LCD不斷刷新。幀緩沖設(shè)備對(duì)應(yīng)的設(shè)備文件為“/dev/fb*”,若系統(tǒng)有多個(gè)顯示卡,Linux下還可支持多個(gè)幀緩沖設(shè)備,最多可達(dá)32個(gè),分別為“/dev/fb0”到“/dev/fb31”,而“/dev/fb”則為當(dāng)前缺省的幀緩沖設(shè)備,通常指向/dev/fb0。在嵌入式系統(tǒng)中幀緩沖設(shè)備為標(biāo)準(zhǔn)字符設(shè)備,主設(shè)備號(hào)為29,次設(shè)備號(hào)則從0到31。(2)幀緩沖設(shè)備操作通過(guò)“/dev/fb”,應(yīng)用程序的操作主要有這幾種:1)讀/寫(xiě)“/dev/fb”讀/寫(xiě)“/dev/fb”相當(dāng)于讀/寫(xiě)屏幕緩沖區(qū)。2)映射(map)操作由于Linux工作在保護(hù)模式,每個(gè)應(yīng)用程序都有自己的虛擬地址空間,在應(yīng)用程序中是不能直接訪(fǎng)問(wèn)物理緩沖區(qū)地址的。為此Linux在文件操作file_operations結(jié)構(gòu)中提供了mmap函數(shù),可將文件的內(nèi)容映射到用戶(hù)空間。對(duì)于幀緩沖設(shè)備,則可通過(guò)映射操作,可將屏幕緩沖區(qū)的物理地址映射到用戶(hù)空間的一段虛擬地址中,之后用戶(hù)就能通過(guò)讀寫(xiě)這段虛擬地址訪(fǎng)問(wèn)屏幕緩沖區(qū),在屏幕上繪圖了。3)I/O控制對(duì)于幀緩沖設(shè)備,對(duì)設(shè)備文件的ioctl操作可讀取/設(shè)置顯示設(shè)備及屏幕的參數(shù),如分辨率、顯示顏色數(shù)、屏幕大小等等。ioctl的操作是由底層的驅(qū)動(dòng)程序來(lái)完成的。4.開(kāi)發(fā)平臺(tái)上的LCD顯示器S3C2410核心板提供一個(gè)32Pin的薄膜線(xiàn)插座,連接8寸16bitTFT真彩液晶屏,分辨率為640×480。由于LCD的驅(qū)動(dòng)程序比較復(fù)雜,因此,將其直接編譯進(jìn)內(nèi)核,應(yīng)用程序只需調(diào)用其提供的相關(guān)函數(shù),編程實(shí)現(xiàn)文本、圖形的顯示即可。需要注意的是:TFT-LCD為16位數(shù)據(jù),每個(gè)像素占2字節(jié),其RGB定義為R:G:B=5:6:5。1.使用命令“cd/labs/Lab_15”進(jìn)入本次實(shí)驗(yàn)?zāi)夸?,使用vi閱讀理解“Lcd.c”、“Lcd.h”的源代碼,熟悉其中顯示文本、畫(huà)線(xiàn)、畫(huà)圓等函數(shù)。2.使用“make”命令測(cè)試程序“test_lcd.c”。3.切換到下位機(jī)的“minicom”窗口,執(zhí)行“./test_lcd”命令測(cè)試LCD驅(qū)動(dòng)程序的顯示功能。12.6.5實(shí)驗(yàn)步驟1.修改測(cè)試程序,畫(huà)出奧運(yùn)五環(huán),并在LCD上移動(dòng)顯示。(參考程序見(jiàn)test_lcd01.c)2.修改測(cè)試程序,顯示ASCII字符或漢字字符;3.修改測(cè)試程序,顯示彩色位圖。12.6.6習(xí)題12.7.1實(shí)驗(yàn)?zāi)康恼莆誙DAl341TS音頻芯片工作原理,熟悉Linux音頻驅(qū)動(dòng)程序?qū)崿F(xiàn)方法,熟悉播放軟件解碼編程基本知識(shí)。12.7.2
實(shí)驗(yàn)設(shè)備
1臺(tái)已安裝Linux的PC機(jī)作為宿主機(jī)(上位機(jī)),1臺(tái)已燒寫(xiě)ARMLinux的博創(chuàng)經(jīng)典UP-TECH-S2410/P270-DVP實(shí)驗(yàn)箱作為目標(biāo)板(下位機(jī))。12.7.3實(shí)驗(yàn)內(nèi)容1.學(xué)習(xí)音頻芯片工作原理;2.掌握音頻播放器的基本工作原理;3.了解S3C2410的IIS總線(xiàn)結(jié)構(gòu);4.剖析音頻驅(qū)動(dòng)程序的實(shí)現(xiàn)過(guò)程。12.7音頻驅(qū)動(dòng)及應(yīng)用實(shí)驗(yàn)
12.7.4實(shí)驗(yàn)原理1.音頻驅(qū)動(dòng)硬件體系結(jié)構(gòu)(1)IIS音頻接口音頻系統(tǒng)設(shè)計(jì)包括軟件設(shè)計(jì)和硬件設(shè)計(jì)兩方面,在硬件上使用了基于IIS總線(xiàn)的音頻系統(tǒng)體系結(jié)構(gòu)。IIS(Inter-ICSoundbus)又稱(chēng)I2S,是菲利浦公司提出的串行數(shù)字音頻總線(xiàn)協(xié)議。目前很多音頻芯片和MCU都提供了對(duì)IIS的支持,圖12-25是UP-TECHS2410/P270DVP音頻芯片接線(xiàn)圖。圖12-25UP-TECHS2410/P270DVP音頻芯片接線(xiàn)圖IIS總線(xiàn)只處理聲音數(shù)據(jù),其它信號(hào)如控制信號(hào)必須單獨(dú)傳輸。為了使芯片的引出管腳盡可能少,IIS只使用了四根串行總線(xiàn)。IIS音頻接口總線(xiàn)共有四根線(xiàn):串行數(shù)據(jù)輸入(IISDI)、串行數(shù)據(jù)輸出(IISDO)、左右聲道選擇(IISLRCK)和串行位時(shí)鐘(IISCLK)。由主控設(shè)備提供IISLRCK和IISCLK。UDAl341TS芯片除了提供IIS接口和麥克風(fēng)揚(yáng)聲器接口,還提供L3接口控制音量等。L3接口分別連到S3C2410的3個(gè)通用數(shù)據(jù)輸出引腳上。(2)IIS音頻接口相關(guān)寄存器IIS音頻接口相關(guān)的寄存器包括:IIS控制寄存器、IIS模式寄存器、IIS模式寄存器、IISFIFO接口寄存器,其地址及相關(guān)位設(shè)置參看教材。(3)DMA數(shù)據(jù)傳輸方式DMA(DirectMemoryAccess)技術(shù)是一種代替微處理器完成存儲(chǔ)器與外部設(shè)備或存儲(chǔ)器之間大數(shù)據(jù)量傳送的方法,也稱(chēng)直接存儲(chǔ)器存取方法。在一些高檔微機(jī)系統(tǒng)中,CPU對(duì)內(nèi)存的讀寫(xiě)速率可能還要高于DMA的傳送速率。DMA的主要優(yōu)點(diǎn)是當(dāng)需要把一個(gè)外設(shè)的大量數(shù)據(jù)送到指定內(nèi)存時(shí),它可以自動(dòng)完成傳送任務(wù)。也就是說(shuō)外設(shè)發(fā)出一個(gè)DMA請(qǐng)求,則DMA電路暫停CPU操作,并控制外設(shè)與內(nèi)存之間進(jìn)行一次傳數(shù),然后再讓CPU繼續(xù)執(zhí)行程序。這樣就使CPU節(jié)省了大量對(duì)外設(shè)查詢(xún)時(shí)間,從而提高了系統(tǒng)的整體性能。從這點(diǎn)上看,似乎與微機(jī)的中斷功能有點(diǎn)類(lèi)似。S3C2410X有4個(gè)DMA控制器,DCON0~DCON3,分別對(duì)應(yīng)4個(gè)獨(dú)立的DMA通道。其中DMA1(數(shù)據(jù)輸入)和DMA2(數(shù)據(jù)輸出)可用于IIS的控制。通過(guò)設(shè)置CPU的IISFCON寄存器可以使IIS接口工作在DMA模式下。此模式下FIFO寄存器組的控制權(quán)掌握在DMA控制器上。當(dāng)FIFO滿(mǎn)時(shí),由DMA控制器對(duì)FIFO中的數(shù)據(jù)進(jìn)行處理。DMA模式的選擇由IISCON寄存器的第四和第五位控制。
DCONn
寄存器的設(shè)置和位描述如表12-55和表12-56所示。(4)S3C2410X芯片與UDAl341TS音頻芯片的連接
S3C2410X芯片與UDAl341TS音頻芯片的連接如圖12-26所示。在這個(gè)體系結(jié)構(gòu)中,為了實(shí)現(xiàn)全雙工,數(shù)據(jù)傳輸使用兩個(gè)DMA通道。數(shù)據(jù)傳輸(以回放為例)先由內(nèi)部總線(xiàn)送到內(nèi)存,然后傳到BDMA控制器通道1,再通過(guò)IIS控制器寫(xiě)入IIS總線(xiàn)并傳輸給音頻芯片,通道2用來(lái)錄音。圖12-26S3C2410X與UDAl341TS音頻芯片的連接2.音頻設(shè)備底層軟件設(shè)計(jì)音頻設(shè)備驅(qū)動(dòng)程序的主要任務(wù)是控制音頻數(shù)據(jù)在硬件中流動(dòng),并為音頻應(yīng)用提供標(biāo)準(zhǔn)接口。在三星公司的ARM芯片中,I/O設(shè)備的寄存器作為內(nèi)存空間的一部分,可用普通的內(nèi)存訪(fǎng)問(wèn)語(yǔ)句讀寫(xiě)I/O寄存器,進(jìn)而控制外部設(shè)備。這是該嵌入式系統(tǒng)與傳統(tǒng)的基于Intel處理器的PC最大的不同。(1)音頻設(shè)備驅(qū)動(dòng)程序功能設(shè)備驅(qū)動(dòng)程序中需要完成的任務(wù)包括:對(duì)設(shè)備以及對(duì)應(yīng)資源初始化和釋放;讀取應(yīng)用程序傳送給設(shè)備文件的數(shù)據(jù)并回送應(yīng)用程序請(qǐng)求的數(shù)據(jù)。這需要在用戶(hù)空間、內(nèi)核空間、總線(xiàn)及外設(shè)之間傳輸數(shù)據(jù)。(2)驅(qū)動(dòng)程序構(gòu)架Linux驅(qū)動(dòng)程序中將音頻設(shè)備按功能分成不同類(lèi)型,每種類(lèi)型對(duì)應(yīng)不同的驅(qū)動(dòng)程序。UDAl341TS音頻芯片提供如下功能:1)數(shù)字化音頻。被稱(chēng)為DSP或Codec設(shè)備,其功能是實(shí)現(xiàn)播放數(shù)字化聲音文件或錄制聲音。2)混頻器。用來(lái)控制各種輸入輸出的音量大小,在本系統(tǒng)中對(duì)應(yīng)L3接口。在Linux設(shè)備驅(qū)動(dòng)程序?qū)⒃O(shè)備看成文件,在驅(qū)動(dòng)程序中將結(jié)構(gòu)file_operations
中的各個(gè)函數(shù)指針與驅(qū)動(dòng)程序?qū)?yīng)例程函數(shù)綁定,以實(shí)現(xiàn)虛擬文件系統(tǒng)VFS對(duì)邏輯文件的操作。數(shù)字音頻設(shè)備(audio)、混頻器(mixer)對(duì)應(yīng)的設(shè)備文件分別是“/dev/dsp”和“/dev/mixer”。(3)設(shè)備的初始化和卸載對(duì)“/dev/dsp”的驅(qū)動(dòng)設(shè)計(jì)主要包含:設(shè)備的初始化和卸載、內(nèi)存與DMA緩存區(qū)的管理、設(shè)備無(wú)關(guān)操作(例程)的實(shí)現(xiàn)以及中斷處理程序。在設(shè)備初始化中對(duì)音頻設(shè)備的相關(guān)寄存器初始化,并在設(shè)備注冊(cè)中使用了
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 安徽省-2024年-社區(qū)工作者-上半年筆試真題卷
- 光伏產(chǎn)品年終總結(jié)
- 車(chē)輛交通安全教育培訓(xùn)
- 防食品安全教育和環(huán)境宣傳主題班會(huì)
- 交通運(yùn)輸?shù)钠髽I(yè)管理與發(fā)展策略考核試卷
- 寵物滅火和緊急疏散考核試卷
- 摩托車(chē)的城市交通運(yùn)輸考核試卷
- 時(shí)尚服飾線(xiàn)下零售管理考核試卷
- 保安培訓(xùn)師博雅聘用合同
- 供應(yīng)鏈創(chuàng)新與變革策略
- 人教版八年級(jí)上冊(cè)古詩(shī)詞默寫(xiě)上下句(最全版)
- 聲光影的內(nèi)心感動(dòng):電影視聽(tīng)語(yǔ)言學(xué)習(xí)通章節(jié)答案期末考試題庫(kù)2023年
- 物業(yè)公司安全生產(chǎn)風(fēng)險(xiǎn)分級(jí)管控和隱患排查治理雙體系方案全套資料2019-2020完整實(shí)施方案模板
- 體育考研體育管理學(xué)36問(wèn)
- 5G NR中SRS和CSI-RS信號(hào)學(xué)習(xí)筆記
- 人教版九年級(jí)數(shù)學(xué)下冊(cè) (相似三角形的判定)相似課件(第3課時(shí))
- 爆款到品類(lèi):從理想L9看理想汽車(chē)的產(chǎn)品理念
- 三視圖的形成及投影規(guī)律教學(xué)課件
- 中醫(yī)養(yǎng)生中醫(yī)養(yǎng)生與體質(zhì)調(diào)護(hù)課件
- 面試業(yè)務(wù)員問(wèn)題及答案
- 戰(zhàn)略性領(lǐng)導(dǎo)力素質(zhì)模型字典
評(píng)論
0/150
提交評(píng)論