<strike id="kiyse"></strike>
  • <tr id="kiyse"></tr>
  • <strike id="kiyse"></strike><samp id="kiyse"><tbody id="kiyse"></tbody></samp>
    <strike id="kiyse"><s id="kiyse"></s></strike>
    <tr id="kiyse"></tr>
    <noframes id="kiyse"><code id="kiyse"></code></noframes>
    <th id="kiyse"></th>
    <samp id="kiyse"></samp>
  • <th id="kiyse"><s id="kiyse"></s></th>
  • WinCE應用程序快速訪問ISA總線端口

     2019-2-27     作者:劉乾坤         
    文章標簽:C/C++精簡ISA總線

      精簡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驅動程序,需要的用戶可與英創聯系。

    文章標簽:C/C++精簡ISA總線
    亚洲日韩一页精品发布| 亚洲AV午夜福利精品一区二区| 国产精品美女WWW爽爽爽视频| 综合在线视频精品专区| 国产精品东北一极毛片| 嫩B人妻精品一区二区三区| 精品久久久久久无码专区| 国产精品成人一区无码| 亚洲精品无码mv在线观看网站 | 一本一本久久aa综合精品| 成人国产精品2021| 国产精品免费看久久久| 国产精品无码专区AV在线播放| 久久www免费人成精品香蕉| 亚洲国产成人91精品| 精品一区二区三区免费视频| 日韩精品免费一级视频| 国产成人无码精品久久久免费| 久久亚洲AV无码精品色午夜 | 99re在线精品视频| 免费看一级毛片在线观看精品视频| 久久久91精品国产一区二区三区 | 国产乱子伦精品无码码专区| 亚洲国产精品一区二区第一页免| 91精品手机国产免费| 久久精品成人影院| 大桥未久在线精品视频在线 | 精品国产一区二区二三区在线观看 | 一本色道久久88精品综合| 国产精品美女久久久久av爽| 亚洲第一区精品日韩在线播放| 国产精品美女久久久浪潮av| 久视频精品免费观看99| 91亚洲精品第一综合不卡播放| 人妻AV一区二区三区精品| 国产高清精品一区| 伊人久久精品影院| 久久精品国产亚洲精品| 奇米影视7777久久精品人人爽| 久久精品一区二区三区中文字幕| 91精品国产9l久久久久|