嵌入式系統(tǒng)概論第十二章_第1頁
嵌入式系統(tǒng)概論第十二章_第2頁
嵌入式系統(tǒng)概論第十二章_第3頁
嵌入式系統(tǒng)概論第十二章_第4頁
嵌入式系統(tǒng)概論第十二章_第5頁
已閱讀5頁,還剩92頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第12章擴展實驗本章包括8個擴展實驗,以設(shè)備驅(qū)動模塊的編寫、編譯、加載和卸載為主要內(nèi)容,對實驗箱自帶的比較復(fù)雜的模塊進行訪問和控制。目錄12.1小鍵盤實驗12.2嵌入式WEB服務(wù)器12.3利用GDBServer在下位機中調(diào)試執(zhí)行程序12.4設(shè)備驅(qū)動程序設(shè)計實驗12.5字符設(shè)備驅(qū)動實例-觸摸屏驅(qū)動實驗12.6LCD驅(qū)動控制實驗12.7音頻驅(qū)動及應(yīng)用實驗12.8SD卡使用實驗12.1.1實驗?zāi)康牧私怄I盤的工作原理,掌握開發(fā)板上小鍵盤的控制和驅(qū)動技術(shù),學(xué)習(xí)鍵盤相關(guān)的編程方法,將按下的數(shù)字鍵通過LED顯示。12.1.2

實驗設(shè)備

1臺已安裝Linux的PC機作為宿主機(上位機),1臺已燒寫ARMLinux的博創(chuàng)經(jīng)典UP-TECH-S2410/P270-DVP實驗箱作為目標板(下位機)。12.1.3實驗內(nèi)容1.學(xué)習(xí)鍵盤的工作原理,掌握鍵盤的驅(qū)動及編程技術(shù)。2.編程控制7段LED顯示小鍵盤所按鍵數(shù)字字符。12.1小鍵盤實驗1.鍵盤接口(1)鍵盤接口設(shè)計鍵盤是由若干個按鍵組成的開關(guān)矩陣。在嵌入式系統(tǒng)的鍵盤接口設(shè)計時,需要根據(jù)應(yīng)用的具體要求,設(shè)計鍵盤接口的硬件電路,同時還需要完成識別按鍵動作、生成按鍵鍵碼和按鍵具體功能的程序設(shè)計。(2)矩陣鍵盤接口程序需處理的問題對于由機械開關(guān)組成的矩陣鍵盤,其接口程序必須處理三個問題:去抖動、防串鍵和產(chǎn)生鍵值。1)抖動抖動是指當(dāng)鍵按下時,開關(guān)簧片的閉合有一個從斷開到不穩(wěn)定接觸,最后到可靠接觸的過程。同樣的現(xiàn)象在按鍵釋放時也存在。去抖動的方法主要采用軟件延時和硬件延時電路。2)串鍵串鍵是指多個鍵同時按下時產(chǎn)生的問題。解決的方法也是有軟件方法和硬件方法兩種。3)產(chǎn)生鍵值產(chǎn)生鍵值是指鍵盤接口必須把按下的鍵翻譯成有限位二進制代碼,以便微處理器識別。12.1.4實驗原理(3)鍵盤接口程序處理方法及其流程下面用一個6ⅹ4陣列的鍵盤(如圖12-1)為例來說明鍵盤接口的“行掃描”處理方式及其流程。圖12-16ⅹ4陣列鍵盤該鍵盤陣列由6行4列構(gòu)成,控制器采用“行掃描”方式來識別按鍵,具體過程如下:1)首先判斷鍵盤中有無鍵按下將全部行線0-5置低電平,然后檢測列線的狀態(tài)。只要有一列的電平為低,則表示鍵盤中有鍵被按下,而且閉合的鍵位于低電平線與6根行線相交叉的幾個按鍵之中。若所有列線均為高電平,則鍵盤中無鍵按下。2)判斷按鍵所在的位置在確認有鍵按下后,即可進入確定具體閉合鍵的過程。其方法是:首先將0行線置為低電平,其它1-5行線為高電平,然后依次檢測各列線的電平狀態(tài)。若某列為低,則該列線與第0行交叉處的按鍵就是按下的鍵;若所有列均為高電平,則第0行沒有鍵按下。然后再將第1行置為低電平,其它行線為高電平,使用上述方法檢測該行是否有鍵按下。這樣依次掃描其余行,直到找到該按鍵,得到其所在行碼及列碼。3)產(chǎn)生鍵值可以根據(jù)行碼及列碼查鍵值表確定按鍵,也可以通過行線和列線的狀態(tài)計算得到鍵值,然后進行處理。2.S3C2410經(jīng)典開發(fā)平臺板載的17鍵小鍵盤(1)小鍵盤的硬件連接及按鍵布局經(jīng)典開發(fā)平臺上17鍵小鍵盤和PS2接口、IC卡接口都由一片ATMEGA8單片機控制,通過IIC總線接到CPU,如圖12-3所示。電路中對IICSDA和IICSCL兩個信號都接有3.3K上拉電阻,其按鍵布局如圖12-4所示。圖12-3開發(fā)平臺17鍵小鍵盤的連接圖12-4小鍵盤按鍵布局結(jié)構(gòu)(2)小鍵盤編程由圖12-3可以看出,小鍵盤是由一片ATMEGA8單片機控制,通過IIC總線接到下位機的CPU,用戶編程時需要事先加載其驅(qū)動程序“i2c-tomega8.o”。然后在宿主機目錄“/labsl/Lab_10”找到Linux下的小鍵盤驅(qū)動程序“keyboard.c”,其中定義了如open、close、read等鍵盤操作的方法及掃描碼和鍵值對應(yīng)的鍵值表。本次實驗用戶程序處理流程如圖12-5所示,調(diào)用其驅(qū)動程序提供的方法讀取小鍵盤上的按鍵,驅(qū)動LED顯示按鍵信息。圖12-5用戶程序處理流程1.使用命令“cd/labsl/Lab_10”進入本次實驗?zāi)夸?,使用vi編輯器閱讀理解源代碼。2.運行“make”命令產(chǎn)生可執(zhí)行文件“key_led”。]3.切換到下位機的minicom窗口,使用NFSmount上位機的“/labsl”目錄到“/host”目錄,然后進入“/host/Lab_10/drivers”目錄,使用命令“insmodi2c-tomega8.o”插入ATMEGA8單片機驅(qū)動,使用命令“insmods3c2410-led.o”插入led驅(qū)動。4.執(zhí)行“./key_led”命令,在小鍵盤上按鍵,查看8字數(shù)碼管顯示按鍵信息。12.1.5實驗步驟1.修改用戶程序,完成簡單的鍵盤計算、LED顯示結(jié)果。2.重新定義小鍵盤健值,完成對應(yīng)功能鍵的處理。12.1.6習(xí)題12.2.1實驗?zāi)康恼莆赵贏RM開發(fā)板實現(xiàn)一個簡單WEB服務(wù)器的過程,學(xué)習(xí)在ARM開發(fā)板上的SOCKET網(wǎng)絡(luò)編程,學(xué)習(xí)Linux下的signal()函數(shù)的使用。12.2.2

實驗設(shè)備

1臺已安裝Linux的PC機作為宿主機(上位機),1臺已燒寫ARMLinux的博創(chuàng)經(jīng)典UP-TECH-S2410/P270-DVP實驗箱作為目標板(下位機)。12.2.3實驗內(nèi)容1.學(xué)習(xí)使用socket進行通訊編程的過程。2.了解一個實際的網(wǎng)絡(luò)通訊應(yīng)用程序整體設(shè)計,閱讀HTTP協(xié)議的相關(guān)內(nèi)容,學(xué)習(xí)幾個重要的網(wǎng)絡(luò)函數(shù)的使用方法。3.讀懂HTTPD.C源代碼,在此基礎(chǔ)上增加一些其他功能。4.在PC計算機上使用瀏覽器測試嵌入式WEB服務(wù)器的功能。12.2嵌入式WEB服務(wù)器

1.HTTP協(xié)議簡介

HTTP協(xié)議是一個屬于應(yīng)用層的面向?qū)ο蟮膮f(xié)議,由于其簡捷、快速的方式,適用于分布式超媒體信息系統(tǒng)。它于1990年提出,經(jīng)過幾年的使用與發(fā)展,得到不斷地完善和擴展。目前在WWW中使用的是HTTP/1.1。

HTTP協(xié)議的主要特點可概括如下:(1)支持客戶/服務(wù)器模式。(2)簡單快速:客戶向服務(wù)器請求服務(wù)時,只需傳送請求方法和路徑。請求方法常用的有GET、HEAD、POST。每種方法規(guī)定了客戶與服務(wù)器聯(lián)系的類型不同。由于HTTP協(xié)議簡單,使得HTTP服務(wù)器的程序規(guī)模小,因而通信速度很快。(3)靈活:HTTP允許傳輸任意類型的數(shù)據(jù)對象。正在傳輸?shù)念愋陀蒀ontent-Type加以標記。(4)無連接:無連接的含義是限制每次連接只處理一個請求。服務(wù)器處理完客戶的請求,并收到客戶的應(yīng)答后,即斷開連接。采用這種方式可以節(jié)省傳輸時間。(5)無狀態(tài):HTTP協(xié)議是無狀態(tài)協(xié)議。無狀態(tài)是指協(xié)議對于事務(wù)處理沒有記憶能力。缺少狀態(tài)意味著如果后續(xù)處理需要前面的信息,則它必須重傳,這樣可能導(dǎo)致每次連接傳送的數(shù)據(jù)量增大。另一方面,在服務(wù)器不需要先前信息時它的應(yīng)答就較快。12.2.4實驗原理2.實驗原理(1)軟件需求說明,如圖12-8所示。圖12-8軟件需求(2)功能需求詳細說明獲取服務(wù)器當(dāng)前目錄文件列表:將服務(wù)器當(dāng)前目錄下所有文件的信息發(fā)送給客戶端,信息包括:文件名、大小、日期。獲取指定文件:將客戶請求的文件發(fā)送給客戶。獲取HTML類型文件:將客戶請求的HTML類型文件發(fā)送給客戶。獲取純文本文件:將客戶請求的純文本發(fā)送給客戶。獲取JPG圖像文件:將客戶請求的JPG圖像文件發(fā)送給客戶。獲取GIF圖像文件:將客戶請求的GIF圖像文件發(fā)送給客戶。解析用戶請求:分析客戶的請求,將請求信息解析為幾個變量,包括:請求的命令、請求的文件名、請求的文件類型。(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”切換到本次實驗?zāi)夸?,使用vi編輯器閱讀理解源代碼。2.運行“make”命令編譯應(yīng)用程序“httpd.c”,產(chǎn)生可執(zhí)行文件httpd。3.切換到下位機的“minicom”窗口,使用NFS服務(wù)方式將HTTPD下載到開發(fā)板上,并拷貝測試用的網(wǎng)頁進行調(diào)試,本實驗中用的是index測試網(wǎng)頁。在下位機上執(zhí)行“./httpd”,顯示以下信息:startinghttpd...pressqtoquit.waitforconnection.

4.在上位機的瀏覽器中輸入“http://21”(即下位機的IP地址),觀察在客戶機的瀏覽器中的連接請求結(jié)果,點擊其中的超級鏈接“A/D數(shù)據(jù)采集”,則顯示采集到的下位機A/D轉(zhuǎn)換結(jié)果。12.2.5實驗步驟1.閱讀源程序,擴展其功能,用于在瀏覽器上監(jiān)控開發(fā)板各部件工作。2.自定義一些功能,使用網(wǎng)絡(luò)TCP協(xié)議實現(xiàn)。12.2.6習(xí)題12.3.1實驗?zāi)康膶⑦\行在上位機中的GDB工具通過網(wǎng)絡(luò)與運行在下位機中的GDBServer進行連接,實現(xiàn)通過上位機來調(diào)試執(zhí)行運行在下位機中的程序。12.3.2

實驗設(shè)備

1臺已安裝Linux的PC機作為宿主機(上位機),1臺已燒寫ARMLinux的博創(chuàng)經(jīng)典UP-TECH-S2410/P270-DVP實驗箱作為目標板(下位機)。12.3.3實驗內(nèi)容1.閱讀控制點陣式LED顯示的程序gdb_led.c和Makefile文件;2.通過交叉編譯生成運行在下位機上的可執(zhí)行文件gdb_led。3.在下位機中運行GDBServer;4.在上位機中運行GDB;5.通過GDB連接GDBServer;4.調(diào)試執(zhí)行運行在下位機上的程序gdb_led;12.3利用GDBServer在下位機中調(diào)試執(zhí)行程序

1.使用命令“cd/labs/Lab_12”進入本次實驗?zāi)夸洠喿x理解源代碼文件gdb_led.c,體會按行逐列點亮點陣式LED的方法。2.查看Makefile文件內(nèi)容,注意編譯時所加的參數(shù)“-g”。3.運行“make”命令產(chǎn)生可執(zhí)行文件“test_led”。4.切換到下位機的minicom窗口,使用命令“mount–t52:/labs/host”掛載上位機的“/labs”目錄到下位機的“/host”目錄,然后進入“/host/Lab_12”目錄,使用命令“insmods3c2410-led.o”加載LED的驅(qū)動程序,然后用lsmod查看裝載的結(jié)果。5.在minicom中執(zhí)行命令“./gdbserver21:4000gdb_led”,在下位機中啟動GDBServer。其中,“21”為下位機的IP地址,“4000”為GDBServer的監(jiān)聽端口,“gdb_led”為要調(diào)試執(zhí)行的程序。6.在上位機中進入“/labs/Lab_12”目錄,執(zhí)行命令“./armv4l-linux-gdbgdb_led”,在上位機中啟動GDB工具,進入GDB界面。其中,“gdb_led”為要調(diào)試執(zhí)行的程序。12.3.4實驗步驟7.在上位機的GDB界面中執(zhí)行命令“targetremote21:4000”,連接GDBServer,連接成功后,下位機界面如圖12-15所示,上位機界面如圖12-16所示。圖12-15GDBServer窗口圖12-16GDB窗口list1//從第一行開始分頁顯示源程序,每頁10行,按回車鍵顯示下一頁。break36//在第36行處,即語句“write(fd,mydata,10)”處創(chuàng)建斷點。infobreak//顯示斷點信息。continue//繼續(xù)執(zhí)行程序,將執(zhí)行到斷點處暫停,顯示斷點處語句。prints//顯示變量s的值。printmydata//顯示數(shù)組mydata的值。step//逐條語句執(zhí)行程序,將發(fā)現(xiàn)下位機上點陣式LED的0行0列燈被點亮。whatiss//顯示變量s的類型。continue//繼續(xù)執(zhí)行程序,將執(zhí)行到斷點處暫停,顯示斷點處語句。next//逐條語句執(zhí)行程序,將發(fā)現(xiàn)下位機上點陣式LED的0行1列燈被點亮。printmydata//顯示數(shù)組mydata的值。help//顯示GDB命令的分類和功能描述。helpdata//顯示data類命令及其功能描述。disable1//使斷點1失效。continue//繼續(xù)執(zhí)行程序,直到結(jié)束。quit//退出GDB環(huán)境。8.在上位機的GDB界面中執(zhí)行如下命令調(diào)試執(zhí)行運行在下位機中的程序gdb_led。1.在第30行處增加1個斷點,然后調(diào)試執(zhí)行程序。2.將程序gdb_led.c中控制LED顯示的循環(huán)語句放入用戶自定義函數(shù)“voidshow()”中,使main函數(shù)調(diào)用show函數(shù)來控制LED的顯示。在main函數(shù)中調(diào)用show函數(shù)處設(shè)置斷點,然后調(diào)試運行程序,比較GDB中的“step”和“next”命令的不同。3.調(diào)試運行過程中,使用GDB命令“setvariables=63”,修改變量“s”的值為63,觀察點陣式LED的顯示。4.將第32行語句中的“s*=2”修改“s+=s*2”,觀察點陣式LED的顯示,并解釋。12.3.5習(xí)題12.4.1實驗?zāi)康膶W(xué)習(xí)Linux下設(shè)備驅(qū)動程序設(shè)計的基礎(chǔ)知識,掌握使用模塊方式進行驅(qū)動程序開發(fā)、調(diào)試的過程。

12.4.2

實驗設(shè)備

1臺已安裝Linux的PC機作為宿主機(上位機),1臺已燒寫ARMLinux的博創(chuàng)經(jīng)典UP-TECH-S2410/P270-DVP實驗箱作為目標板(下位機)。12.4.3實驗內(nèi)容1.學(xué)習(xí)設(shè)備驅(qū)動程序設(shè)計相關(guān)知識;2.在宿主機上編寫一個簡單的虛擬設(shè)備驅(qū)動程序并進行調(diào)試;3.編寫實現(xiàn)驅(qū)動程序的各個接口函數(shù),分析并理解驅(qū)動程序與應(yīng)用程序的交互過程。12.4設(shè)備驅(qū)動程序設(shè)計實驗12.4.4實驗原理1.設(shè)備驅(qū)動程序簡介(1)設(shè)備驅(qū)動程序在嵌入式系統(tǒng)中,各種硬件設(shè)備繁多,而且各自沒有統(tǒng)一的標準,而控制硬件又是嵌入式系統(tǒng)的核心內(nèi)容。因此,在嵌入式系統(tǒng)中設(shè)備管理分為兩層:上層與設(shè)備無關(guān),它根據(jù)輸入輸出請求,通過特定的設(shè)備驅(qū)動程序接口,來與設(shè)備進行通信。下層與硬件設(shè)備密切相關(guān),常稱為設(shè)備驅(qū)動程序,它直接與相應(yīng)設(shè)備打交道,并且向上層提供一組訪問接口。

如圖12-17所示,在Linux系統(tǒng)中,系統(tǒng)調(diào)用是內(nèi)核和應(yīng)用程序之間的接口,而驅(qū)動程序是內(nèi)核和及其硬件之間的接口。驅(qū)動程序為應(yīng)用程序屏蔽了硬件細節(jié)。應(yīng)用程序可將硬件設(shè)備看作一個設(shè)備文件,象操作普通文件一樣對硬件設(shè)備進行操作。圖12-17內(nèi)核和應(yīng)用程序之間的通信(2)設(shè)備驅(qū)動程序的功能設(shè)備驅(qū)動程序是內(nèi)核的一部分,主要完成以下功能:對設(shè)備進行初始化和釋放,如對音頻設(shè)備而言包括向內(nèi)核注冊設(shè)備、設(shè)置音頻的輸入輸出參數(shù)(如采樣頻率、采樣寬度等)、分配音頻設(shè)備使用的內(nèi)核內(nèi)存等工作。把數(shù)據(jù)從內(nèi)核傳送到硬件和從硬件讀取數(shù)據(jù)并提交給內(nèi)核;讀取應(yīng)用程序傳送給設(shè)備文件的數(shù)據(jù)和回送應(yīng)用程序請求的數(shù)據(jù);檢測和處理硬件設(shè)備出現(xiàn)的錯誤。(3)驅(qū)動程序開發(fā)的方法驅(qū)動程序主要需要考慮下面三個方面:提供盡量多的選項給用戶,提高驅(qū)動程序的速度和效率,盡量使驅(qū)動程序簡單,使之易于維護。Linux的驅(qū)動開發(fā)調(diào)試有兩種方法:1)把設(shè)備驅(qū)動作為內(nèi)核的一部分,直接編譯到內(nèi)核中,隨同Linux啟動時加載,該方式稱為靜態(tài)編譯,這種方式效率較低,但在某些場合是唯一的方法。2)單獨作為一個模塊(module),編譯成.o(或2.6內(nèi)核下為.ko)文件,需要時使用“insmod”動態(tài)加載到內(nèi)核中;如果出現(xiàn)故障,可以使用“rmmod”從內(nèi)核中卸載模塊,不需要重新啟動內(nèi)核,這使驅(qū)動調(diào)試效率大大提高。該方式即動態(tài)連接。這種方式控制了內(nèi)核的大小,而模塊一旦被插入內(nèi)核,它就和內(nèi)核其他部分一樣。顯然動態(tài)連接比靜態(tài)連接有更多的好處。(4)設(shè)備分類目前,Linux系統(tǒng)支持的設(shè)備可分為三種:字符設(shè)備(characterdevice)、塊設(shè)備(blockdevice)和網(wǎng)絡(luò)接口設(shè)備(networkinterface)。當(dāng)然它們之間并不是要嚴格的加以區(qū)分。1)字符設(shè)備字符設(shè)備的讀寫以字節(jié)為單位按順序進行,存取時沒有緩沖區(qū)。對字符設(shè)備發(fā)出讀寫請求時,實際的硬件I/O緊接著就發(fā)生了,不支持隨機讀寫。典型的字符設(shè)備包括鼠標、鍵盤及串口等。2)塊設(shè)備塊設(shè)備讀寫以塊為單位,典型的塊大小為寫512或1024字節(jié),存取時有緩存支持以提高效率。當(dāng)用戶進程對設(shè)備發(fā)出讀寫請求時,驅(qū)動程序先查看緩存中的內(nèi)容,若緩存中的的數(shù)據(jù)能滿足用戶的要求就返回相應(yīng)的數(shù)據(jù),否則就調(diào)用相應(yīng)的請求函數(shù)來進行實際的I/O操作。典型的塊設(shè)備主要包括硬盤、軟盤、內(nèi)存、Flash等可以容納文件系統(tǒng)的存儲設(shè)備。3)網(wǎng)絡(luò)接口設(shè)備網(wǎng)絡(luò)接口設(shè)備是Linux中比較復(fù)雜的一種設(shè)備,通常是硬件設(shè)備,有時還可以是一個軟件設(shè)備(如回環(huán)接口loopback)。它們由內(nèi)核中網(wǎng)絡(luò)子系統(tǒng)驅(qū)動,負責(zé)發(fā)送和接收數(shù)據(jù)包,而且它并不需要了解每一項事務(wù)是如何映射到實際傳送的數(shù)據(jù)包的。網(wǎng)絡(luò)接口設(shè)備由內(nèi)核中的協(xié)議棧來管理,在Linux中采用給網(wǎng)絡(luò)接口設(shè)備分配一個唯一名字的方法來訪問該設(shè)備。(5)設(shè)備文件和設(shè)備號

1)設(shè)備文件Linux使用設(shè)備文件的概念來統(tǒng)一對設(shè)備的訪問接口,在引入設(shè)備文件系統(tǒng)(devfs)之前Linux將設(shè)備文件放在“/dev”目錄下,設(shè)備的命名一般為設(shè)備文件名+數(shù)字或字母表示的子類,例如“/dev/hda1”、“/dev/hda2”等。

2)設(shè)備號傳統(tǒng)的設(shè)備管理中,除了設(shè)備類型外,Linux內(nèi)核還需要一對稱作主設(shè)備號、次設(shè)備號的參數(shù),才能唯一標識設(shè)備。主設(shè)備號(magornumber)標識設(shè)備的類型,也標示設(shè)備對應(yīng)的驅(qū)動程序。主設(shè)備號相同的設(shè)備使用相同的驅(qū)動程序。一個主設(shè)備號可能有多個設(shè)備與之對應(yīng),這多個設(shè)備在驅(qū)動程序內(nèi)通過次設(shè)備號來進一步區(qū)分。次設(shè)備號(minornumber)標識了使用同一設(shè)備驅(qū)動程序的不同硬件設(shè)備。如PC機中的IDE設(shè)備,一般主設(shè)備號使用3,WINDOWS下進行的分區(qū),一般將主分區(qū)的次設(shè)備號為1,擴展分區(qū)的次設(shè)備號為2、3、4,邏輯分區(qū)使用5、6、…。設(shè)備操作宏MAJOR()和MINOR()可分別用于獲取主、次設(shè)備號,宏MKDEV()用于將主設(shè)備號和次設(shè)備號合并為設(shè)備號,這些宏定義在“include/linux/kdev_t.h”中。設(shè)備文件的主設(shè)備號必須與設(shè)備驅(qū)動程序在注冊時申請的主設(shè)備號一致,否則用戶進程將無法訪問到設(shè)備驅(qū)動程。所有已經(jīng)注冊的硬件設(shè)備的主設(shè)備號都可以從“/proc/devices”文件中得到。使用“mknod”命令可以創(chuàng)建指定類型的設(shè)備文件,同時為其分配相應(yīng)的主設(shè)備號和次設(shè)備號(生成設(shè)備文件需要具有root權(quán)限),如下命令:

mknod/dev/hda1b80其中,/dev/hda1是設(shè)備名,b表示塊設(shè)備,8是主設(shè)備號,0是次設(shè)備號。(6)設(shè)備文件相關(guān)的數(shù)據(jù)結(jié)構(gòu)設(shè)備文件作為Linux的一種特殊文件,也可以通過普通文件的操作函數(shù)訪問,前提是必須實現(xiàn)文件操作中的相應(yīng)函數(shù),這些函數(shù)和文件相關(guān)數(shù)據(jù)結(jié)構(gòu)的定義是對應(yīng)的。

1)file_operations

(文件操作)file_operations是定義文件操作的數(shù)據(jù)結(jié)構(gòu),其中定義了一組I/O操作的接口函數(shù),在驅(qū)動程序中編寫這些接口函數(shù),之后在執(zhí)行設(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重新定位讀寫位置。read從設(shè)備中讀取數(shù)據(jù)。write向字符設(shè)備中寫入數(shù)據(jù)。readdir只用于文件系統(tǒng),對設(shè)備無用。ioctl控制設(shè)備,除讀、寫操作外的其他控制命令。mmap將設(shè)備內(nèi)存映射到進程地址空間,通常只用于塊設(shè)備。open打開設(shè)備并初始化設(shè)備。flush清除內(nèi)容,一般只用于網(wǎng)絡(luò)文件系統(tǒng)中。release關(guān)閉設(shè)備并釋放資源。fsync實現(xiàn)內(nèi)存與設(shè)備的同步,如將內(nèi)存數(shù)據(jù)寫入硬盤。fasync實現(xiàn)內(nèi)存與設(shè)備之間的異步通訊。lock文件鎖定,用于文件共享時的互斥訪問。readv在進行讀操作前要驗證地址是否可讀。writev在進行寫操作前要驗證地址是否可寫。

在驅(qū)動程序中,需要根據(jù)驅(qū)動程序需要的功能,編寫相應(yīng)的函數(shù),然后將函數(shù)加入到file_operations結(jié)構(gòu)中。對于不需要的函數(shù)接口可以將其函數(shù)指針直接置為NULL,或者不用賦值。2.內(nèi)核模塊編程驅(qū)動程序在Linux內(nèi)核中往往是以模塊形式出現(xiàn)的。與應(yīng)用程序的執(zhí)行過程不同,模塊通常只是預(yù)先向內(nèi)核注冊自己,當(dāng)內(nèi)核需要時響應(yīng)請求。模塊中包含兩個重要的函數(shù):init_module()和cleanup_module()。前者是模塊的入口,它為模塊調(diào)用做好準備工作,而后者則是在模塊即將卸載時被調(diào)用,做一些清掃工作。

下面給出一個最基本的內(nèi)核模塊的例子,它不提供實際的功能,但是包含了模塊程序的框架。#include<linux/module.h>#include<linux/kernel.h>#include<linux/init.h>#include<linux/errno.h>staticint__initinit_module(void){/*每個模塊必須具有初始化函數(shù)*/printk("Testmoduleinit\n");return0;}staticvoid__exitcleanup_module(void){/*每個模塊必須具有退出函數(shù)*/printk("Hellomoduleexit\n");}module_init(init_module);/*模塊注冊函數(shù)*/module_exit(cleanup_module);一個Linux內(nèi)核模塊需包含模塊初始化和模塊卸載函數(shù),前者在insmod的時候運行,后者在rmmod的時候運行。初始化與卸載函數(shù)必須在宏module_init和module_exit使用前定義,否則會出現(xiàn)編譯錯誤。內(nèi)核模塊與應(yīng)用程序運行方式存在差別,因此在內(nèi)核模塊編寫時需要注意以下事項:(1)內(nèi)存分配函數(shù)在Linux內(nèi)核模式下,不能使用用戶態(tài)的malloc()和free()函數(shù)申請和釋放內(nèi)存。進行內(nèi)核編程時,最常用的內(nèi)存申請和釋放函數(shù)為在“include/linux/kernel.h”文件中聲明的kmalloc()和kfree(),其原型為:void*kmalloc(unsigned

int

len,intpriority);voidkfree(void*__ptr);

(2)內(nèi)核空間和用戶空間的數(shù)據(jù)交換Linux把存儲器分為“內(nèi)核空間”和“用戶空間”。操作系統(tǒng)內(nèi)核和驅(qū)動程序在內(nèi)核空間中運行,而用戶程序在用戶空間中運行。二者之間不能直接訪問對方的內(nèi)存,而應(yīng)該使用Linux中的用戶空間和內(nèi)核空間的數(shù)據(jù)交換函數(shù)。主要有:unsignedlongcopy_from_user(void*to,constvoid*from,unsignedlongn);/*從用戶空間拷貝數(shù)據(jù)到內(nèi)核空間*/unsignedlongcopy_to_user(void*to,void*from,unsignedlonglen);/*從內(nèi)核空間拷貝數(shù)據(jù)到用戶空間*/copy_from_user、copy_to_user函數(shù)返回不能被復(fù)制的字節(jié)數(shù),因此,如果完全復(fù)制成功,返回值為0。此外還有put_user和get_user函數(shù)用于內(nèi)核空間和用戶空間的單值交互(如char、int、long)。(3)輸出在內(nèi)核編程時,不能使用用戶態(tài)C庫函數(shù)中的printf()函數(shù)輸出信息,而只能使用printk()。3.設(shè)備驅(qū)動程序的結(jié)構(gòu)一個典型的Linux設(shè)備驅(qū)動程序應(yīng)包含以下幾部分代碼:驅(qū)動程序模塊的注冊與注銷函數(shù);設(shè)備的打開、關(guān)閉、讀、寫及需要的其它操作函數(shù);設(shè)備的中斷服務(wù)程序。4.驅(qū)動程序的調(diào)試下面給出幾種設(shè)備驅(qū)動程序調(diào)試的簡單方法:(1)使用printk

函數(shù)最簡單的方法是使用printk

函數(shù),printk

函數(shù)中可以使用附加不同的日志級別或消息優(yōu)先級,如下例子:printk(KERN_DEBUG“Hereis:%s:%i\n”,__FILE,__LINE__);上述例子中宏KERN_DEBUG和后面的””之間沒有逗號,因為宏實際是字符串,在編譯時會由編譯器將它和后面的文本拼接在一起。(2)使用/proc文件系統(tǒng)/proc文件系統(tǒng)是由程序創(chuàng)建的文件系統(tǒng),內(nèi)核利用它向外輸出信息。/proc目錄下的每一個文件都被綁定到一個內(nèi)核函數(shù),這個函數(shù)在此文件被讀取時,動態(tài)地生成文件的內(nèi)容。典型的例子就是ps、top命令就是通過讀取/proc下的文件來獲取他們需要的信息。(3)使用ioctl

函數(shù)ioctl

系統(tǒng)調(diào)用會調(diào)用驅(qū)動的ioctl

函數(shù),可以通過設(shè)置不同的命名號來編寫一些測試函數(shù),使用ioctl

系統(tǒng)調(diào)用在用戶級調(diào)用這些函數(shù)進行調(diào)試。5.虛擬設(shè)備驅(qū)動程序-demo.c主要代碼分析(1)驅(qū)動程序代碼參考驅(qū)動程序demo.c中的demo_read、demo_write

函數(shù)完成驅(qū)動程序的讀寫接口功能,sort函數(shù)實現(xiàn)將用戶寫入的數(shù)據(jù)選擇排序,通過讀取函數(shù)demo_read讀取轉(zhuǎn)換后的數(shù)據(jù)。這里只是演示接口的實現(xiàn)過程和內(nèi)核驅(qū)動對用戶的數(shù)據(jù)的處理。demo_ioctl

函數(shù)演示ioctl

調(diào)用接口的實現(xiàn)過程。代碼清單12-4驅(qū)動程序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ū)動程序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);/*將用戶空間數(shù)據(jù)拷貝到內(nèi)核空間*/WRI_LENGTH=count;printk("userwritedatatodriver\n");sort(); /*將緩沖區(qū)數(shù)據(jù)排序*/returncount;}代碼清單12-6驅(qū)動程序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ū)動程序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)用戶測試程序test_demo.c主要代碼代碼清單12-8用戶測試程序主函數(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ù)打開設(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ù)寫入內(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用戶測試程序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”進入本次實驗?zāi)夸?,使用vi編輯器閱讀理解源代碼。2.使用“make”命令編譯驅(qū)動模塊及測試程序。3.切換到下位機的“minicom”窗口,首先使用“insmod

demo.o”加載驅(qū)動模塊demo.o,然后可用“l(fā)smod”命令來查看模塊是否已經(jīng)被插入,在不使用該模塊的時候還可以用“rmmod”命令來將模塊卸載。4.執(zhí)行“./test_demo”命令測試驅(qū)動程序,運行結(jié)果如圖12-18所示。12.4.5實驗步驟1.添加一些自己的功能,修改源代碼并編譯調(diào)試。2.增加一個中斷驅(qū)動函數(shù),比如PC機并口,試驗中斷驅(qū)動的實現(xiàn)。12.4.6習(xí)題12.5.1實驗?zāi)康牧私庥|摸屏基本概念與工作原理,掌握開發(fā)板上實現(xiàn)觸摸屏驅(qū)動程序的基本原理,學(xué)習(xí)Linux字符設(shè)備驅(qū)動程序開發(fā)的基本過程,編程實現(xiàn)對觸摸屏的控制。12.5.2

實驗設(shè)備

1臺已安裝Linux的PC機作為宿主機(上位機),1臺已燒寫ARMLinux的博創(chuàng)經(jīng)典UP-TECH-S2410/P270-DVP實驗箱作為目標板(下位機)。12.5.3實驗內(nèi)容1.以一個簡單的字符設(shè)備驅(qū)動程序--觸摸屏驅(qū)動程序為原型,剖析字符設(shè)備驅(qū)動程序的基本結(jié)構(gòu)。2.學(xué)習(xí)觸摸屏基本原理,掌握開發(fā)板上觸摸屏控制相關(guān)技術(shù),理解對觸摸屏進行坐標定位輸出的編程方法。12.5字符設(shè)備驅(qū)動實例-觸摸屏驅(qū)動實驗

12.5.4實驗原理1.Linux字符設(shè)備管理(1)字符設(shè)備字符設(shè)備是指以字節(jié)為單位進行順序訪問的設(shè)備,它沒有緩沖區(qū),不支持隨即讀寫。普通打印機、系統(tǒng)的串口以及終端顯示器是比較常見的字符設(shè)備,嵌入式系統(tǒng)中簡單的按鍵、觸摸屏、手寫板等都是字符設(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ū)動程序名稱*/

struct

file_operations*fops;/*指向設(shè)備文件操作函數(shù)指針*/}staticstruct

device_struct

chrdevs[MAX_CHRDEV];字符設(shè)備的初始化在內(nèi)核啟動時進行。某個字符設(shè)備初始化時,其驅(qū)動程序會構(gòu)造一個device_struct結(jié)構(gòu),將其作為字符向量數(shù)組chrdevs的一個元素向Linux內(nèi)核注冊。使用register_chrdev()函數(shù)注冊字符設(shè)備。該函數(shù)的主要功能是按照調(diào)用是指定的主設(shè)備號填寫數(shù)組相應(yīng)表項中的設(shè)備名稱和文件操作數(shù)據(jù)結(jié)構(gòu)指針。如果輸入的主設(shè)備號為0,則由系統(tǒng)動態(tài)選擇一個沒有使用的主設(shè)備號返回給調(diào)用者。在打開文件時,根據(jù)主設(shè)備號從chrdevs中獲取對應(yīng)表項的文件操作指針fop,并填寫到file結(jié)構(gòu)中。字符設(shè)備注銷時使用unregister_chrdev()。該函數(shù)的主要功能就是將對應(yīng)主設(shè)備號的chrdevs表項中的設(shè)備名稱指針和文件操作指針設(shè)置為NULL。

在設(shè)備驅(qū)動程序中,根據(jù)字符設(shè)備的硬件特性編寫函數(shù)實現(xiàn)設(shè)備文件操作的各種函數(shù),然后初始化字符設(shè)備驅(qū)動的file_operations結(jié)構(gòu)體。2.觸摸屏驅(qū)動(1)觸摸屏工作原理觸摸屏按其工作原理的不同分為電阻式、電容式、聲表面波式和紅外線掃描式等類型,使用最多的是電阻式觸摸屏。如圖12-19所示,電阻式觸摸屏的屏體部分是一塊與顯示器表面非常配合的多層復(fù)合薄膜,由一層玻璃或有機玻璃作為基層,表面涂有一層透明的ITO(氧化鋼)導(dǎo)電層,上面再蓋有一層外表面硬化處理、光滑防刮的塑料層,它的內(nèi)表面也涂有一層透明ITO導(dǎo)電層,在兩層導(dǎo)電層之間有許多細小(小于千分之一英寸)的透明“隔離點”把它們隔開絕緣。當(dāng)手指或筆觸摸屏幕時,平常相互絕緣的兩層導(dǎo)電層就在觸摸點位置有了一個接觸,因其中一面導(dǎo)電層(頂層)接通Y軸(或X軸)方向的5V均勻電壓場,使得底層的電壓由零變?yōu)榉橇?,控制器偵測到這個接通后,進行A/D轉(zhuǎn)換,并將得到的電壓值與5V相比即可得觸摸點的Y軸(或X軸)坐標。圖12-19電阻式觸摸屏的結(jié)構(gòu)(2)觸摸屏坐標識別如圖12-20所示,若上層用以讀取Y軸電壓值,下層用以讀取X軸電壓值。在待命狀態(tài)下,輪流將+5V電壓供給上層Y軸與下層X軸,當(dāng)一層導(dǎo)電時,另一層接地以讀取電壓值。導(dǎo)電層上的電壓值持續(xù)地由A/D轉(zhuǎn)換器做轉(zhuǎn)換,送給控制器進行處理。當(dāng)屏幕被觸摸時,上層與下層的ITO導(dǎo)通,控制器檢查到上述動作后,進行如下處理:首先供給下層X軸+5V,并將上層Y軸接地;當(dāng)觸摸時,上層將下層X軸的電壓值送出,A/D轉(zhuǎn)換器將電壓值數(shù)字化,計算出X軸的坐標。接著,供給Y軸+5V,并將下層X軸接地;當(dāng)觸摸時,下層將上層Y軸的電壓值送出,A/D轉(zhuǎn)換器將電壓值數(shù)字化,計算出Y軸的坐標。圖12-20觸摸屏坐標識別原理(3)S3C2410模數(shù)轉(zhuǎn)換器(ADC)及觸摸屏控制器S3C2410內(nèi)置1個8信道的10位模數(shù)轉(zhuǎn)換器(ADC),該ADC能以500KSPS的采樣頻率將外部的模擬信號轉(zhuǎn)換為10位二進制數(shù)字代碼。同時ADC部分能與CPU的觸摸屏控制器協(xié)同工作,完成對觸摸屏絕對地址的測量。圖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ū)動程序分析觸摸屏是一個典型的字符設(shè)備,目錄“/labs”下有其驅(qū)動程序s3c2410-ts.c,下面簡要分析一下觸摸屏驅(qū)動程序s3c2410-ts.c。(1)觸摸屏相關(guān)的數(shù)據(jù)結(jié)構(gòu)1)觸摸屏的的file_operations

結(jié)構(gòu)定義如下,該結(jié)構(gòu)給出了內(nèi)核對驅(qū)動的調(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ū)動程序中,全局變量structTS_DEVtsdev

是很重要的,用來保存觸摸屏的相關(guān)參數(shù)、等待處理的消息隊列、當(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;

/*等待隊列數(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ù)來實現(xiàn)的,主要完成觸摸屏設(shè)備的內(nèi)核模塊加載、初始化系統(tǒng)I/O、中斷注冊、設(shè)備注冊,為設(shè)備文件系統(tǒng)創(chuàng)建入口等標準的字符設(shè)備初始化工作。(3)模塊的退出函數(shù)模塊的退出函數(shù)為s3c2410_ts_exit,其功能就是清除已注冊的字符設(shè)備、中斷以及設(shè)備文件系統(tǒng)。(4)觸摸屏打開設(shè)備文件函數(shù)該函數(shù)打開設(shè)備,完成設(shè)備初始化和使用計數(shù)增一。(5)讀取設(shè)備文件的接口函數(shù)該函數(shù)是用戶層要調(diào)用的讀取設(shè)備文件的接口,實現(xiàn)的任務(wù)是將事件隊列從設(shè)備緩存中讀到用戶空間的數(shù)據(jù)緩存中。實現(xiàn)的過程主要是通過一個循環(huán),只有在事件隊列的頭、尾指針不重合時,才能成功的從tsdev.tail指向的隊列尾部讀取到一組觸摸信息數(shù)據(jù),并退出循環(huán),否則調(diào)用讀取函數(shù)的進程就要進入睡眠。(6)釋放設(shè)備文件的函數(shù)該函數(shù)在定義了筆拖曳的情況下,調(diào)用del_timer

函數(shù)來刪除定時器,變量ts_timer

為struct

timer_list

數(shù)據(jù)結(jié)構(gòu),然后調(diào)用MOD_DEC_USE_COUNT;將設(shè)備文件計數(shù)器減一計數(shù),并返回。下面總結(jié)一下觸摸屏驅(qū)動程序的大致流程:首先在驅(qū)動模塊初始化函數(shù)中,除了對驅(qū)動的字符設(shè)備的注冊外,還要對中斷進行申請。申請了兩個觸摸屏相關(guān)的中斷,一個是IRQ_TC中斷,該中斷在筆按下時,由XP管腳產(chǎn)生表示中斷的低電平信號,而筆抬起時沒有中斷信號產(chǎn)生。另一個是IRQ_ADC_DONE中斷,該中斷是當(dāng)芯片內(nèi)部A/D轉(zhuǎn)換結(jié)束后,通知中斷控制器產(chǎn)生中斷,這時就可以去讀取轉(zhuǎn)換得到的數(shù)據(jù)。當(dāng)觸摸屏按下后,就會發(fā)出中斷,這時會調(diào)用申請中斷時附帶的s3c2410_isr_tc中斷回調(diào)函數(shù),該函數(shù)中判斷若為筆抬起則啟動x軸坐標的A/D轉(zhuǎn)換。當(dāng)轉(zhuǎn)換完畢后就會產(chǎn)生ADC中斷,這時就會調(diào)用申請中斷時附帶的s3c2410_isr_adc中斷回調(diào)函數(shù),在該函數(shù)中進行判斷,若x軸坐標轉(zhuǎn)換結(jié)束馬上進行y軸坐標的A/D轉(zhuǎn)換轉(zhuǎn)換;若y軸坐標轉(zhuǎn)換結(jié)束,則重新回到等待中斷模式,然后將坐標值寫入環(huán)形緩沖區(qū),并環(huán)形等待隊列中的進程。

1.使用命令“cd/labs/Lab_14”進入本次實驗?zāi)夸?,使用vi閱讀理解觸摸屏驅(qū)動程序“s3c2410-ts.c”。2.使用“make”命令編譯其測試程序“testTS.c”。3.切換到下位機的“minicom”窗口,使用NFSmount掛載上位機的“/labs”目錄到“/host”,進入“Lab_14”目錄,執(zhí)行“./testTS”命令測試觸摸屏驅(qū)動程序,顯示相應(yīng)的坐標點信息如圖12-22所示。12.5.5實驗步驟1.另外找一個Linux的設(shè)備驅(qū)動程序(在Linux源碼的drivers目錄下),剖析它的結(jié)構(gòu)及工作原理。2.把UP-TECHS2410/P270DVP開發(fā)平臺上的觸摸屏驅(qū)動從內(nèi)核中卸載,自己動手寫一個類似的驅(qū)動程序,以新驅(qū)動代替舊驅(qū)動并編譯進內(nèi)核看看運行情況。12.5.6習(xí)題12.6.1實驗?zāi)康牧私釲CD基本概念與原理,理解LCD的驅(qū)動控制,熟悉用總線方式驅(qū)動LCD模塊,熟悉用ARM內(nèi)置的LCD控制器驅(qū)動LCD。12.6.2

實驗設(shè)備

1臺已安裝Linux的PC機作為宿主機(上位機),1臺已燒寫ARMLinux的博創(chuàng)經(jīng)典UP-TECH-S2410/P270-DVP實驗箱作為目標板(下位機)。12.6.3實驗內(nèi)容1.學(xué)習(xí)LCD顯示器的基本原理,理解其驅(qū)動控制方法。2.掌握開發(fā)平臺內(nèi)置的LCD控制器來驅(qū)動LCD。12.6LCD驅(qū)動控制實驗12.6.4實驗原理1.LCD顯示(LiquidCrystalDisplay)原理(1)LCD顯示器LCD顯示器中的液晶體在外加交流電場的作用下排列狀態(tài)會發(fā)生變化,呈不規(guī)則扭轉(zhuǎn)形狀,形成了一個個光線閘門,從而控制液晶顯示器件背后的光線是否穿透,呈現(xiàn)明與暗或者透過與不透過的顯示效果,人們才能在LCD屏上看到深淺不一、錯落有致的圖像。LCD顯示器中的每個顯示像素都可以單獨被電場控制,不同的顯示像素按照控制信號的“指揮”便可以在顯示屏上組成不同的字符、數(shù)字及圖形。因此,建立顯示所需的電場與顯示像素的組合就成為液晶顯示驅(qū)動器和液晶顯示控制器的功能。(2)LCD顯示器的類型LCD顯示器的種類很多,不同種類的LCD顯示器,其顯示的控制方式不同。本實驗只介紹STN(SuperTwistedNematic,超扭曲向列)LCD和TFT(Thin-filmtransistor,薄膜晶體管)LCD兩類顯示器的顯示原理。STN-LCD和TFT-LCD都使用“向列型”液晶,利用電場來控制液晶的方向。通常液晶體夾在兩片玻璃中間,玻璃的表面上先鍍有一層透明而導(dǎo)電的薄膜以作電極之用,然后在有薄膜電極的玻璃上鍍表面配向劑,以使液晶順著一個特定且平行玻璃表面的方向排列。STN-LCD顯示屏中的液晶,其自然狀態(tài)具有90度的扭曲,利用電場可使液晶旋轉(zhuǎn),液晶的折射系數(shù)隨液晶的方向而改變,光經(jīng)過STN型液晶后,偏極性發(fā)生變化。只要選擇適當(dāng)?shù)?,使光的偏極性旋轉(zhuǎn)到180~270度,就可利用兩個平行偏光片使得光完全不能通過。若使液晶方向與電場方向平行,這樣光的偏極性就不會改變,光就可通過第二個偏光片。于是,就可控制光的明暗了。而STN液晶之所以能顯示彩色,是因為在STN液晶顯示器加上一個彩色濾光片,并將單色顯示矩陣中的每一像素分成三個子像素,分別通過彩色濾光片顯示紅、綠、藍三原色,就可以顯示出色彩了。STN型液晶屬于反射式LCD期間,它的好處是功耗小,但在比較暗的環(huán)境中清晰度很差,需要配備外部照明光源。TFT-LCD液晶顯示技術(shù)采用了“主動式矩陣”的方式來驅(qū)動,其切面結(jié)構(gòu)圖如圖12-23所示。方法是利用薄膜技術(shù)所做成的電晶體電極,利用掃描的方法“主動的”控制任意一個顯示點的開與關(guān)。光源照射時先通過下偏光板向上透出,借助液晶分子傳導(dǎo)光線。電極通過時,液晶分子的排列狀態(tài)發(fā)生變化。此外,由于TFT晶體管具有電容效應(yīng),能夠保持電位狀態(tài),直到下一次TFT電極再加電時才改變其排列方式。和STN相比,TFT有出色的色彩飽和度、還原能力和更高的對比度,但是缺點就是比較耗電,而且成本也比較高。圖12-23TFT-LCD的切面結(jié)構(gòu)圖2.LCD的控制器(1)LCD控制器的功能LCD顯示屏的顯示需要LCD驅(qū)動器和LCD控制器兩部分硬件邏輯來控制。LCD驅(qū)動器用來建立顯示所需的電場,LCD控制器用來建立顯示像素與顯示緩沖區(qū)的對應(yīng)關(guān)系。(2)3C2410芯片內(nèi)置的LCD控制器S3C2410芯片中具有內(nèi)置的LCD控制器,它將系統(tǒng)主存中的顯示緩存中的LCD圖象數(shù)據(jù)傳輸?shù)酵獠縇CD驅(qū)動器中。它支持灰度LCD和彩色LCD。在灰度LCD上,可以支持單色、4級灰度和16級灰度模式的灰度LCD。在彩色LCD上,可以支持256級彩色,使用STN-LCD可以支持4096級彩色。它還支持帶調(diào)色板功能的彩色TFT-LCD顯示器,以及不帶調(diào)色板的真彩TFT-LCD顯示器(其每個像素用16位或24位二進制數(shù)表示)。支持分辯率為640*480、320*240、160*160以及其它規(guī)格的多種LCD。S3C2410中內(nèi)置的LCD控制器的邏輯框圖如圖12-24所示。LCD控制器用于傳輸顯示數(shù)據(jù)并產(chǎn)生必要的控制信號,如VFRAME、VLINE、VCLK和VM等信號。除了控制信號,還有顯示數(shù)據(jù)的數(shù)據(jù)端口VD[23:0]。

LCD控制器包含REGBANK、LCDCDMA、VIDPRCS、TIMEGEN和LPC3600。圖12-24LCD控制器邏輯框圖3.Linux下LCD驅(qū)動(1)幀緩沖設(shè)備Linux工作在保護模式下,所以用戶進程無法像DOS那樣使用顯卡BIOS里提供的中斷調(diào)用來實現(xiàn)直接寫屏。因此,Linux為顯示設(shè)備提供了一個驅(qū)動接口,把顯存抽象為幀緩沖(Framebuffer)設(shè)備,它允許上層應(yīng)用程序在圖像模式下直接對顯示緩沖區(qū)進行讀寫操作,用戶不必關(guān)心物理顯存的位置。幀緩沖驅(qū)動程序?qū)崿F(xiàn)兩個方面的工作:一是對LCD及其相關(guān)部分的初始化,包括緩沖區(qū)的創(chuàng)建和對DMA通道設(shè)置;另一方面是對緩沖區(qū)的讀寫及控制,具體到代碼為read、write、ioctl等系統(tǒng)調(diào)用接口。至于將緩沖區(qū)中的顯示內(nèi)容輸出到LCD顯示屏上,則由硬件自動完成。對于軟件來說是透明的。當(dāng)對DMA通道和緩沖區(qū)設(shè)置完成后,DMA開始正常工作,并將緩沖區(qū)的內(nèi)容不斷發(fā)送到LCD上。這個過程就是通過DMA方式對LCD不斷刷新。幀緩沖設(shè)備對應(yīng)的設(shè)備文件為“/dev/fb*”,若系統(tǒng)有多個顯示卡,Linux下還可支持多個幀緩沖設(shè)備,最多可達32個,分別為“/dev/fb0”到“/dev/fb31”,而“/dev/fb”則為當(dāng)前缺省的幀緩沖設(shè)備,通常指向/dev/fb0。在嵌入式系統(tǒng)中幀緩沖設(shè)備為標準字符設(shè)備,主設(shè)備號為29,次設(shè)備號則從0到31。(2)幀緩沖設(shè)備操作通過“/dev/fb”,應(yīng)用程序的操作主要有這幾種:1)讀/寫“/dev/fb”讀/寫“/dev/fb”相當(dāng)于讀/寫屏幕緩沖區(qū)。2)映射(map)操作由于Linux工作在保護模式,每個應(yīng)用程序都有自己的虛擬地址空間,在應(yīng)用程序中是不能直接訪問物理緩沖區(qū)地址的。為此Linux在文件操作file_operations結(jié)構(gòu)中提供了mmap函數(shù),可將文件的內(nèi)容映射到用戶空間。對于幀緩沖設(shè)備,則可通過映射操作,可將屏幕緩沖區(qū)的物理地址映射到用戶空間的一段虛擬地址中,之后用戶就能通過讀寫這段虛擬地址訪問屏幕緩沖區(qū),在屏幕上繪圖了。3)I/O控制對于幀緩沖設(shè)備,對設(shè)備文件的ioctl操作可讀取/設(shè)置顯示設(shè)備及屏幕的參數(shù),如分辨率、顯示顏色數(shù)、屏幕大小等等。ioctl的操作是由底層的驅(qū)動程序來完成的。4.開發(fā)平臺上的LCD顯示器S3C2410核心板提供一個32Pin的薄膜線插座,連接8寸16bitTFT真彩液晶屏,分辨率為640×480。由于LCD的驅(qū)動程序比較復(fù)雜,因此,將其直接編譯進內(nèi)核,應(yīng)用程序只需調(diào)用其提供的相關(guān)函數(shù),編程實現(xiàn)文本、圖形的顯示即可。需要注意的是:TFT-LCD為16位數(shù)據(jù),每個像素占2字節(jié),其RGB定義為R:G:B=5:6:5。1.使用命令“cd/labs/Lab_15”進入本次實驗?zāi)夸洠褂胿i閱讀理解“Lcd.c”、“Lcd.h”的源代碼,熟悉其中顯示文本、畫線、畫圓等函數(shù)。2.使用“make”命令測試程序“test_lcd.c”。3.切換到下位機的“minicom”窗口,執(zhí)行“./test_lcd”命令測試LCD驅(qū)動程序的顯示功能。12.6.5實驗步驟1.修改測試程序,畫出奧運五環(huán),并在LCD上移動顯示。(參考程序見test_lcd01.c)2.修改測試程序,顯示ASCII字符或漢字字符;3.修改測試程序,顯示彩色位圖。12.6.6習(xí)題12.7.1實驗?zāi)康恼莆誙DAl341TS音頻芯片工作原理,熟悉Linux音頻驅(qū)動程序?qū)崿F(xiàn)方法,熟悉播放軟件解碼編程基本知識。12.7.2

實驗設(shè)備

1臺已安裝Linux的PC機作為宿主機(上位機),1臺已燒寫ARMLinux的博創(chuàng)經(jīng)典UP-TECH-S2410/P270-DVP實驗箱作為目標板(下位機)。12.7.3實驗內(nèi)容1.學(xué)習(xí)音頻芯片工作原理;2.掌握音頻播放器的基本工作原理;3.了解S3C2410的IIS總線結(jié)構(gòu);4.剖析音頻驅(qū)動程序的實現(xiàn)過程。12.7音頻驅(qū)動及應(yīng)用實驗

12.7.4實驗原理1.音頻驅(qū)動硬件體系結(jié)構(gòu)(1)IIS音頻接口音頻系統(tǒng)設(shè)計包括軟件設(shè)計和硬件設(shè)計兩方面,在硬件上使用了基于IIS總線的音頻系統(tǒng)體系結(jié)構(gòu)。IIS(Inter-ICSoundbus)又稱I2S,是菲利浦公司提出的串行數(shù)字音頻總線協(xié)議。目前很多音頻芯片和MCU都提供了對IIS的支持,圖12-25是UP-TECHS2410/P270DVP音頻芯片接線圖。圖12-25UP-TECHS2410/P270DVP音頻芯片接線圖IIS總線只處理聲音數(shù)據(jù),其它信號如控制信號必須單獨傳輸。為了使芯片的引出管腳盡可能少,IIS只使用了四根串行總線。IIS音頻接口總線共有四根線:串行數(shù)據(jù)輸入(IISDI)、串行數(shù)據(jù)輸出(IISDO)、左右聲道選擇(IISLRCK)和串行位時鐘(IISCLK)。由主控設(shè)備提供IISLRCK和IISCLK。UDAl341TS芯片除了提供IIS接口和麥克風(fēng)揚聲器接口,還提供L3接口控制音量等。L3接口分別連到S3C2410的3個通用數(shù)據(jù)輸出引腳上。(2)IIS音頻接口相關(guān)寄存器IIS音頻接口相關(guān)的寄存器包括:IIS控制寄存器、IIS模式寄存器、IIS模式寄存器、IISFIFO接口寄存器,其地址及相關(guān)位設(shè)置參看教材。(3)DMA數(shù)據(jù)傳輸方式DMA(DirectMemoryAccess)技術(shù)是一種代替微處理器完成存儲器與外部設(shè)備或存儲器之間大數(shù)據(jù)量傳送的方法,也稱直接存儲器存取方法。在一些高檔微機系統(tǒng)中,CPU對內(nèi)存的讀寫速率可能還要高于DMA的傳送速率。DMA的主要優(yōu)點是當(dāng)需要把一個外設(shè)的大量數(shù)據(jù)送到指定內(nèi)存時,它可以自動完成傳送任務(wù)。也就是說外設(shè)發(fā)出一個DMA請求,則DMA電路暫停CPU操作,并控制外設(shè)與內(nèi)存之間進行一次傳數(shù),然后再讓CPU繼續(xù)執(zhí)行程序。這樣就使CPU節(jié)省了大量對外設(shè)查詢時間,從而提高了系統(tǒng)的整體性能。從這點上看,似乎與微機的中斷功能有點類似。S3C2410X有4個DMA控制器,DCON0~DCON3,分別對應(yīng)4個獨立的DMA通道。其中DMA1(數(shù)據(jù)輸入)和DMA2(數(shù)據(jù)輸出)可用于IIS的控制。通過設(shè)置CPU的IISFCON寄存器可以使IIS接口工作在DMA模式下。此模式下FIFO寄存器組的控制權(quán)掌握在DMA控制器上。當(dāng)FIFO滿時,由DMA控制器對FIFO中的數(shù)據(jù)進行處理。DMA模式的選擇由IISCON寄存器的第四和第五位控制。

DCONn

寄存器的設(shè)置和位描述如表12-55和表12-56所示。(4)S3C2410X芯片與UDAl341TS音頻芯片的連接

S3C2410X芯片與UDAl341TS音頻芯片的連接如圖12-26所示。在這個體系結(jié)構(gòu)中,為了實現(xiàn)全雙工,數(shù)據(jù)傳輸使用兩個DMA通道。數(shù)據(jù)傳輸(以回放為例)先由內(nèi)部總線送到內(nèi)存,然后傳到BDMA控制器通道1,再通過IIS控制器寫入IIS總線并傳輸給音頻芯片,通道2用來錄音。圖12-26S3C2410X與UDAl341TS音頻芯片的連接2.音頻設(shè)備底層軟件設(shè)計音頻設(shè)備驅(qū)動程序的主要任務(wù)是控制音頻數(shù)據(jù)在硬件中流動,并為音頻應(yīng)用提供標準接口。在三星公司的ARM芯片中,I/O設(shè)備的寄存器作為內(nèi)存空間的一部分,可用普通的內(nèi)存訪問語句讀寫I/O寄存器,進而控制外部設(shè)備。這是該嵌入式系統(tǒng)與傳統(tǒng)的基于Intel處理器的PC最大的不同。(1)音頻設(shè)備驅(qū)動程序功能設(shè)備驅(qū)動程序中需要完成的任務(wù)包括:對設(shè)備以及對應(yīng)資源初始化和釋放;讀取應(yīng)用程序傳送給設(shè)備文件的數(shù)據(jù)并回送應(yīng)用程序請求的數(shù)據(jù)。這需要在用戶空間、內(nèi)核空間、總線及外設(shè)之間傳輸數(shù)據(jù)。(2)驅(qū)動程序構(gòu)架Linux驅(qū)動程序中將音頻設(shè)備按功能分成不同類型,每種類型對應(yīng)不同的驅(qū)動程序。UDAl341TS音頻芯片提供如下功能:1)數(shù)字化音頻。被稱為DSP或Codec設(shè)備,其功能是實現(xiàn)播放數(shù)字化聲音文件或錄制聲音。2)混頻器。用來控制各種輸入輸出的音量大小,在本系統(tǒng)中對應(yīng)L3接口。在Linux設(shè)備驅(qū)動程序?qū)⒃O(shè)備看成文件,在驅(qū)動程序中將結(jié)構(gòu)file_operations

中的各個函數(shù)指針與驅(qū)動程序?qū)?yīng)例程函數(shù)綁定,以實現(xiàn)虛擬文件系統(tǒng)VFS對邏輯文件的操作。數(shù)字音頻設(shè)備(audio)、混頻器(mixer)對應(yīng)的設(shè)備文件分別是“/dev/dsp”和“/dev/mixer”。(3)設(shè)備的初始化和卸載對“/dev/dsp”的驅(qū)動設(shè)計主要包含:設(shè)備的初始化和卸載、內(nèi)存與DMA緩存區(qū)的管理、設(shè)備無關(guān)操作(例程)的實現(xiàn)以及中斷處理程序。在設(shè)備初始化中對音頻設(shè)備的相關(guān)寄存器初始化,并在設(shè)備注冊中使用了

溫馨提示

  • 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)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論