• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 74, 文章 - 0, 評論 - 26, 引用 - 0
            數據加載中……

            WINCE Driver and BSP Develop Blog 轉

            開發優秀的驅動程序

            作為驅動開發工程師,我們需要在每一行代碼上下功夫,因為驅動程序的效率直接影響著系統的性能.而新手往往不會注意到這些細節。以為功能實現以后就萬事大吉了,其實不然,好的驅動程序不只是能實現預期的功能。它同樣需要高的效率與規范的風格。用戶花錢買我們系統是給他/她做事的,而不是給我們做測試的,所以我們要盡可能提高效率。同時好的代碼風格能大大降低我們自己的維護成本。

            高效率看似容易,但要注意到每個細節還是挺難的,我們可以從以下幾點去注意這個問題:

            1, 不要使用無關的代碼,這點容易理解,尤其是調試代碼,RELEASE時一定要去除這些代碼。

            2, 去掉多余的函數調用,盡可能的保存一些數據。即使是最快的函數,調用它時也會引發壓棧與出棧,所以要盡量少做函數調用。當然如果一個函數返回的數據比較大,保存那些數據將占用比較多的內在空間,保存返回值就得不償失了。比如,看到有的人每次在使用一個地址時就調用MmmapIoSpace將這個地址映射到程序地址空間,用完以后又立即Unmap這個地址,下次使用時又做MAP,這就是一種及不好的方法,每次需要多調用兩個系統函數。

            3.如果可行,不要在循環中使用條件判斷,尤其在一個次數很多的循環中更應該如此。

            比如:

            For( i=0; i<1000;>

            If( m==1) ..

            Else if (m==2 )….

            Else …..

            }

            這種代碼,我們可以把If 寫在for 之外,即,每一種不同的條件寫一個循環體。

            If( m==1) for ...

            Else if (m==2 ) for ….

            Else for …..

            標簽:

            2007-03-10

            開發DMA驅動

            使用DMA的好處就是它不需要CPU的干預而直接服務外設,這樣CPU就可以去處理別的事務,從而提高系統的效率,對于慢速設備,如UART,其作用只是降低CPU的使用率,但對于高速設備,如硬盤,它不只是降低CPU的使用率,而且能大大提高硬件設備的吞吐量。因為對于這種設備,CPU直接供應數據的速度太低。

            CPU只能一個總線周期最多存取一次總線,而且對于ARM,它不能把內存中A地址的值直接搬到B地址。它只能先把A地址的值搬到一個寄存器,然后再從這個寄存器搬到B地址。也就是說,對于ARM,要花費兩個總線周期才能將A地址的值送到B地址。而DMA就不同了,一般系統中的DMA都有突發(Burst)傳輸的能力,在這種模式下,DMA能一次傳輸幾個甚至幾十個字節的數據,所以使用DMA能使設備的吞吐能力大為增強。

            使用DMA時我們必須要注意如下事實:

            1. DMA使用物理地址,程序是使用虛擬地址的,所以配置DMA時必須將虛擬地址轉化成物理地址。

            2. 因為程序使用虛擬地址,而且一般使用CACHED地址,所以虛擬地址中的內容與其物理地址上的內容不一定一致辭,所以在啟動DMA傳輸之前一定要將該地址的CACHE刷新,即寫入內存。

            3. OS并不能保證每次分配到的內在空間在物理上是連續的。尤其是在系統使用過一段時間而又分配了一塊比較大的內存時。

            所以每次都需要判斷地址是不是連續的,如果不連續就需要把這段內存分成幾段讓DMA完成傳輸。

            標簽:

            2007-03-03

            WINCE下USBFN驅動程序的一些概念

            USBFN,即USB客戶端驅動,用來將一個WINCE設備模擬成一定的USB設備,讓主機端(如PC)訪問。目前WINCE提供的USB客戶端有存儲設備,串口設備,及RNDIS網絡接口設備。

            存儲設備用來將WINCE設備上的存儲空間,例如FLASH,當作一塊存儲介質給主機訪問,即將WINCE設備模擬成一個U盤。

            串口設備將設備與主機的USB連線模擬成串口,WINCE和主機端都認為它們之前連接上了一根串口線,它們之間可以做串口通信,典型的應用是用來實現WINCEPC機的同步連接。

            RNDIS設備使兩端認為它們之間建立了網絡連接,通過注冊表設置可以讓主機通過WINCE設備上網或者使WINCE設備通過主機上網。

            WINCE已經提供了以上三種設備的驅動程序,在同一時刻只能使用一個設備。而我們需要做的只是提供USBFN總線控制器的驅動程序。USBFN系統各個模塊的關系如下:

            USBFN總路線控制器作為一個總線驅動程序,被設備管理器加載,根據注冊表設置加載相應的客戶驅動程序,即存儲設備,串口設備或者RNDIS設備。客戶驅動程序即啟動USBFN,引發主機配置設備,配置完成以后即可開始工作。

            USBFN總路線控制器驅動的MDD部分WINCE本身已經提供,PDD只需初始化硬件設備,提供傳輸即可。MDD在初始化時調用UfnPdd_Init函數得到PDD層的函數表,之后會根據需要調用各個函數。PDD還需要提供IST,用以處理各個中斷。需要注意的是USBFN有一個與其它設備不同之處,它的注冊表需要這樣一個設置:

            "BusIoctl"=dword:2a0048,用以讓系統加載完設備之后調用值為0x2a0048IOCTL代碼去完成初始化,其定義為IOCTL_BUS_POSTINIT

            標簽:

            2007-02-28

            SOURCES文件詳解

            SOURCES文件是WINCE底層開發中最重要的文件之一,主要的配置項如下:

            TARGETNAME,定義模塊名稱.
            TARGETTYPE,
            模塊的種類,可以是DYNLINK, LIBRARY,EXE.
            如果TARGETTYPEDLL,則可以定義DLLENTRY,Dll入口定義成別的不是DLLMain的函數,如果DLL的入口是DllMain,則不需要別的定義。
            如果TARGETTYPEEXE,則可以定義EXEENTRY,用于指定EXE的入口函數.

            如果TARGETTYPELIBRARY,則不需要定義入口函數。


            INCLUDES
            ,如果一個模塊需要使用非標準路徑下的頭文件時,需要定義INCLUDES,用于包含更多的頭文件路徑,用法如下:

            INCLUDES=$(INCLUDES);\new directory\...,
            注意定義新的INCLUDES,需要包含INCLUDES原來的值,否則就需要包含所有可能的目錄。

            TARGETLIBS,SOURCELIBS
            用于定義該模塊需要鏈接哪些庫文件.


            TARGETLIBS
            ,如果一個庫以DLL的形式提供給調用者,就需要用TARGETLIBS,它只鏈接一個函數地址,系統執行時會將被鏈接的庫加載。比如coredll.lib就是這樣的庫文件。即動態鏈接。

            SOURCELIBS,將庫中的函數實體鏈接進來。即靜態鏈接,用到的函數會在我們的文件中形成一份拷貝。


            注意,內核這個執行文件是沒有TARGETLIBS的,GIISR.DLL也不能有TARGETLIBS


            WINCECOD,
            如果將其定義為1,則編譯器會為每一個文件生成.cod文件,它是一個匯編文件,調試時查看匯編代碼也是一種很好的辦法。

            SOURCES,
            定義該模塊需要哪些源文件.

            標簽:

            2007-02-17

            多個設備共享同一個硬件中斷

            硬件中斷線總是有限的,我們可能需要在已有的系統上做一些擴展,比如將串口擴展成好幾個,有些硬件本身就設計成多個設備共享一條中斷線,比如我的系統中兩個串口就共享同一個CPU中斷,任何一個串口發生中斷以后都會觸發CPU的同一條中斷線,需要判斷別的寄存器來確定是哪個串口發生了什么中斷。

            我們可以在OAL中分析各個中斷源,然后返回不同的SYSINTR值,但這種做法擴展性不好。例如,OAL中設值某個中斷源最多會產生三個SYSINTR,但以后擴展成了四個設備,有一個設備就無法正常工作了。

            WINCE引入了可裝載中斷處理例程的概念。即在需要與別的設備共享中斷的驅動程序中加載一個ISR,一般使用WINCE提供的GIISR即成滿足需求。將其安裝到內核。OAL中發生中斷時調用NKCallIntChain來得到SYSINTR,這個函數會引起系統逐個調用在該IRQ上加載的所有可裝載的ISR,當某個ISR認為這個中斷是由它引發的時就返回其SYSINTR,否則就返回SYSINTR_CHAIN系統就會接著調用其它的ISR,甚至所有的ISR都被調用或者有一個ISR返回了正確的SYSINTR

            驅動程序中的調用辦法如下(CE幫助文檔):

            if (InstallIsr) {

            // Install ISR handler

            g_IsrHandle = LoadIntChainHandler(IsrDll, IsrHandler, (BYTE)Irq);

            if (!g_IsrHandle) {

            DEBUGMSG(ZONE_ERROR, (L"WAVEDEV: Couldn't install ISR handler\r\n"));

            } else {

            GIISR_INFO Info;

            PVOID PhysAddr;

            DWORD inIoSpace = 1; // io space

            PHYSICAL_ADDRESS PortAddress = {ulIoBase, 0};

            if (!TransBusAddrToStatic(PCIBus, 0, PortAddress, ulIoLen, &inIoSpace, &PhysAddr)) {

            DEBUGMSG(ZONE_ERROR, (L"WAVEDEV: Failed TransBusAddrToStatic\r\n"));

            return FALSE;

            }

            DEBUGMSG(ZONE_PDD, (L"WAVEDEV: Installed ISR handler, Dll = '%s', Handler = '%s', Irq = %d, PhysAddr = 0x%x\r\n", IsrDll, IsrHandler, Irq, PhysAddr));

            // Set up ISR handler

            Info.SysIntr = ulSysIntr;

            Info.CheckPort = TRUE;

            Info.PortIsIO = TRUE;

            Info.UseMaskReg = FALSE;

            Info.PortAddr = (DWORD)PhysAddr + ES1371_dSTATUS_OFF;

            Info.PortSize = sizeof(DWORD);

            Info.Mask = ES1371_INTSTAT_PENDING;

            if (!KernelLibIoControl(g_IsrHandle, IOCTL_GIISR_INFO, &Info, sizeof(Info), NULL, 0, NULL)) {

            DEBUGMSG(ZONE_ERROR, (L"WAVEDEV: KernelLibIoControl call failed.\r\n"));

            }

            }

            }

            這里需要注意一下,因為ISR在內核態運行,Info.PortAddr必須是系統最原始的虛擬地址,即沒有用VirtualCopy映射過的,從OEMAddressTable中計算出來的虛擬地址。在這個例子中用TransBusAddrToStatic函數可以直接把物理地址轉換成這種地址。而MmMapIoSpace得到是在當前程序空間中的地址,不能使用。而且GIIR要被加載到內核空間,所以在加入到OS包中時需要加上K標志,否則LoadIntChainHandler函數會失敗。

            posted on 2008-12-24 15:12 井泉 閱讀(740) 評論(0)  編輯 收藏 引用

            香蕉久久夜色精品国产小说| 伊人久久大香线蕉综合影院首页| AV无码久久久久不卡蜜桃| 久久99精品久久久久久动态图| 99久久er这里只有精品18| 91精品国产综合久久香蕉| 久久久久久国产a免费观看黄色大片 | 久久青青草视频| av国内精品久久久久影院| 久久青青草原精品国产软件| 久久久久久九九99精品| 久久国产精品免费一区二区三区| 麻豆久久久9性大片| 青青草国产成人久久91网| 亚洲AV无码1区2区久久 | 九九精品久久久久久噜噜| 亚洲欧美成人综合久久久| 色8激情欧美成人久久综合电| 久久亚洲国产精品一区二区| 漂亮人妻被中出中文字幕久久| 中文字幕亚洲综合久久2| 99精品久久久久久久婷婷| 亚洲Av无码国产情品久久| 国产A级毛片久久久精品毛片| 久久99精品久久久久久动态图 | 久久996热精品xxxx| 狠狠色丁香婷婷久久综合不卡| 久久热这里只有精品在线观看| 久久成人永久免费播放| 99久久er这里只有精品18| aaa级精品久久久国产片| 久久亚洲AV成人无码| 久久亚洲中文字幕精品一区| 91麻精品国产91久久久久| 亚洲国产精品无码成人片久久| 狠狠色婷婷久久综合频道日韩| 亚洲精品tv久久久久| 久久精品国产一区二区三区| 国产AV影片久久久久久| 久久国产热这里只有精品| 久久综合久久鬼色|