國嵌實(shí)驗(yàn)手冊(cè)2011-課程5內(nèi)核驅(qū)動(dòng)深入_第1頁
國嵌實(shí)驗(yàn)手冊(cè)2011-課程5內(nèi)核驅(qū)動(dòng)深入_第2頁
國嵌實(shí)驗(yàn)手冊(cè)2011-課程5內(nèi)核驅(qū)動(dòng)深入_第3頁
國嵌實(shí)驗(yàn)手冊(cè)2011-課程5內(nèi)核驅(qū)動(dòng)深入_第4頁
國嵌實(shí)驗(yàn)手冊(cè)2011-課程5內(nèi)核驅(qū)動(dòng)深入_第5頁
已閱讀5頁,還剩125頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

嵌入式Linux內(nèi)核驅(qū)動(dòng)深入實(shí)驗(yàn)手國嵌編著嵌入式LINUX培訓(xùn)該資料歸屬國(簡稱“國嵌”)所有,并保留。非經(jīng)國嵌同意(形1.1:kobjectSysfs文件系統(tǒng)工作原理,kobject工作原理 測試創(chuàng)建的文件是否可讀#mkdir/home/guoqian/5-4-1#cd/home/guoqian/5-4-1說明:上圖kobject.ko為編譯生成的內(nèi)核模塊#cpkobject.ko在加載內(nèi)核模塊前先查看當(dāng)前#ls#insmodkobject.ko在加載模塊后查看#ls #ls/sys/kobject_test/ 首先測試是否可#cat再測試是否可#echo1234>/ 再次查看#ls 件系統(tǒng)相似,相比于proc文件系統(tǒng),使用sysfs導(dǎo)出內(nèi)核數(shù)據(jù)的方1.2:busBus設(shè)備模型工作原理編寫內(nèi)核模塊,向系統(tǒng)中添加一條總線#mkdir/home/guoqian/5-4-2#cd/home/guoqian/5-4-2說明:上圖bus.ko為編譯生成的內(nèi)核模塊#cpbus.ko在加載內(nèi)核模塊前先查看當(dāng)前#ls#ls#insmodbus.ko查看#ls#ls說明:從上圖可以發(fā)現(xiàn),屬性文#ls9.總線屬性文件信#cat說明:屬性文件,函數(shù)show_bus_version被調(diào)用打印輸出相應(yīng)信#rmmodbus再次查看#ls#ls說明:從上圖可以看出總線/sys/bus/my_bus,屬性文/sys/bus/my_bus/version,總線設(shè)/sys/devices/my_bus0被刪除為:pci,usb,i2c,i2s,tform等驅(qū)動(dòng)。本實(shí)驗(yàn)需要大家掌握最本的總線操作,如:總線創(chuàng)建與刪除、總線屬性文件的讀寫等1.3:deviceDevice設(shè)備模型工作原理基于實(shí)驗(yàn)5.4.2實(shí)現(xiàn)的總線,在該總線上添加一個(gè)設(shè)備#mkdir/home/guoqian/5-4-3#cd/home/guoqian/5-4-3說明:上圖device.ko為編譯生成的內(nèi)核模塊#cpdevice.ko在加載內(nèi)核模塊前先查看當(dāng)前#ls#ls#insmod注:先加載實(shí)驗(yàn)5.4.2總線模#insmod注:然后在該總線上添加一個(gè)設(shè)查看#ls/sys/bus/my_bus/devices#ls/sys/devices/my_bus0/#ls/sys/devices/my_bus0/my_dev、創(chuàng)建設(shè)備屬性文/sys/devices/my_bus0/my_dev/dev#cat#rmmoddevice說明:卸載內(nèi)核模塊時(shí),模塊卸載函數(shù)完成設(shè)備的刪除作再次查看#ls/sys/bus/my_bus/devices#ls/sys/devices/my_bus0說明:從上圖可以看出設(shè)備my_dev從總/sys/bus/my_bus上被成功的刪除1.4:driverDriver設(shè)備模型工作原理基于實(shí)驗(yàn)1.2和實(shí)驗(yàn)1.3,在該總線上一個(gè)驅(qū)動(dòng)程序#mkdir/home/guoqian/5-4-4#cd/home/guoqian/5-4-4說明:上圖driver.ko為編譯生成的內(nèi)核模塊#cpdriver.ko在加載內(nèi)核模塊前先查看當(dāng)前#ls#ls#insmod注:加載總#insmod注:在總線上添加設(shè)#insmod注:為總線上設(shè)備添加驅(qū)調(diào)用,打印輸出語句”Driverfounddevicewhichmydrivercanhandle!”;除了驅(qū)動(dòng),函數(shù)my_driver_init/sys/bus/my_bus/drivers/my_dev/drv查看#ls#ls說明:在加載驅(qū)動(dòng)內(nèi)核模塊時(shí),函數(shù)在總/sys/bus/my_bus上添加設(shè)備驅(qū)/sys/bus/my_bus/drivers/my_dev、創(chuàng)建驅(qū)動(dòng)屬性文/sys/bus/my_bus/drivers/my_dev/drv#cat#rmmoddriver說明:卸載內(nèi)核模塊時(shí),模塊卸載函數(shù)完成驅(qū)動(dòng)的刪除作再次查看#ls實(shí)驗(yàn)1.5:tform驅(qū)動(dòng)模掌握tform驅(qū)動(dòng)模型工作原理使用tform驅(qū)動(dòng)模型改寫按鍵驅(qū)動(dòng)程設(shè)計(jì)應(yīng)用程序,測試tform驅(qū)動(dòng)是否可#mkdir/home/guoqian/5-4-5#cd/home/guoqian/5-4-5#cd/home/guoqian/4-3-1/linux-2.6.29 configARCH=armPILE=arm-注:按鍵驅(qū)動(dòng)位于Devicedrivers-->Characterdevices<>ButtonsdriverforFriendlyARMMini2440/QQ2440developmentboards#make根據(jù)實(shí)驗(yàn)要求編寫內(nèi)核模塊t_device部分t_device.c(見實(shí)驗(yàn)代碼光盤5-4-5);編寫t_driver編寫Makefile(見實(shí)驗(yàn)代碼光盤5-4-說明:上圖t_device.ko和t_buttons.ko為編譯生成 t_buttons.ko使用重新編譯后的內(nèi)核起根文件系首先加載t_device內(nèi)核模塊#insmodt_device.ko說明:在加載t_device內(nèi)核模塊時(shí),模塊初始化函tform_init被調(diào)用,該函數(shù)完成t_device的定義和注加載t_buttons內(nèi)核模塊#insmodt_buttons.ko說明:在加載t_buttons內(nèi)核模塊時(shí),模塊初始化函數(shù)buttons_init被調(diào)用,該函數(shù)完成t_driver的定義和操作。在t_driver時(shí)內(nèi)核會(huì)在相應(yīng)的tform總線動(dòng)中函數(shù)mini2440_buttons_probe(t_buttons.c)被調(diào)由于t_driver中采用混雜型字符設(shè)備驅(qū)動(dòng)方式來設(shè)#ls-l/dev/*|grep說明:主設(shè)備號(hào):10,內(nèi)核分配的次設(shè)備號(hào):57#arm-linux-gcc–staticapp-button.c–oapp-button#cpapp-button/nfsroot/rootfs/tmp運(yùn)試程運(yùn)行應(yīng)用程序,并按鍵測試功能是否實(shí)現(xiàn)#./app-是多次,這是因?yàn)榘存I沒有去抖動(dòng)??刹捎醚訒r(shí)的方式抖動(dòng)#rmmodt_buttons.ko#rmmodt_device.ko總結(jié):tform是一種虛擬的總線,tform驅(qū)動(dòng)與傳統(tǒng)的設(shè)備驅(qū)動(dòng)模型相比,優(yōu)勢(shì)在于tform機(jī)制將設(shè)備本身的資源2.1:DM9000掌握網(wǎng)卡驅(qū)動(dòng)設(shè)計(jì)規(guī)范分析DM9000網(wǎng)卡驅(qū)動(dòng)程序,編寫分析文檔DM9000網(wǎng)卡驅(qū)動(dòng)位于內(nèi)核源代碼/*模塊加載函數(shù)staticint init{printk(KERN_INFO"%sEthernetDriver,V%s\n",CARDNAME,/*平臺(tái)驅(qū)動(dòng)return}/*平臺(tái)驅(qū)動(dòng)定義staticstructtform_driverdm9000_driver=.driver= =.owner= = = .suspend= =問題:probe調(diào)用時(shí)機(jī)tform.c)冊(cè)的驅(qū)動(dòng)能驅(qū)動(dòng)該設(shè)備,則probe函數(shù)被調(diào)用。staticint dm9000_probe(structtform_device{ structboard_info*db;/* structure*/structnet_deviceconstunsignedchar*mac_src;intret=0;intiosize;inti;u32/*Initnetworkdevice/*分配ndev=alloc_etherdev(sizeof(structboard_info));if(!ndev){dev_err(&pdev->dev,"couldnotallocatedevice.\n");return-ENOMEM;}SET_NETDEV_DEV(ndev,&pdev->dev);/*setupboardinfostructure*/db=netdev_priv(ndev);memset(db,0,sizeof(*db));db->dev=&pdev->dev;db->ndev=ndev;/*獲取tform設(shè)備資源 IORESOURCE_MEM,0); IORESOURCE_MEM,1); IORESOURCE_IRQ,0);if(db->addr_res==NULL||db->data_res==NULL||db->irq_res==NULL){dev_err(db->dev,"insufficientresources\n");ret=-ENOENT;goto}iosize=res_size(db-/*I/O內(nèi)存申請(qǐng)db->addr_req=request_mem_region(db->addr_res->start,if(db->addr_req==NULL)dev_err(db->dev,"cannotclaimaddressregarea\n");ret=-EIO;goto}/*映射db->io_addr=ioremap(db->addr_res->start,if(db->io_addr==NULL)dev_err(db->dev,"failedtoioremapaddressreg\n");ret=-EINVAL;goto}iosize=res_size(db-db->data_req=request_mem_region(db->data_res->start,if(db->data_req==NULL)dev_err(db->dev,"cannotclaimdataregarea\n");ret=-EIO;goto}db->io_data=ioremap(db->data_res->start,iosize);if(db->io_data==NULL){dev_err(db->dev,"failedtoioremapdatareg\n");ret=-EINVAL;goto}/*fillinparametersfornet-devstructurendev->base_addr=(unsignedlong)db->io_addr;ndev->irq=db->irq_res->start;/*ensureatleastwehaveadefaultsetofIOroutines指針*/dm9000_set_io(db,/*checktoseeifanythingisbeingover-ridden/*根據(jù)tform的定義(16bit),再次初始化讀寫數(shù)據(jù)幀if(pdata!=NULL)/*checktoseeifthedriverwantstoover-ride*defaultIOwidthif(pdata->flags&DM9000_TF_8BITONLY)dm9000_set_io(db,1);if(pdata->flags&DM9000_TF_16BITONLY)dm9000_set_io(db,2);if(pdata->flags&DM9000_TF_32BITONLY)dm9000_set_io(db,4);/*checktoseeifthereareanyIO*over-ridesif(pdata->inblk!=db->inblk=pdata-if(pdata->outblk!=db->outblk=pdata-if(pdata->dumpblk!=db->dumpblk=pdata-db->flags=pdata-}#ifdefCONFIG_DM9000_/*復(fù)位/*ID號(hào)并判斷是否為/*trymultipletimes,DM9000sometimesgetsthereadwrong*/for(i=0;i<8;i++) =ior(db,id_val|=(u32)ior(db,DM9000_VIDH)<<8;id_val|=(u32)ior(db,DM9000_PIDL)<<16;id_val|=(u32)ior(db,DM9000_PIDH)<<if(id_val==DM9000_ID)dev_err(db->dev,"readwrongid0x%08x\n",}if(id_val!=DM9000_ID)dev_err(db->dev,"wrongid:0x%08x\n",id_val);ret=-ENODEV;goto}/*IdentifywhattypeofDM9000weareworkingon/*DM9000_CHIPR=0x2c寄存器,判斷網(wǎng)卡類型id_val=ior(db,dev_dbg(db->dev,"dm9000revision0x%02x\n",switch(id_val)casedb->type=TYPE_DM9000A;casedb->type=TYPE_DM9000B; DM9000E\n",id_val);db->type=}/*fromthispointweassumethatwehavefounda/*driversystemfunction/*初始化以太網(wǎng)ndev的部分成員/*設(shè)置ndev的基本操作 = =&dm9000_start_xmit; =&dm9000_timeout;ndev->watchdog_timeo=msecs_to_jiffies(watchdog); =&dm9000_stop;ndev->set_multicast_list=&dm9000_hash_table; =&dm9000_ethtool_ops; =&dm9000_ioctl;#ifdefndev->poll_controller=&dm9000_poll_controller; =NETIF_MSG_LINK; =0x1f;db->mii.reg_num_mask=0x1f; =0; =0; =ndev; =dm9000_phy_read; =/*設(shè)置MAC地址的操作#if mac_src="friendly-arm";ndev->dev_addr[0]=0x08;ndev->dev_addr[1]=0x90;ndev->dev_addr[2]=0x90;ndev->dev_addr[3]=0x90;ndev->dev_addr[4]=0x90;ndev->dev_addr[5]=mac_src=/*tryreadingthenodeaddressfromtheattachedfor(i=0;i<6;i+=dm9000_read_eeprom(db,i/2,ndev- NULL){mac_src="tform}if(!is_valid_ether_addr(ndev->dev_addr))/*tryreadingfrommacmac_src="chip";for(i=0;i<6;i++)ndev->dev_addr[i]=ior(db,}if(!is_valid_ether_addr(ndev-Please"setusingifconfig\n",ndev-/*網(wǎng)卡驅(qū)動(dòng)ret=if(ret==printk(KERN_INFO"%s:dm9000%cat%p,%pIRQ%dMAC:%pM(%s)\n",ndev->name,dm9000_type_to_char(db->type),db->io_addr,db->io_data,ndev->irq,returndev_err(db->dev,"notfound(%d).\n",return}問題:open函數(shù)調(diào)用時(shí)機(jī)在網(wǎng)卡open函數(shù)中應(yīng)該完成以下操作中斷;設(shè)置寄存器,啟動(dòng)設(shè)備;啟動(dòng)發(fā)送隊(duì)staticintdm9000_open(structnet_device{board_info_t*db= ifdev_dbg(db->dev,"enabling%s\n",dev-/*IfthereisnoIRQtypespecified,defaulttosomething*maywork,andltheuserthatthisisaproblemif(irqflags==dev_warn(db->dev,"WARNING:noIRQresourceflags/*中斷irqflags|= dev->name,dev))return-/*InitializeDM9000board/*復(fù)位DM9000,初始化的寄存器*//*Initdrivervariable*/ t=0;mii_check_media(&db->mii,netif_msg_link(db),/*開啟網(wǎng)絡(luò)接口發(fā)送數(shù)據(jù)隊(duì)列return}問題:數(shù)據(jù)發(fā)送函數(shù)調(diào)用時(shí)機(jī)答:當(dāng)網(wǎng)卡有數(shù)據(jù)要發(fā)送的時(shí)候,該函數(shù)被調(diào)用 net_device*dev){unsignedlongboard_info_t*db=netdev_priv(dev);dm9000_dbg(db,3,"%s:\n", if(db-> t>1)return1;/*MovedatatoDM9000TXRAM*/writeb(DM9000_MWCMD,db->io_addr);/*把skb的數(shù)據(jù)拷貝到DM9000的SRAM中*/(db->outblk)(db->io_data,skb->data,skb->len);dev->stats.tx_bytes+=skb->len; /*TXcontrol:Firstpacketimmedia ysend,secondpacketqueue*/if(db- t==1)/*將要發(fā)送數(shù)據(jù)包的長度寫入寄存器/*SetTXlengthtoDM9000*/iow(db,DM9000_TXPLL,skb->len);iow(db,DM9000_TXPLH,skb->len>>/*置0x02寄存器bit0位為1,發(fā)送數(shù)據(jù)/*IssueTXpollingcommandiow(db,DM9000_TCR,TCR_TXREQ);/* complete*/dev->trans_start=jiffies;/*savethetimestamp}else/*Secondpacketdb->queue_pkt_len=skb->len;}spin_unlock_irqrestore(&db->lock, thisSKB*/return}問題:網(wǎng)卡有幾種類型的中斷staticirqreturn_tdm9000_interrupt(intirq,void{structnet_device*dev=dev_id;board_info_t*db=netdev_priv(dev);intint_status;unsignedlongu8dm9000_dbg(db,3,"entering%s\n", /*Arealinterruptcoming/*holdersofdb->lockmustalwaysblockIRQs*/spin_lock_irqsave(&db->lock,flags);/*Savepreviousregisteraddress*/reg_save=readb(db->io_addr);/*Disableallinterrupts/*關(guān)閉所有中斷iow(db,DM9000_IMR,/*中斷狀態(tài)寄存器,清中斷/*GotDM9000interruptstatusint_status=ior(db,DM9000_ISR); /*GotISR*/iow(db,DM9000_ISR,int_status);/*ClearISRstatus*/if /*Receivedthecomingpacket/*文到達(dá)中斷if(int_status&ISR_PRS)/*TrnasmitInterruptcheck/*報(bào)文發(fā)送完成中斷if(int_status&ISR_PTS)if(db->type!=TYPE_DM9000E)if(int_status&ISR_LNKCHNG)/*firealink-changerequest*/schedule_delayed_work(&db->phy_poll,1);}}/*重新使能中斷/*Re-enableinterruptmask*/iow(db,DM9000_IMR,db->imr_all);/*Restorepreviousregisteraddress*/writeb(reg_save,db->io_addr);spin_unlock_irqrestore(&db->lock,return}中斷狀態(tài)寄存器判斷出是否是接收中斷,接著使用函數(shù)dm9000_rx處理接收到的數(shù)據(jù)。staticdm9000_rx(structnet_device{board_info_t*db=netdev_priv(dev);structdm9000_rxhdrrxhdr;structsk_buff*skb;u8rxbyte,*rdptr;boolGoodPacket;intRxLen;/*Checkpacketreadyornot*/do{ior(db, /*Dummyread/*Getmostupdateddata*/rxbyte=readb(db->io_data);/*Statuscheck:thisbytemustbe0or1*/if(rxbyte>DM9000_PKT_RDY){ request}

iow(db,DM9000_RCR,0x00);/*StopDevice*/iow(db,DM9000_ISR,IMR_PAR);/* if(rxbyte!=DM9000_PKT_RDY)/*Apacketreadynow &Getstatus/length*/GoodPacket=true;writeb(DM9000_MRCMD,db-(db->inblk)(db->io_data,&rxhdr,sizeof(rxhdr));RxLen=le16_to_cpu(rxhdr.RxLen);if length%04x\n",/*PacketStatuscheck*/if(RxLen<0x40){GoodPacket=ifdev_dbg(db->dev,"RX:BadPacket}if(RxLen>DM9000_PKT_MAX)dev_dbg(db->dev,"RST:RXLen:%x\n",}/*rxhdr.RxStatusisidenticaltoRSRregister.if(rxhdr.RxStatus&(RSR_FOE|RSR_CE|RSR_AE|RSR_PLE|RSR_RWTO|RSR_LCS|RSR_RF))GoodPacket=if(rxhdr.RxStatus&RSR_FOE){if(netif_msg_rx_err(db))dev_dbg(db->dev,"fifoerror\n");}if(rxhdr.RxStatus&RSR_CE){if(netif_msg_rx_err(db))dev_dbg(db->dev,"crcerror\n");}if(rxhdr.RxStatus&RSR_RF){if(netif_msg_rx_err(db))dev_dbg(db->dev,"lengtherror\n");}}/*MovedatafromDM9000/*分配if&&((skb=dev_alloc_skb(RxLen+4))!=NULL)){skb_reserve(skb,2);rdptr=(u8*)skb_put(skb,RxLen-/*ReadreceivedpacketfromRXSRAM/*從硬件中數(shù)據(jù)到(db->inblk)(db->io_data,rdptr,RxLen);dev->stats.rx_bytes+=RxLen;/*Passtoupperlayerskb->protocol=eth_type_trans(skb,/*調(diào)用netif_rx將數(shù)據(jù)交給協(xié)議棧}else/*needtodumpthepacket'sdata(db->dumpblk)(db->io_data,}}while(rxbyte==}2.2掌握網(wǎng)卡驅(qū)動(dòng)設(shè)計(jì)規(guī)實(shí)現(xiàn)回環(huán)網(wǎng)卡驅(qū)動(dòng)程#mkdir/home/guoqian/5-5-2#cd/home/guoqian/5-5-2說明:上圖loopback.ko為編譯生成的內(nèi)核模塊#cploopback.ko#insmodloopback.ko由于網(wǎng)絡(luò)接口驅(qū)動(dòng)本身特點(diǎn),在 下沒有設(shè)節(jié)點(diǎn),而是使用socket系統(tǒng)調(diào)用內(nèi)核子系統(tǒng)。故 #ifconfiglotest#rmmodloopback說明:卸載內(nèi)核模塊時(shí),模塊卸載函數(shù)被調(diào)用,函數(shù)完成網(wǎng)絡(luò)接口驅(qū)動(dòng)注銷操作2.3:input掌握input子系統(tǒng)驅(qū)動(dòng)模型工作原理以input驅(qū)動(dòng)模式改寫按鍵驅(qū)動(dòng)程設(shè)計(jì)應(yīng)用程序,測試驅(qū)#mkdir/home/guoqian/5-5-3#cd/home/guoqian/5-5-3由于內(nèi)核本身自帶mini2440按鍵驅(qū)動(dòng),為了不跟本驗(yàn),內(nèi)核配置時(shí)去掉對(duì)mini2440按鍵驅(qū)動(dòng)的支持#cd/home/guoqian/4-3-1/linux-2.6.29 configARCH=armPILE=arm-注:按鍵驅(qū)動(dòng)位于Devicedrivers-->Characterdevices<>ButtonsdriverforFriendlyARMMini2440/QQ2440developmentboards#make注:按鍵驅(qū)動(dòng)中斷觸發(fā)方式采沿觸發(fā)說明:上圖input_button.ko為編譯生成的內(nèi)核模塊#cpinput_button.ko使用重新編譯后的內(nèi)核起根文件系#insmodinput_button.ko說明:加載內(nèi)核模塊時(shí),模塊初始化函數(shù)dev_init被#cat說明:主設(shè)備號(hào):13,次設(shè)備號(hào):64輸入子系統(tǒng)設(shè)備文件會(huì)被自動(dòng)創(chuàng)#ls-l/dev/*|grep#arm-linux-gcc-staticapp-input.c-oapp-input#cpapp-input/nfsroot/rootfs/tmp運(yùn)試程#./app-說明:type:1,code:2,value:1-->表示2號(hào)鍵被按下#rmmodinput_button總結(jié):iux系統(tǒng)提供了nut子系統(tǒng),按鍵、觸摸屏、鼠標(biāo)等輸入型設(shè)備都可以利用nut接口函數(shù)來實(shí)現(xiàn)設(shè)備驅(qū)動(dòng)。這里留一個(gè)思考題,本實(shí)驗(yàn)中斷觸發(fā)方式采沿觸發(fā),能否將中斷觸發(fā)方式改為單沿觸發(fā)?2.4:s3c2440掌握觸摸屏驅(qū)動(dòng)工作流程,回顧input子系統(tǒng)驅(qū)動(dòng)模型分析s3c2440觸摸屏驅(qū)動(dòng)程軟件:linux-2.6.29內(nèi)核源代模塊加載函數(shù)主要完成以下工作INT_TC,INT_ADC中斷staticint init{structinput_dev/*獲取時(shí)鐘,觸摸屏是掛載在APBBUS上的設(shè)備,需adc_clock=clk_get(NULL,if(!adc_clock)printk(KERN_ERR"failedtogetadcclocksource\n");return-ENOENT;}/*I/O內(nèi)存是不能直接進(jìn)行的,必須對(duì)其進(jìn)行映射if(base_addr==NULL){printk(KERN_ERR"Failedtoremapregisterblock\n");return-ENOMEM;}/*ConfigureGPIOs*/s3c2410_ts_connect*GPIO設(shè)置*//*使能預(yù)分頻和設(shè)置分頻系數(shù)iowrite32(S3C2410_ADCCON_PRSCEN|/*設(shè)置ADC延時(shí),在等待中斷模式下表示產(chǎn)生的間隔時(shí)間,ADC轉(zhuǎn)換周期等待定時(shí)器 /*ADCTSC0xd3將觸摸屏置為等待中斷模式,等待iowrite32(WAIT4INT(0),/*以下配置2.6內(nèi)核劃分出來的輸入設(shè)備/*Initialiseinputstuffinput_dev=if(!input_dev)printk(KERN_ERR"Unabletoallocatetheinputdevice!!\n");return-}dev=dev->evbit[0]=BIT(EV_SYN)|BIT(EV_KEY)|dev->keybit[BITS_TO_LONGS(BTN_TOUCH)]/*設(shè)置絕對(duì)坐標(biāo)x的最小最大值(0-0x3FF)input_set_abs_params(dev,ABS_X,0,0x3FF,0,/*設(shè)置絕對(duì)坐標(biāo)y的最小最大值(0-0x3FF)input_set_abs_params(dev,ABS_Y,0,0x3FF,0,input_set_abs_params(dev,ABS_PRESSURE,0,1,0,dev->name=s3c2410ts_name;dev->id.bustype=BUS_RS232;dev->id.vendor=0xDEAD;dev->duct=dev->id.version=/*INT_TC,INT_ADC中斷,問題:兩種中斷的產(chǎn)生/*Getirqsif(request_irq(IRQ_ADC,stylus_action,"s3c2410_action",dev))printk(KERN_ERR"s3c2410_ts.c:CouldnotallocatetsIRQ_ADC!\n");return-EIO;}if(request_irq(IRQ_TC,stylus_updown,"s3c2410_action",dev))printk(KERN_ERR"s3c2410_ts.c:CouldnotallocatetsIRQ_TC!\n");return-EIO;}printk(KERN_INFO"%ssuccessfullyloaded\n",/*Allwentok,soregistertotheinputsystem/*輸入設(shè)備return}staticirqreturn_tstylus_updown(intirq,void{unsignedlongdata0;unsignedlongdata1;intupdown;了這個(gè)鎖,才能進(jìn)入到啟動(dòng)ADC代碼部分,注意盡管中信號(hào)量因?yàn)樾菝卟贿m合使用在ISR中,down_trylock是一個(gè)例外,它不會(huì)休眠if(down_trylock(&ADC_LOCK)==0){OwnADC=1;data0=ioread32(base_addr+S3C2410_ADCDAT0);data1=updown=(!(data0&S3C2410_ADCDAT0_UPDOWN))&&(!(data1&S3C2410_ADCDAT0_UPDOWN));updown=1 updown=0 if(updown)}elseOwnADC=0;}}return}接下來應(yīng)分析函數(shù)touch_timer_fire函數(shù)staticvoidtouch_timer_fire(unsignedlongdata){unsignedlongdata0;unsignedlongdata1;intupdown;data0=ioread32(base_addr+S3C2410_ADCDAT0);data1=updown=(!(data0&S3C2410_ADCDAT0_UPDOWN))&&(!(data1&S3C2410_ADCDAT0_UPDOWN));if(updown)/*轉(zhuǎn)換四次后進(jìn)行匯報(bào)if(count!=0){longtmp;tmp=xp;xp=yp;yp=tmp;/*求平均值xp>>=yp>>=input_report_abs(devABS_Xxp);input_report_abs(devABS_Y/*報(bào)告按鍵,鍵值為1(代表觸摸屏對(duì)應(yīng)的被按下input_report_key(dev,BTN_TOUCH,/*報(bào)告觸摸屏的狀態(tài),1表明觸摸屏被按下input_report_abs(dev,ABS_PRESSURE,/*同步}

xp=yp=count=完畢

AUTOPST,}elsecount=于等待觸摸的階段*/放)*/input_report_key(dev,BTN_TOUCH,/*報(bào)告觸摸屏的狀態(tài),0表明觸摸屏未被按下input_report_abs(dev,ABS_PRESSURE,/*同步/*設(shè)置觸摸屏為等待中斷模式,等待觸摸筆按下if(OwnADC){OwnADC=0;}}}制器的處理模式為x/y位置自動(dòng)轉(zhuǎn)換模式,開啟ADCINT_ADCstaticirqreturn_tstylus_action(intirq,void{unsignedlongdata0;unsignedlongif(OwnADC)data0=ioread32(base_addr+S3C2410_ADCDAT0);data1=xp+=data0&S3C2410_ADCDAT0_XPDATA_MASK;yp+=data1&/*如果小于四次重新啟動(dòng)ADC轉(zhuǎn)換if(count<(1<<2))|AUTOPST,iowrite32(ioread32(base_addr+S3C2410_ADCCON)|}else/*如果超過四次,啟動(dòng)1個(gè)時(shí)間滴答的定時(shí)器,停止mod_timer(&touch_timer,jiffies+1);}}return}INT_ADC中斷處理函數(shù)主要完成記錄四次ADC轉(zhuǎn)換完代碼if(updown)/*轉(zhuǎn)換四次后進(jìn)行匯報(bào)if(count!=0){longtmp;tmp=xp;xp=yp;yp=tmp;/*求平均值xp>>=yp>>=input_report_abs(devABS_Xxp);input_report_abs(devABS_Y/*報(bào)告按鍵,鍵值為1(代表觸摸屏對(duì)應(yīng)的被按下input_report_key(dev,BTN_TOUCH,/*報(bào)告觸摸屏的狀態(tài),1表明觸摸屏被按下input_report_abs(dev,ABS_PRESSURE,/*同步}

xp=yp=count=AUTOPST,}代碼staticstructtimer_listtouch_timer=TIMER_INITIALIZER(touch_timer_fire,0,0);表明定時(shí)器處理函數(shù)為touch_timer_fire代碼mod_timer(&touch_timer,表明定時(shí)器超時(shí)時(shí)間為10msupdownISR,如果能獲取ADC_LOCK則調(diào)用后,啟動(dòng)1個(gè)時(shí)間滴答的定時(shí)器,停止ADC,也就是說在這樣可以防止屏幕抖動(dòng)3.1:RTL-8139PCIRTC-8139pci網(wǎng)卡,既是一個(gè)pci總線驅(qū)動(dòng),又是一個(gè)網(wǎng)絡(luò)設(shè)分析RTL-8139PCI網(wǎng)卡驅(qū)動(dòng)程序,編寫分析文軟件:linux-2.6.29內(nèi)核源代RTL-8139PCI網(wǎng)卡驅(qū)動(dòng)位于內(nèi)核源代碼:模塊加載函數(shù)主要完成以下工作采用pci_register_driverpci驅(qū)動(dòng)程序/*模塊加載函數(shù)staticint initrtl8139_init_module{/*whenwe'reamodule,wealwaysprintaversion*evenifno8139boardis#ifdefprintk(KERN_INFORTL8139_DRIVER_NAME/*PCI驅(qū)動(dòng)return}/*pci_driver定義staticstructpci_driverrtl8139_pci_driver= = = = = #ifdefCONFIG_PM = =rtl8139_resume,#endif/*CONFIG_PM*/問題:probe調(diào)用時(shí)機(jī)答當(dāng)pci驅(qū)動(dòng)時(shí)內(nèi)核會(huì)在pci總線上去遍歷所有的碼drivers/pci/pci-driver.c),匹配方式為設(shè)備ID和驅(qū)動(dòng)注冊(cè)的id_table是否一致;如果匹配成功,說明的驅(qū)動(dòng)能驅(qū)動(dòng)該設(shè)備,則probe函數(shù)被調(diào)用。staticint devinitrtl8139_init_one(structpci_devconststructpci_device_id{/*初始化8139網(wǎng)卡dev=rtl8139_init_board(pdev);if(IS_ERR(dev))return/*TheRtl8139-specificentriesinthedevicestructure./*設(shè)置net_device的基本方法dev->netdev_ops=&rtl8139_netdev_ops;dev->ethtool_ops=&rtl8139_ethtool_ops;dev->watchdog_timeo=TX_TIMEOUT;netif_napi_add(dev,&tp->napi,rtl8139_poll,DPRINTK("abouttoregisterdevicenamed%s(%p)...\n",dev->name,dev);/*網(wǎng)卡驅(qū)動(dòng)i=register_netdev(dev);if(i)gotoerr_out;}接下來分析函數(shù)rtl8139_init_board和net_device基本方rtl8139_netdev_ops函數(shù)static devinitstructnet_device*rtl8139_init_boardpci_dev{/*devandprivzeroedinalloc_etherdev/*分配dev=alloc_etherdev(sizeof/*enabledevice(incl.PCIPMwakeupandhotplug/*在PCI驅(qū)動(dòng)使用PCI設(shè)備的任何資源(I/O區(qū)或者中斷)之前,驅(qū)動(dòng)必須使能設(shè)備*/rc=pci_enable_deviceifgoto/*獲得bar地址上的資源pio_start=pci_resource_start(pdev,0);pio_end=pci_resource_end(pdev,0);pio_flags=pci_resource_flags(pdev,0);pio_len=pci_resource_len(pdev,0);mmio_start=pci_resource_start(pdev,1);mmio_end=pci_resource_end(pdev,1);mmio_flags=pci_resource_flags(pdev,1);mmio_len=pci_resource_len(pdev,1);/*I/O資源的申請(qǐng)rc=pci_request_regions(pdev,DRV_NAME);if(rc)gotoerr_out;disable_dev_on_err=1;/*enablePCIbus-mastering/*通過設(shè)置PCI設(shè)備令寄存器允許pci_set_master(pdev);if(use_io){/*I/O地址映射ioaddr=pci_iomap(pdev,0,0);if(!ioaddr){dev_err(&pdev->dev,"cannotmapPIO,rc=-goto}dev->base_addr=pio_start;tp->regs_len=pio_len;}else/*ioremapMMIOregion/*I/O地址映射ioaddr=pci_iomap(pdev,1,0);if(ioaddr==NULL){dev_err(&pdev->dev,"cannotremapMMIO,}

use_io=1;gotodev->base_addr=(long)ioaddr;tp->regs_len=mmio_len;}/*復(fù)位rtl8139_chip_reset}/*網(wǎng)絡(luò)接口操作函數(shù)集staticconststructnet_device_opsrtl8139_netdev_ops= = /*網(wǎng)絡(luò)接口打開函數(shù) = = = rtl8139_start_xmit,/*發(fā)送函數(shù) = = =rtl8139_tx_timeout,#ifdefCONFIG_NET_POLL_CONTROLLER =rtl8139_poll_controller,問題:open函數(shù)調(diào)用時(shí)機(jī)函數(shù)rtl8139_open主要完成以下操作8139DMA緩沖區(qū)設(shè)置寄staticintrtl8139_open(structnet_device{/*中斷retval=request_irq(dev->irq,rtl8139_interrupt,IRQF_SHARED,dev->name,dev);ifreturn/*分配8139接收與傳送DMA緩沖區(qū)tp->tx_bufs=dma_alloc_coherent(&tp->pci_dev->dev,TX_BUF_TOT_LEN,&tp->tx_bufs_dma,GFP_KERNEL);tp->rx_ring=dma_alloc_coherent(&tp->pci_dev->dev,RX_BUF_TOT_LEN,&tp->rx_ring_dma,GFP_KERNEL);/*開啟網(wǎng)絡(luò)接口發(fā)送數(shù)據(jù)隊(duì)列netif_start_queuereturn}staticirqreturn_trtl8139_interrupt(intirq,{/*中斷狀態(tài)寄存器spin_lock(&tp-status=RTL_R16/*ReceivepacketsareprocessedbypollIfnotrunningstartitnow./*文到達(dá)中斷if(status&if(netif_rx_schedule_prep(&tp->napi)){RTL_W16_F(IntrMask,rtl8139_norx_intr_mask); }}/*報(bào)文發(fā)送完成中斷if(status&(TxOK|TxErr)){rtl8139_tx_interrupt(dev,tp,ioaddr);if(status&TxErr)RTL_W16(IntrStatus,}return}RTL8139網(wǎng)卡的發(fā)送和接收與前面實(shí)驗(yàn)5.5.1DM9000網(wǎng)掌握塊設(shè)備驅(qū)動(dòng)設(shè)計(jì)規(guī)范模式,測試方法設(shè)計(jì)ramdisk驅(qū)動(dòng)程序,并測#mkdir/home/guoqian/part5/4-1#cd/home/guoqian/part5/4-1 注:本程序以X86說明:上圖blk.ko為編譯生成的內(nèi)核模塊#insmodblk.ko#lsmod|grepblk#ls注:查看設(shè)備文件是否自動(dòng)建#mkfs.ext3注意:格式化塊設(shè)備文件為ext3系#mkdir–p注:創(chuàng)建掛#mount/dev/simp_blkdev/mnt/blk#ls/mnt/blk注:掛載塊設(shè)備simp_blkdev #cp/etc/init.d/*/mnt/blk#ls/mnt/blk注

溫馨提示

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

評(píng)論

0/150

提交評(píng)論