<track id="zxlr8"></track>
<u id="zxlr8"><sub id="zxlr8"></sub></u>
  • <track id="zxlr8"></track>
    1. <ins id="zxlr8"><table id="zxlr8"></table></ins><wbr id="zxlr8"><ins id="zxlr8"></ins></wbr>
      <wbr id="zxlr8"><table id="zxlr8"></table></wbr><u id="zxlr8"><bdo id="zxlr8"></bdo></u>
    2. <video id="zxlr8"></video>
      <rp id="zxlr8"><input id="zxlr8"></input></rp>
    3. <u id="zxlr8"></u>

      WinCE應用程序快速訪問ISA總線端口

       2019-2-27     作者:劉乾坤    

        精簡ISA總線是英創工控主板的特色之一,我們基于ISA總線推出了多串口、多網口、多CAN接口等擴展模塊,我們的很多用戶也基于ISA總線設計了自己的專有擴展單元并取得了成功。為了充分發揮ISA總線的性能,對于ISA總線的訪問,我們除了提供最基本的設備驅動API操作函數外,還先后增加了ISA總線的塊讀寫操作方法ISA總線的DMA操作方法。當ISA總線以DMA方式進行數據傳輸時,在最大限度的利用ISA總線帶寬的同時,又減少了ISA操作占用CPU的時間,所以利用DMA是進行批量數據傳輸時的首選方式。


        在實際的應用中,除了成批量的數據訪問外,也可能會存在對外設進行頻繁的字或字節訪問。英創主板的ISA總線周期通常在200ns左右,而應用程序調用一次設備驅動程序API(WriteFile,ReadFile)花費的時間卻需要數微秒的時間,這顯然大大降低了對外設單字(或單字節)的訪問效率。為了解決這一問題,我們利用了WinCE的虛擬地址映射技術,在ISA驅動程序中實現了在使用ISA的應用進程地址空間內分配一段虛擬地址空間,并將其與ISA接口的物理地址空間進行了綁定。簡單來講就是實現了在WinCE應用程序中可以直接訪問ISA總線的外設地址空間,從使用的角度看,我們實現了以下5個函數。ISAMmMap用于獲得ISA總線的基地址,其余4個函數分別為字讀/寫和字節讀/寫操作函數。


      HANDLE       ISAMmMap(HANDLE hISA);                                    // 映射ISA總線物理地址空間
      BYTE          ISARead8(HANDLE hMmMap, DWORD dwPortOffset);               // 讀單字節
      void           ISAWrite8(HANDLE hMmMap, DWORD dwPortOffset, BYTE ucValue);   // 寫單字節
      WORD       ISARead16(HANDLE hMmMap, DWORD dwPortOffset);                    // 讀單字void           ISAWrite16(HANDLE hMmMap, DWORD dwPortOffset, WORD wValue);       // 寫單字



        下面是上述5個函數實現的源代碼,在ISAMmMap函數中調用DeviceIoControl,通過IOCTL_VIRTUAL_COPY_EX命令獲取ISA總線的基地址。


      // Function: Get the base address of ISA Port
      // Input:    hISA: Handle of ISA1:
      // Return:   Base address of the ISA Port
      HANDLE ISAMmMap(HANDLE hISA)
      {
             DWORD       dwMemBase;
       
             if(DeviceIoControl(hISA,         //打開“ISA1:”返回的Handler
                    IOCTL_VIRTUAL_COPY_EX,      // IOCTL命令碼    
                    NULL,0,                                // 不使用輸入參數
                    &dwMemBase, sizeof(DWORD),  // 得到ISA基地址   
                    NULL, NULL))
                    return (HANDLE)dwMemBase;
       
             return NULL;
      }
       
      // Function: read a byte from a port on ISA bus
      // Input: hMmMap: Base address of the ISA Port
      //         dwPortOffset = 0, 1, .. 255, address of port on ISA
      // Return: the byte data read
      BYTE ISARead8(HANDLE hMmMap, DWORD dwPortOffset)
      {
             WORD   *pPortAddr;
             WORD   wValue;
       
             dwPortOffset &= 0xff;
             dwPortOffset <<= 1;               // D[0..7] <=> A[1..8] in AD-muxed mode
             pPortAddr = (WORD*)((DWORD)hMmMap + dwPortOffset);
             wValue = *pPortAddr;
       
             return (BYTE)wValue;
      }
       
      // Function: write a byte to a port on ISA bus
      // Input: hMmMap: Base address of the ISA Port//
      //        dwPortOffset = 0, 1, .. 255, address of port on ISA
      //        ucValue = the byte data to be written
      void ISAWrite8(HANDLE hMmMap, DWORD dwPortOffset, BYTE ucValue)
      {
             WORD   *pPortAddr;
            
             dwPortOffset &= 0xff;
             dwPortOffset <<= 1;               // D[0..7] <=> A[1..8] in AD-muxed mode
             pPortAddr = (WORD*)((DWORD)hMmMap + dwPortOffset);
             *pPortAddr = (WORD)ucValue;   
      }
       
      // Function: read a word from a port on ISA bus
      // Input: hMmMap: Base address of the ISA Port
      //        dwPortOffset = 0, 2, 4, .. 254, address of port on ISA
      // Return: the word data read
      WORD ISARead16(HANDLE hMmMap, DWORD dwPortOffset)
      {
             DWORD       *pPortAddr;
             DWORD       dwValue;
       
             dwPortOffset &= 0xFE;           // 2-byte alignment
             dwPortOffset <<= 1;               // D[0..7] <=> A[1..8] in AD-muxed mode
             pPortAddr = (DWORD*)((DWORD)hMmMap + dwPortOffset);
             dwValue = *pPortAddr;
             // the high-byte of data is at value[23..16]
             return (WORD)(((dwValue >> 8) & 0xFF00) | (dwValue & 0xFF));     
      }
       
      // Function: write a word to a port on ISA bus
      // Input: hMmMap: Base address of the ISA Port
      //        dwPortOffset = 0, 2, 4, .. 254, address of port on ISA
      //        wValue = the word data to be written
      void ISAWrite16(HANDLE hMmMap, DWORD dwPortOffset, WORD wValue)
      {
             DWORD       *pPortAddr;
             DWORD       dwValue;
       
             dwPortOffset &= 0xFE;           // 2-byte alignment
             dwPortOffset <<= 1;               // D[0..7] <=> A[1..8] in AD-muxed mode
             pPortAddr = (DWORD*)((DWORD)hMmMap + dwPortOffset);
             dwValue = wValue;
             // dispatch high-byte of data to value[23..16]
             *pPortAddr = ((dwValue << 8) & 0x00ff0000) | (dwValue & 0x000000ff);
      }


        我們在ESM3352上,分別測試了利用地址映射方法直接訪問ISA外設地址和調用設備驅動API函數讀寫ISA地址,測得的結果是當進行字(WORD)讀寫時,應用程序直接訪問ISA外設地址比調用設備驅動API函數快10倍以上,當時行字節(BYTE)讀寫時,應用程序直接訪問ISA外設地址比調用設備驅動API函數快15倍以上。


        下面是測試程序源代碼:


      int _tmain(int argc, _TCHAR* argv[])
      {
             HANDLE       hISA, hMmMap;
             BYTE             ucValue;
             WORD          wValue;
       
             DWORD       dwStartTick, dwEndTick, i, k, cnt=2000;
       
             hISA = CreateFile(_T("ISA1:"),        // name of device
                    GENERIC_READ|GENERIC_WRITE,         // desired access
                    FILE_SHARE_READ|FILE_SHARE_WRITE,      // sharing mode
                    NULL,                                               // security attributes (ignored)
                    OPEN_EXISTING,                             // creation disposition
                    FILE_FLAG_RANDOM_ACCESS,                    // flags/attributes
                    NULL);
       
             hMmMap = ISAMmMap(hISA);
             if(hMmMap == NULL)
                    return -1;
       
             printf("ISA read/write speed test\r\n");
             printf("Memory Map VS Device Driver API\r\n");
       
             dwStartTick = GetTickCount();
             for(i=0; i<cnt; i++)
                    for(k=0; k<256; k++)
                    {
                           ISAWrite8(hMmMap, k, 0x55);
                           ucValue = ISARead8(hMmMap, k);      
                    }
             dwEndTick = GetTickCount();
             printf("1. Memory map BYTE read/write %d KBytes, Take time:%d ms\r\n", 256 * 2 *cnt / 1024, dwEndTick - dwStartTick);
       
             dwStartTick = GetTickCount();
             for(i=0; i<cnt; i++)
                    for(k=0; k<256; k++)
                    {
                           ISA_WriteUchar( hISA, k, 0x55 );
                           ISA_ReadUchar( hISA, k, &ucValue );
                    }
                    dwEndTick = GetTickCount();
             printf("2. Device driver API BYTE read/write %d KBytes, Take time:%d ms\r\n", 256 * 2 * cnt/ 1024, dwEndTick - dwStartTick);
       
             cnt /= 2;
             dwStartTick = GetTickCount();
             for(i=0; i<cnt; i++)
                    for(k=0; k<256; k++)
                    {
                           ISAWrite16(hMmMap, k, 0x55AA);
                           wValue = ISARead16(hMmMap, k);     
                    }
             dwEndTick = GetTickCount();
             printf("3. Memory map WORD read/write %d KBytes, Take time:%d ms\r\n", 256 * 4 * cnt / 1024, dwEndTick - dwStartTick);
       
             dwStartTick = GetTickCount();
             for(i=0; i<cnt; i++)
                    for(k=0; k<256; k++)
                    {
                           ISA_WriteWord( hISA, k, 0x55AA );
                           ISA_ReadWord( hISA, k, &wValue );
                    }
                    dwEndTick = GetTickCount();
             printf("4. Device driver API WORD read/write %d KBytes, Take time:%d ms\r\n", 256 * 4 * cnt / 1024, dwEndTick - dwStartTick);
       
             CloseHandle(hISA);
             return 0;
      }


        下面是在ESM3352上兩種訪問方式的測試結果:



        要實現應用程序直接訪問ISA外設地址空間需要更新ISA驅動程序,需要的用戶可與英創聯系。

      A毛看片免费观看视频视频在线播放,国产a片欧美一级毛 片在线观看,2019午夜75福利不卡片在线,久久精品国产99国产精,最近更新中文字幕免费,久久人人97超碰,中文字幕无码A片久久东京热 亚洲伊人成综合人影院,亚洲国产中文字幕在线视频,天天五月缴情在线观看,97国产在线看片免费人成视频,天干夜天天夜天干天,免费A级毛片高清视频,窝窝午夜色视频国产精品 92福利视频合集100午夜,人人天天夜夜曰曰狠狠狠,免费观看网站 亚洲自国产拍偷拍,国产免费888在线观看,久久天天躁狠狠躁夜夜躁2020,无羞耻肉动漫在线观看 欧美成人电影,日本不卡免费一区二区,老司机精品视频在线观看,快播影院在线观看,无遮挡又色又黄的免费视频,美女一黄色网站,成年无码AV片在线观看,亚洲AVAV天堂Av在线不卡 色就色欧美综合在线影院,亚洲欧美卡通另类丝袜美腿,老司机福利在线观看,夜夜爽8888免费视频,国内自拍99re久久,2018Av天堂在线视频精品观看,少妇无码精品12p 午夜天堂欧美成人在线视频,超碰91自拍国产自拍,激情综合色综合啪啪五月,男人的天堂在线视频,午夜理理伦A级毛片天天看,无码熟妇人妻AV在线偷拍,大量偷拍情侣自拍视频 精品国产自在现线拍在线,无码专区人妻系列日韩,色婷婷色综合缴情网站,猛男操的我高潮连连,国产片av国语在线观看手机版,久久人人97超碰精品,亚洲最大AV网站在线观看
      久久亚洲精品无码爱剪辑,亚洲欧美国产vr在线观,国产真实乱子伦精品视频,日韩精品一区二区中文免费在线观看,在线A亚洲V天堂网2018,免费观看欧美大片毛片不用播放器 日本极品高清不卡AV,亚洲AⅤ天堂AV在线电影猫咪,五月色婷婷综合狠狠爱,碰超79网站,印度女人牲交视频免费播放,va在线看国产免费,狠狠躁夜夜躁人人爽天天古典 免费 在线 av 日本,免费A片在线观看,一本道久在道最新2021,人妻无码不卡中文字幕系列,午夜爽爽爽男女免费观看HD,日本高清视频永久网站www,东京热人妻无码人av 人人插人人莫人人干在线,AV天堂久久天堂AV色综合,欧美A色爱综合网欧美V,亚洲图欧美日韩在线,亚洲中文字幕曰本毛片,中文字幕97超碰大香寡妇蕉,久爱在线 亚洲AV片不卡无码久久,亚洲人成免费观看视频在线,欧洲亚洲偷自拍第一页,av在线播放日韩亚洲欧,一日本道不卡高清A无码,97碰碰碰人妻无码视频,加勒比最新无码AV免费资源 国内精品自线在拍,日韩一区二区三不卡高清,伊人中文字幕无码专区视频在线播放网站,看全黄大色黄大片美女蓝光在线看,无码av高清毛片在线看,人人超人人超碰超国产 小草视频手机在线视频,免费黃色大片,偷欧洲亚洲另类图片AV天堂,久久国产乱子伦,国产乱子伦精品视频,日本高清色本在线视频观看,加勒比一本HEYZO高清视频 AV无码东京热亚洲男人的天堂,315电影网A级毛片,深夜A级毛片视频免费,亚洲日本VA午夜在线电影,日本无码免费不卡AV二区,在线看午夜福利片国产,亚洲中文字幕aⅴ天堂 无码刺激性A片,成上人色爱A∨综合网,午夜性影院在线观看视频播放,手机国产乱子伦精品视频,无码99久热只有精品视频在线,狠狠噜天天噜日日黑人亚洲,在线观看无码不卡 真实国产乱子伦对白视频不卡,国产成人亚洲精品,老司机亚洲精品影院无码,亚洲成av人片在线观看天堂无码,美国一级a片,狠狠狠的在啪线香蕉亚洲,AV男人的天堂在线观看第三区