激情综合丁香-激情综合六月-激情综合婷婷亚洲图片-激情综合图区-激情综合网五月

精簡ISA總線WinCE編程

 2019-4-16     作者:劉乾坤         

ISA總線簡介


  英創(chuàng)精簡ISA總線接口是一種8-bit寬度的雙向并行擴展總線,其特點是地址數(shù)據(jù)分時復用8-bit總線。英創(chuàng)精簡ISA總線支持異步和同步訪問模式,異步訪問模式下ISA總線使用8條數(shù)據(jù)線加上4條總線控制信號,即可實現(xiàn)對外部數(shù)據(jù)的快速讀寫,異步訪問的最高速率在5MB/s左右。同步訪問需要再使能一條總線時鐘信號(共13條信號),可實現(xiàn)高達12MB/s的數(shù)據(jù)傳輸。精簡ISA總線作為英創(chuàng)主板的特色功能之一,在ESM6802、ESM7000、ESM335x等多款型號中均有配置。英創(chuàng)精簡ISA總線的信號定義如下:


主板引腳信號及說明
E2ISA_D0,地址數(shù)據(jù)總線,LSB
E3ISA_D1,地址數(shù)據(jù)總線
E4ISA_D2,地址數(shù)據(jù)總線
E5ISA_D3,地址數(shù)據(jù)總線
E6ISA_D4,地址數(shù)據(jù)總線
E7ISA_D5,地址數(shù)據(jù)總線
E8ISA_D6,地址數(shù)據(jù)總線
E9ISA_D7,地址數(shù)據(jù)總線
E10ISA_RDn,數(shù)據(jù)讀控制信號
E11ISA_WEn,數(shù)據(jù)寫控制信號
E12ISA_ADVn,地址鎖存控制信號
E13ISA_CSn,片選信號
F9GPIO24 / ISA_BCLK,同步時鐘ISA_BCLK


ISA總線數(shù)據(jù)結構


  ISA總線的數(shù)據(jù)傳輸由ISA_BLOCK_INFO數(shù)據(jù)結構定義,其說明如下:


typedef struct
{
       PBYTE    pReadBuf;          
       PBYTE    pWriteBuf;         
       DWORD       dwDataLength;
       DWORD       dwDataPortOfs; 
       DWORD       dwInc;                
} ISA_BLOCK_INFO, *PISA_BLOCK_INFO;


  成員說明


  pReadBuf

  ISA總線讀數(shù)據(jù)緩存,!=NULL表示為ISA總線讀操作,pReadBuf與pWriteBuf指針不能同時有效


  pWriteBuf

  ISA總線寫數(shù)據(jù)緩存, !=NULL表示為ISA總線寫操作,pReadBuf與pWriteBuf指針不能同時有效


  dwDataLength

  讀/寫訪問的字節(jié)長度


  dwDataPortOfs

  ISA端口地址。ISA總線驅動程序支持應用程序使用不同的地址范圍來區(qū)別不同的操作模式,根據(jù)ISA端口地址可實現(xiàn)以下幾種總線訪問模式。


ValueISA總線訪問模式
0x0000...0x00FF異步總線周期,CPU操作
0x1000...0x10FF異步總線周期,DMA方式傳輸,dwInc需要同時設置為0
0x4000...0x40FF同步總線周期,DMA方式傳輸,dwInc需要同時設置為0


  由于精簡ISA總線的寬度只有8-bit,因此它實際的物理尋址范圍也只有8-bit,即0x00-0xFF。


  dwInc

  每次ISA讀寫后地址是否增加


ValueMeaning
0固定地址
1讀/寫后地址自動加1


  備注:

  ISA總線的CPU操作方式主要用于小量數(shù)據(jù)的傳輸,比如控制命令、配置數(shù)據(jù)讀寫等。

  DMA方式傳輸可在較低CPU開銷的情況下實現(xiàn)大批量數(shù)據(jù)的高速傳輸,DMA方式傳輸要求傳輸?shù)臄?shù)據(jù)長度dwDataLength為32的整倍數(shù)、同時需要將dwInc設置為0,否則驅動程序會使用CPU方式進行數(shù)據(jù)傳輸。DMA傳輸方式需要連接在ISA總線的上CPLD/FPGA使用固定的數(shù)據(jù)端口地址,在CPLD/FPGA內部自己管理地址偏移。

  ESM335x工控主板只支持異步訪問模式,在異步DMA方式傳輸時,需要將dwInc設置為0來固定數(shù)據(jù)端口地址。

  ESM6802/ESM7000支持異步和同步DMA訪問模式,但由于SDMA(NXP Smart DMA)的原因,即使將dwInc設置為0,在進行DMA數(shù)據(jù)傳輸時也無法固定端口地址,因此CPLD/FPGA需要通過額外的方法來識別當前為DMA傳輸。ESM6802/ESM7000在進行異步DMA訪問時,可通過1位GPIO來向外表明當前為異步DMA訪問模式,也可通過CPU操作方式向指定地址寫入特定命令,讓CPLD/FPGA切換到異步DMA傳輸模式。在進行同步DMA訪問時,可結合ISA_BCLK信號來識別當前的傳輸模式。為了避免混淆,在實際應用時建議僅使用一種DMA(同步或異步)訪問模式,推薦使用同步DMA訪問模式以獲得最高的ISA總線速度。


ISA總線速度測試


  在ISA_BLOCK_INFO結構體中定義了異步CPU訪問,異步DMA和同步DMA三種ISA總線訪問方式,而異步CPU訪問又可通過驅動API函數(shù)和內存映射兩種方式來實現(xiàn)。


  驅動API訪問是指應用程序直接調用設備驅動API函數(shù)WriteFil/ReadFile進行字/字節(jié)的總線讀寫。ISA總線周期通常在200ns左右,而應用程序調用一次設備驅動程序API花費的時間卻需要數(shù)微秒的時間,這顯然大大降低了總線單字(或單字節(jié))的訪問效率。為了解決這一問題,我們利用了WinCE的虛擬地址映射技術,在ISA驅動程序中實現(xiàn)了,在使用ISA總線的應用進程地址空間內分配一段虛擬地址空間,并將其與ISA接口的物理地址空間進行綁定。簡單來講就是實現(xiàn)了在WinCE應用程序中可以直接訪問ISA總線的外設地址空間,即內存映射訪問方式。


  下圖是ESM3354、ESM7000和ESM6802,ISA總線在各種訪問模式下的總線速度。


精簡ISA總線WinCE編程.png

圖1 ESM335x / ESM7000 / ESM6802 ISA總線速度


  下圖是ESM7000 ISA總線在不同訪問模式下,總線速度與CPU使用情況的對比??梢钥吹絻却嬗成浞绞皆L問(異步CPU操作)與異步DMA訪問在總線速度上很接近,但使用DMA傳輸可大大降低對CPU的開銷。因此對于頻繁的字或字節(jié)訪問可以使用內存映射方式訪問,而對于成批量數(shù)據(jù)的讀寫應該使用DMA方式進行傳輸。


精簡ISA總線WinCE編程.png

圖2 ESM7000 ISA總線在不同訪問方式下總線速度與CPU占用率


ISA總線訪問API


  對ISA總線的所有訪問方法都包含在isa_api_v3.cpp文件中,如下所示:


#include "StdAfx.h"
#include "bsp_drivers.h"
#include <WinIoCtl.h>
#include "isa_api_v3.h"
 
DWORD       g_dwISABase = 0;
 
HANDLE       ISA_Open( LPCWSTR lpDevName )
{
       HANDLE       hISA;
 
       hISA = CreateFile(lpDevName,           // 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); 
 
       if(hISA != INVALID_HANDLE_VALUE)
       {
              if(DeviceIoControl(hISA,         //打開“ISA1:”返回的Handler
              IOCTL_VIRTUAL_COPY_EX,      // IOCTL命令碼    
              NULL,0,                                     // 不使用輸入?yún)?shù)
              &g_dwISABase, sizeof(DWORD),  // 得到ISA基地址   
              NULL, NULL))
                     return    hISA;
      
              CloseHandle(hISA);
              hISA = INVALID_HANDLE_VALUE;
       }     
       return    hISA;
}
 
BOOL     ISA_Close( HANDLE hISA)
{
       g_dwISABase = 0;
       return CloseHandle( hISA );
}
 
// Function: read a byte from a port on ISA bus
// Input: hISA: the HANDLE returned from ISA_Open function
//        dwPortOffset = 0, 1, .. 255, address of port on ISA
// Return: the byte data read
BYTE ISARead8(HANDLE hISA, DWORD dwPortOffset)
{
       WORD   *pPortAddr;
       WORD   wValue;
       BYTE      ucValue;
       DWORD       dwNbBytesRead = 0;
 
       if(g_dwISABase != 0)
       {
              dwPortOffset &= 0xff;
              dwPortOffset <<= 1;               // D[0..7] <=> A[1..8] in AD-muxed mode
              pPortAddr = (WORD*)(g_dwISABase + dwPortOffset);
              wValue = *pPortAddr;
 
              return (BYTE)wValue;
       }     
 
       ucValue = (BYTE)(dwPortOffset & 0xFF);
       ReadFile(hISA, &ucValue, sizeof(ucValue), &dwNbBytesRead, NULL);
       return ucValue;
}
 
// Function: write a byte to a port on ISA bus
// Input: hISA: the HANDLE returned from ISA_Open function
//        dwPortOffset = 0, 1, .. 255, address of port on ISA
//        ucValue = the byte data to be written
void ISAWrite8(HANDLE hISA, DWORD dwPortOffset, BYTE ucValue)
{
       WORD   *pPortAddr;
       WORD   wValue;
       DWORD       dwNbBytesWritten = 0;
 
       if(g_dwISABase != 0)
       {
              dwPortOffset &= 0xff;
              dwPortOffset <<= 1;               // D[0..7] <=> A[1..8] in AD-muxed mode
              pPortAddr = (WORD*)(g_dwISABase + dwPortOffset);
              *pPortAddr = (WORD)ucValue;   
              return;
       }     
 
       wValue = (WORD)(dwPortOffset & 0xFF);
       wValue = (wValue << 8) | ucValue;
       WriteFile(hISA, &wValue, sizeof(wValue), &dwNbBytesWritten, NULL);
}
 
// Function: read a word from a port on ISA bus
// Input: hISA: the HANDLE returned from ISA_Open function
//        dwPortOffset = 0, 2, 4, .. 254, address of port on ISA
// Return: the word data read
WORD ISARead16(HANDLE hISA, DWORD dwPortOffset)
{
       DWORD       *pPortAddr;
       DWORD       dwValue;
       WORD   wValue;
       DWORD       dwNbBytesRead = 0;
 
       if(g_dwISABase != 0)
       {
              dwPortOffset &= 0xFE;           // 2-byte alignment
              dwPortOffset <<= 1;               // D[0..7] <=> A[1..8] in AD-muxed mode
              pPortAddr = (DWORD*)(g_dwISABase + dwPortOffset);
              dwValue = *pPortAddr;
              // the high-byte of data is at value[23..16]
              return (WORD)(((dwValue >> 8) & 0xFF00) | (dwValue & 0xFF));
       }
 
       wValue = (WORD)(dwPortOffset & 0xFE);
       ReadFile(hISA, &wValue, sizeof(wValue), &dwNbBytesRead, NULL);      
       return wValue;
}
 
// Function: write a word to a port on ISA bus
// Input: hISA: the HANDLE returned from ISA_Open function
//        dwPortOffset = 0, 2, 4, .. 254, address of port on ISA
//        wValue = the word data to be written
void ISAWrite16(HANDLE hISA, DWORD dwPortOffset, WORD wValue)
{
       DWORD       *pPortAddr;
       DWORD       dwValue;
       DWORD       dwNbBytesWritten = 0;
 
       if(g_dwISABase != 0)
       {
              dwPortOffset &= 0xFE;           // 2-byte alignment
              dwPortOffset <<= 1;               // D[0..7] <=> A[1..8] in AD-muxed mode
              pPortAddr = (DWORD*)(g_dwISABase + dwPortOffset);
              dwValue = wValue;
              // dispatch high-byte of data to value[23..16]
              *pPortAddr = ((dwValue << 8) & 0x00ff0000) | (dwValue & 0x000000ff);
              return;
       }
 
       dwValue = (dwPortOffset << 16) | wValue;
       WriteFile(hISA, &dwValue, sizeof(dwValue), &dwNbBytesWritten, NULL);
}
 
// Function: read a bulk data from a port on ISA bus
// Input: hISA: the HANDLE returned from ISA_Open function
//        *tp: a pointer to the ISA_BLOCK_INFO structure
// Return: number of bytes read
DWORD       ISAReadBuf(HANDLE hISA, PISA_BLOCK_INFO tp)
{
       DWORD dwNbBytesRead = 0;
 
       if(ReadFile(hISA, tp, sizeof(ISA_BLOCK_INFO), &dwNbBytesRead, NULL))
              return dwNbBytesRead;
       return 0;
}
 
// Function: read a bulk data from a port on ISA bus
// Input: hISA: the HANDLE returned from ISA_Open function
//        *tp: a pointer to the ISA_BLOCK_INFO structure
// Return: the number of bytes written
DWORD       ISAWriteBuf(HANDLE hISA, PISA_BLOCK_INFO tp)
{
       DWORD dwNbBytesWritten = 0;
       if(WriteFile(hISA, tp, sizeof(ISA_BLOCK_INFO), &dwNbBytesWritten, NULL))
              return dwNbBytesWritten;
 
       return 0;
}


  注意,當采用內存映射方式訪問時,若在多個線程中均有調用字或字節(jié)讀寫函數(shù)(ISAWrite8, ISAWrite16, ISARead8, ISARead126),需要加互斥鎖,以保證對硬件資源操作的完整性。通過驅動API調用的讀寫函數(shù),在驅動內部已經增加了互斥操作,應用程序不需要再次添加。


ISA異步總線周期讀時序


精簡ISA總線WinCE編程.png


ISA異步總線周期寫時序


精簡ISA總線WinCE編程.png


ISA同步總線周期讀時序


精簡ISA總線WinCE編程.png


  ISA擴展單元可根據(jù)上述時序來支持高速的同步總線周期讀邏輯電路,其要點包括:

  ● 每個同步周期共12個BCLK時鐘,第1個BCLK下降沿ADVn有效,標志同步周期的開始,之后連續(xù)11個BCLK下降沿后同步周期結束。

  ● 每個同步周期傳輸8個字節(jié)有效數(shù)據(jù),ISA總線從BCLK第5個上升沿開始鎖存數(shù)據(jù),連續(xù)讀8個字節(jié)。

  ● ISA總線雖然輸出了ADDR地址數(shù)據(jù),但這個地址是不固定的,ISA擴展單元應該忽略此地址數(shù)據(jù)。


ISA同步總線周期寫時序


精簡ISA總線WinCE編程.png


  ISA擴展單元可根據(jù)上述時序來支持高速的同步總線周期寫邏輯電路,其要點包括:

  ● 每個同步周期共12個BCLK時鐘,第1個BCLK下降沿ADVn有效,標志同步周期的開始,之后連續(xù)11個BCLK下降沿后同步周期結束。

  ● 每個同步周期傳輸8個字節(jié)有效數(shù)據(jù),ISA擴展單元應從BCLK第5個上升沿開始鎖存數(shù)據(jù),連續(xù)8個字節(jié)。

  ● ISA總線雖然輸出了ADDR地址數(shù)據(jù),但這個地址是不固定的,ISA擴展單元應該忽略此地址數(shù)據(jù)。

主站蜘蛛池模板: 国产毛片在线| 美国一级特色大黄| 久久久视频在线| 亚洲欧美日韩国产综合| 久久青草免费97线频观| 亚洲成a人片在线观看www| 欧美a级影院| 国产日本亚洲| 夜色网| 91短视频网址| 国产精品久久久久久久免费大片 | 国产一区二区不卡免费观在线| 黄色大毛片| 91久久福利国产成人精品| 国产一区曰韩二区欧美三区| 欧美在线成人午夜网站| 亚洲欧美日韩专区一| xxxxxx日本护士xxxx| 日本 欧美 在线| 日韩欧美二区| 亚洲一区二区三区四区五区| 成人欧美精品一区二区不卡| 欧美久久一区二区| 国产1024在线永久免费观看| 国产啊v在线观看| 夜鲁鲁鲁夜夜综合视频欧美| 黄色中文字幕| 韩国免费特一级毛片| 激情免费网站| 97起碰| 91小视频在线观看| 成人污| 成人国产免费| 成人啪啪网站| 丁香婷婷久久| 福利午夜国产网站在线不卡| 国产美女啪| 国产精品久久久久免费| 国产三级视频在线观看视主播| 国产综合福利| 国产三级图片|