版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
實驗八I/O口驅(qū)動實驗【實驗?zāi)康摹?、 了解PXA270微處理器GPIO的功能2、 熟悉PXA270微處理器GPIO驅(qū)動程序的編寫方法3、 掌握驅(qū)動程序的加載過程和方法【實驗原理】Linux以模塊的形式加載設(shè)備類型,通常來說一個模塊對應(yīng)一個設(shè)備驅(qū)動,因此是可以分類的。將模塊分成不同的類型或者類并不是一成不變的,開發(fā)人員可以根據(jù)實際工作需要在一個模塊中實現(xiàn)不同的驅(qū)動程序。一般情況,一個設(shè)備驅(qū)動對應(yīng)一類設(shè)備的模塊方式,這樣便于多個設(shè)備的協(xié)調(diào)工作也利于應(yīng)用程序的開發(fā)和擴展。設(shè)備驅(qū)動在準備好以后可以編譯到內(nèi)核中(參考實驗四的內(nèi)容),在系統(tǒng)啟動時和內(nèi)核一起啟動,這種方法在嵌入式Linux系統(tǒng)中經(jīng)常被采用。通常情況下設(shè)備驅(qū)動的動態(tài)加載更為普遍(參考實驗七的內(nèi)容),開發(fā)人員不必在調(diào)試過程中頻繁啟動機器就能完成設(shè)備驅(qū)動的開發(fā)工作。設(shè)備驅(qū)動在加載時首先調(diào)用入口函數(shù)init_module(),該函數(shù)完成設(shè)備驅(qū)動的初始化工作,比如寄存器置位、結(jié)構(gòu)體賦值等一系列工作,其中最重要的一個工作就是向內(nèi)核注冊該設(shè)備,對于字符設(shè)備調(diào)用register_chrdev()完成注冊,對于塊設(shè)備需要調(diào)用register_blkdev()完成注冊。注冊成功后,該設(shè)備獲得了系統(tǒng)分配的主設(shè)備號、自定義的次設(shè)備號,并建立起于文件系統(tǒng)的關(guān)聯(lián)。設(shè)備在卸載時需要回收相應(yīng)的資源,令設(shè)備的響應(yīng)寄存器復(fù)位并從系統(tǒng)中注銷該設(shè)備,字符設(shè)備調(diào)用unregister_chrdev()、塊設(shè)備調(diào)用unregister_blkdev()。系統(tǒng)調(diào)用部分則是對設(shè)備的操作過程,比如open、read、write、ioctl等。圖8-1為一個設(shè)備驅(qū)動模塊動態(tài)掛載、卸載和系統(tǒng)調(diào)用的全過程。圖8-1設(shè)備驅(qū)動在內(nèi)核中的掛載、卸載和系統(tǒng)調(diào)用過程用戶空間I 內(nèi)核空間圖8-1設(shè)備驅(qū)動在內(nèi)核中的掛載、卸載和系統(tǒng)調(diào)用過程用戶空間I 內(nèi)核空間1<-模塊1111insmod*Init_module()-1—,廣,4 register_XXX1 系1統(tǒng)/—設(shè)備驅(qū)動調(diào)\r內(nèi)核模塊用rmmodClearup_module()- [ ? unregister_XXX設(shè)備驅(qū)動程序負責將應(yīng)用程序如讀、寫等操作正確無誤的傳遞給相關(guān)的硬件,并使硬件能夠做出正確反應(yīng)的代碼,因此在編寫設(shè)備驅(qū)動程序時,必須要了解相應(yīng)的硬件設(shè)備的寄存器、IO口及內(nèi)存的配置參數(shù)。1、硬件接口電路介紹(1)、LED和八段數(shù)碼顯示接口電路目標板LED和八段數(shù)碼顯示接口電路如圖8-2所示,74HC574為D鎖存器,在時鐘信號CLK作用下,該鎖存器將輸入信號進行鎖存,即xQ=xD(x=1?8)。從圖中可以看出,LED和八段數(shù)碼顯示電路將74HC574的時鐘信號輸入端作為片選信號,其中LED顯示的片選信號為LED_CS4、八段數(shù)碼顯示的片選信號為LED_CS1。在八段數(shù)碼顯示電路中,8位數(shù)據(jù)的高位(D7、D15:即數(shù)碼管的小數(shù)點dp段)用作八段數(shù)碼的公共選通信號,通過控制PNP三極管來控制數(shù)碼管的顯示。[1.2.6.8]BD[0:31]<<^-|\BDO2\ 3\ED24\BD35\ED57\ ,\EI”974HC574LED-CS4VCC5 0VCC_5FB1LBDR191680LSDh受>CLKOEVCC>CLK1190OPENSS8J50L.T1…5R202一VCC[1.2.6.8]BD[0:31]<<^-|\BDO2\ 3\ED24\BD35\ED57\ ,\EI”974HC574LED-CS4VCC5 0VCC_5FB1LBDR191680LSDh受>CLKOEVCC>CLK1190OPENSS8J50L.T1…5R202一VCC5F12QQ一I■SS8J50L.T1JJ22DidHD11□14□151191VCC3.3一R6574Hfti7422OPE雇R2161LED420gdp81A522OPE^D.1UFR216LEIM51iiD.1UFVCC3.3一R65LED420'77D1Q1D2Q2D3Q3D4Q4D5Q5D606D7Q7D8QG>CLKOOCgIHQ顯示電路中的片選信號LED_CSx,由目標板系統(tǒng)的PXA270xCPU的地址信號BA22?BA20通過BA20通過3-8譯碼器LC138產(chǎn)生(如圖8-3所示)。BA20BA21BA22圖8-3片選信號產(chǎn)生電路由圖可知,當BA22、BA21、BA20=101時產(chǎn)生LED顯示電路的片選信號LED_CS4,當BA22、BA21、BA20=010、011、100時分別產(chǎn)生八段數(shù)碼顯示電路的片選信號LED_CS1、LED_CS2、LED_CS3(另外2組八段顯示電路參考系統(tǒng)提供的總電路圖)。(2)、鍵盤接口電路目標平臺提供了陣列鍵盤(如圖8-4所示)和單按鍵鍵盤(如圖8-5所示)兩種鍵盤接口電路,其中陣列鍵盤中行控制信號線KP-MKIN0?2分別由CPU的通用IO口GPIO100?102控制,列控制信號線KP-MKOUT0?5分別由CPU的通用IO口GPIO103?105和GPIO108控制。單按鍵鍵盤的控制信號線KP-DKIN1?2,KP-DKIN5?6分別由CPU的通用IO口GPIO94?95和GPIO98?99控制。[1]KP-DKING[1]KP-DKIN1[1]KP-CKIN2[1]KP-DKIN5VCC_3.3KP-DK1M6KP-DK1M2KP-DK1H5xxKP-DK1H1[1]KP-DKING[1]KP-DKIN1[1]KP-CKIN2[1]KP-DKIN5VCC_3.3KP-DK1M6KP-DK1M2KP-DK1H5xxKP-DK1H1圖8-5單按鍵鍵盤接口、步進電機控制接口步進電機控制電路如圖8-6所示,步進電機的轉(zhuǎn)動方向控制信號和步進輸入信號GP1、GP2分別由CPU的通用IO口GPIO83和GPIO84控制。圖8-6步進電機控制接口電路2、I/O驅(qū)動程序設(shè)備驅(qū)動程序運行在內(nèi)核空間,而應(yīng)用程序則運行在用戶空間,Linux操作系統(tǒng)通過系統(tǒng)調(diào)用和硬件中斷完成從用戶空間到內(nèi)核空間的控制轉(zhuǎn)移,執(zhí)行系統(tǒng)調(diào)用的內(nèi)核代碼在進程的上下文中執(zhí)行,也就是說代表調(diào)用進程操作而且可以訪問進程地址空間的數(shù)據(jù),中斷處理程序相對進程而言是異步的,而且與任何一個進程都無關(guān)。
設(shè)備驅(qū)動模塊的功能就是擴展內(nèi)核的功能,主要完成兩部分任務(wù):一個是系統(tǒng)調(diào)用,另一個是中斷處理。下面分別以八段數(shù)碼顯示驅(qū)動模塊為例介紹如何在一個字符驅(qū)動設(shè)備實現(xiàn)對I/O驅(qū)動程序的編寫方法和過程(源碼實驗文件為XSB_EDR_8SEG..c)。模塊初始化模塊初始化module_init(Emdoor_8Seg_init)函數(shù)中的參數(shù)Emdoor_8Seg_init實際上為八段數(shù)碼顯示驅(qū)動模塊的初始化函數(shù)staticint_initEmdoor_8Seg_init(void),該函數(shù)主要完成將產(chǎn)生數(shù)碼顯示的片選控制信號的BA22?BA20通過void*ioremap(unsignedlongoffset,unsignedlongsize)函數(shù)為I/O內(nèi)存區(qū)域分配虛擬地址,這樣設(shè)備驅(qū)動程序就能訪問I/O內(nèi)存地址,同時在模塊初始化函數(shù)中,register_chrdev()函數(shù)完成字符設(shè)備在內(nèi)核系統(tǒng)中的注冊并建立與文件系統(tǒng)(Emdoor_fops)的關(guān)聯(lián)。staticint__initEmdoor_8Seg_init(void){intret;cs1_address=ioremap(SEG_CS1,32);//distributeI/Omemorymapaddresscs2_address=ioremap(SEG_CS2,4);cs3_address=ioremap(SEG_CS3,4);ret=register_chrdev(61,DEVICE_NAME,&Emdoor_fops);//registerdevicenameif(ret<0){printk(DEVICE_NAME"can'tgetmajornumber\n");returnret;}return0;}其中數(shù)碼片選信號SEG_CS1~3和設(shè)備文件名在程序中采用#define宏定義進行定義。#defineDEVICE_NAME"emdoor_8seg"#defineSEG_CS1#defineSEG_CS2#defineSEG_CS3#defineSEG_CS1#defineSEG_CS2#defineSEG_CS30x102000000x103000000x10400000//A22,A21,A20=011->LED_CS2//A22,A21,A20=100->LED_CS3模塊的卸載模塊的卸載module_exit(Emdoor_8Seg_exit)函數(shù)中參數(shù)Emdoor_8Seg_exit實際上是模塊的從內(nèi)核卸載時所調(diào)用的staticvoid_exitEmdoor_8Seg_exit(void);設(shè)備在卸載時需要回收相應(yīng)的資源,并利用unregister_chrdev(涵數(shù)從內(nèi)核中將設(shè)備注銷。staticvoid__exitEmdoor_8Seg_exit(void){iounmap(cs1_address);//releaseI/Omemorymap,reclaimsystemresourceiounmap(cs2_address);iounmap(cs3_address);unregister_chrdev(61,DEVICE_NAME);//unregisterdevice}設(shè)備文件操作接口定義設(shè)備文件操作接口定義是用戶使用該設(shè)備的關(guān)鍵,合理的定義可簡化應(yīng)用程序設(shè)計,縮短項目的整體開發(fā)周期。八段數(shù)碼顯示驅(qū)動模塊定義了open、write、release、ioctl等四種設(shè)
備文件操作,內(nèi)容如下所示:staticstructfile_operationsEmdoor_fops=(Emdoor_8Seg_open,Emdoor_8Seg_write,Emdoor_8Seg_release,Emdoor_8Seg_open,Emdoor_8Seg_write,Emdoor_8Seg_release,Emdoor_8Seg_ioctl,//openoperationfunction//writeoperationfunction//releaseoperationfunction//IOcontroloperationfunctionwrite:release:ioctl:owner:THIS_MODULE,};設(shè)備文件操作根據(jù)設(shè)備文件操作接口定義,每一個設(shè)備文件操作對應(yīng)一個系統(tǒng)調(diào)用,在用戶程序中利用系統(tǒng)調(diào)用對設(shè)備文件進行諸如open/write等操作時,系統(tǒng)調(diào)用通過設(shè)備文件的主設(shè)備號找到相應(yīng)的設(shè)備驅(qū)動程序,然后讀取設(shè)備文件操作接口定義的相應(yīng)的函數(shù)指針,接著把控制權(quán)交給該操作函數(shù)。在八段數(shù)碼顯示驅(qū)動模塊定義了open、write、release>ioctl等四種設(shè)備文件操作。.打開設(shè)備操作staticintEmdoor_8Seg_open(structinode*inode,structfile*filp){structseg*seg_7;seg_7=kmalloc(sizeof(structseg),GFP_KERNEL);//distributememoryinkernelspaceseg_7->negative=LED_MODULE;filp->private_data=seg_7;//privatedatapointerpointtoseg_7MOD_INC_USE_COUNT;//currentmodulecounteradd1return0;}.寫設(shè)備操作staticssize_tEmdoor_8Seg_write(structfile*file,constchar*buffer,size_tcount,loff_t*ppos){inti;structseg*seg_7=file->private_data;charled_forall[6];if(count!=6)//LEDamount{printk(KERN_EMERG"thecountofinputisnotsix!!");return0;}copy_from_user(led_forall,buffer,6);//copydatafromuserspacetokernelspacefor(i=1;i<=6;i++){value_seting(seg_7,i,LED[i-1]);}Updateled(seg_7);//lightentheLEDreturn6;}.I/O控制操作unsignedlongarg)staticintEmdoor_8Seg_ioctl(structinode*ip,structfile*fp,unsignedintcmd,unsignedlongarg)charval=0x00;structseg*seg_7=fp->private_data;if(!arg)return-EINVAL;if(copy_from_user(&val,(int*)arg,sizeof(char)))return-EFAULT;switch(cmd){//controltheLEDcommandwordcase1:value_seting(seg_7,1,val);//controlthefirst8LEDbreak;case2:value_seting(seg_7,2,val);//controlthesecond8LEDbreak;case3:value_seting(seg_7,3,val);//controlthethird8LEDbreak;case4:value_seting(seg_7,4,val);break;case5:value_seting(seg_7,5,val);break;case6:value_seting(seg_7,6,val);//controlthesixth8LEDbreak;case0: //clearallLEDseg_7->negative=LED_MODULE;break;default:printk(KERN_EMERG"ioctlparameterinputerror,pleaseinputnumber0-6");break;}Updateled(seg_7);//lightenLEDreturn0;}④.釋放設(shè)備操作staticintEmdoor_8Seg_release(structinode*inode,structfile*filp){kfree(filp->private_data);//releasememorywhichdistributedbykmallocMOD_DEC_USE_COUNT;//currentmodulecountersubtract1return0;}5)內(nèi)部自定義函數(shù)在八段數(shù)碼顯示驅(qū)動程序中,自定義了一個點亮數(shù)碼管的函數(shù) Updateled(structseg*seg_7)staticvoidUpdateled(structseg*seg_7){unsignedshortbuff=0x00;buff=seg_7->led1_val;buff=buff|(seg_7->led2_val<<8);writew(buff,cs1_address);//write16bitsdataintoI/Omemorybuff=0x00;buff=seg_7->led3_val;buff=buff|(seg_7->led4_val<<8);writew(buff,cs2_address);buff=0x00;buff=seg_7->led5_val;buff=buff|(seg_7->led6_val<<8);writew(buff,cs3_address);return;}和設(shè)置數(shù)碼管所顯示數(shù)值的函數(shù)value_seting(structseg*seg_7,charposition,charvalue)。voidvalue_seting(structseg*seg_7,charposition,charvalue){if(seg_7->negative==0)value=~value&~(0x1<<7);elsevalue=(0x1<<7)|value;if(position==1)seg_7->led1_val=value;elseif(position==2)seg_7->led2_val=value;elseif(position==3)seg_7->led3_val=value;elseif(position==4)seg_7->led4_val=value;elseif(position==5)seg_7->led5_val=value;elseif(position==6)seg_7->led6_val=value;}3、驅(qū)動模塊的編譯在編譯驅(qū)動模塊程序時,應(yīng)當編寫適合于特定目標平臺的Makefile編譯文件(具體參考實驗七和實驗二的內(nèi)容),下面為八段數(shù)碼顯示驅(qū)動模塊的Makefile內(nèi)容,,必須注意的是交叉編譯工具變量CC和模塊將要使用和運行的內(nèi)核源碼的include變量INCLUDEDIR兩個變量的設(shè)定必須根據(jù)編譯平臺的實際路徑進行修改。CC=/opt/xscalevl/bin/arm-linux-gccINCLUDEDIR=/XSBase270/2.4/Kernel/xsbase/linux-2.4.21-emdoor_EDR/includeCFLAGS=-D__KERNEL__-DMODULE-Wall-O2CFLAGS+=-I..-I$(INCLUDEDIR)#8SEGTARGET_8SEG=XSB_EDR_8SEGOBJ_8SEG=$(TARGET_8SEG).oSOURCE_8SEG=$(TARGET_8SEG).call:$(OBJ_8SEG)$(OBJ_8SEG):$(SOURCE_8SEG)$(CC)$(CFLAGS)-c-o$(OBJ_8SEG)$(SOURCE_8SEG)clean:rm-rf$(OBJ_8SEG)4、驅(qū)動模塊的加載將編譯好的驅(qū)動模塊下載到目標上,進入目標板系統(tǒng)后,利用mknod命令在/dev目錄下建立該設(shè)備的節(jié)點。然后利用insmod命令裝載驅(qū)動模塊,最后在目標平臺中運行驅(qū)動模塊的測試程序driverTest(測試程序的下載過程參考實驗六的內(nèi)
溫馨提示
- 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)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年華東師大版九年級生物上冊月考試卷含答案
- 2025年北師大新版選修4地理下冊月考試卷含答案
- 二零二五版拌合料行業(yè)技術(shù)交流與合作開發(fā)合同4篇
- 二零二五年度陶瓷面磚研發(fā)及采購合同4篇
- 二零二五版美團外賣外賣配送高峰期應(yīng)急預(yù)案合同4篇
- 2025年新型共享辦公空間租賃合同3篇
- 掛鉤生產(chǎn)單位的合同(2篇)
- 2025年度木門安裝工程招標合同4篇
- 2025年度門窗安裝工程設(shè)計與施工一體化合同4篇
- 2025年度民間借貸融資租賃與資產(chǎn)證券化合同4篇
- 射頻在疼痛治療中的應(yīng)用
- 和平精英電競賽事
- 四年級數(shù)學豎式計算100道文檔
- “新零售”模式下生鮮電商的營銷策略研究-以盒馬鮮生為例
- 項痹病辨證施護
- 職業(yè)安全健康工作總結(jié)(2篇)
- 懷化市數(shù)字經(jīng)濟產(chǎn)業(yè)發(fā)展概況及未來投資可行性研究報告
- 07FD02 防空地下室電氣設(shè)備安裝
- 教師高中化學大單元教學培訓(xùn)心得體會
- 彈簧分離問題經(jīng)典題目
- 部編版高中歷史中外歷史綱要(下)世界史導(dǎo)言課課件
評論
0/150
提交評論