精簡(jiǎn)ISA總線(xiàn)是英創(chuàng)工控主板的特色之一,我們基于ISA總線(xiàn)推出了多串口、多網(wǎng)口、多CAN接口等擴(kuò)展模塊,我們的很多用戶(hù)也基于ISA總線(xiàn)設(shè)計(jì)了自己的專(zhuān)有擴(kuò)展單元并取得了成功。為了充分發(fā)揮ISA總線(xiàn)的性能,對(duì)于ISA總線(xiàn)的訪(fǎng)問(wèn),我們除了提供最基本的設(shè)備驅(qū)動(dòng)API操作函數(shù)外,還先后增加了ISA總線(xiàn)的塊讀寫(xiě)操作方法和ISA總線(xiàn)的DMA操作方法。當(dāng)ISA總線(xiàn)以DMA方式進(jìn)行數(shù)據(jù)傳輸時(shí),在最大限度的利用ISA總線(xiàn)帶寬的同時(shí),又減少了ISA操作占用CPU的時(shí)間,所以利用DMA是進(jìn)行批量數(shù)據(jù)傳輸時(shí)的首選方式。
在實(shí)際的應(yīng)用中,除了成批量的數(shù)據(jù)訪(fǎng)問(wèn)外,也可能會(huì)存在對(duì)外設(shè)進(jìn)行頻繁的字或字節(jié)訪(fǎng)問(wèn)。英創(chuàng)主板的ISA總線(xiàn)周期通常在200ns左右,而應(yīng)用程序調(diào)用一次設(shè)備驅(qū)動(dòng)程序API(WriteFile,ReadFile)花費(fèi)的時(shí)間卻需要數(shù)微秒的時(shí)間,這顯然大大降低了對(duì)外設(shè)單字(或單字節(jié))的訪(fǎng)問(wèn)效率。為了解決這一問(wèn)題,我們利用了WinCE的虛擬地址映射技術(shù),在ISA驅(qū)動(dòng)程序中實(shí)現(xiàn)了在使用ISA的應(yīng)用進(jìn)程地址空間內(nèi)分配一段虛擬地址空間,并將其與ISA接口的物理地址空間進(jìn)行了綁定。簡(jiǎn)單來(lái)講就是實(shí)現(xiàn)了在WinCE應(yīng)用程序中可以直接訪(fǎng)問(wèn)ISA總線(xiàn)的外設(shè)地址空間,從使用的角度看,我們實(shí)現(xiàn)了以下5個(gè)函數(shù)。ISAMmMap用于獲得ISA總線(xiàn)的基地址,其余4個(gè)函數(shù)分別為字讀/寫(xiě)和字節(jié)讀/寫(xiě)操作函數(shù)。
|
HANDLE ISAMmMap(HANDLE hISA); // 映射ISA總線(xiàn)物理地址空間 BYTE ISARead8(HANDLE hMmMap, DWORD dwPortOffset); // 讀單字節(jié) void ISAWrite8(HANDLE hMmMap, DWORD dwPortOffset, BYTE ucValue); // 寫(xiě)單字節(jié) WORD ISARead16(HANDLE hMmMap, DWORD dwPortOffset); // 讀單字 void ISAWrite16(HANDLE hMmMap, DWORD dwPortOffset, WORD wValue); // 寫(xiě)單字 |
||
下面是上述5個(gè)函數(shù)實(shí)現(xiàn)的源代碼,在ISAMmMap函數(shù)中調(diào)用DeviceIoControl,通過(guò)IOCTL_VIRTUAL_COPY_EX命令獲取ISA總線(xiàn)的基地址。
|
// 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, //打開(kāi)“ISA1:”返回的Handler IOCTL_VIRTUAL_COPY_EX, // IOCTL命令碼 NULL,0, // 不使用輸入?yún)?shù) &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); } |
||
我們?cè)贓SM3352上,分別測(cè)試了利用地址映射方法直接訪(fǎng)問(wèn)ISA外設(shè)地址和調(diào)用設(shè)備驅(qū)動(dòng)API函數(shù)讀寫(xiě)ISA地址,測(cè)得的結(jié)果是當(dāng)進(jìn)行字(WORD)讀寫(xiě)時(shí),應(yīng)用程序直接訪(fǎng)問(wèn)ISA外設(shè)地址比調(diào)用設(shè)備驅(qū)動(dòng)API函數(shù)快10倍以上,當(dāng)時(shí)行字節(jié)(BYTE)讀寫(xiě)時(shí),應(yīng)用程序直接訪(fǎng)問(wèn)ISA外設(shè)地址比調(diào)用設(shè)備驅(qū)動(dòng)API函數(shù)快15倍以上。
下面是測(cè)試程序源代碼:
|
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 { 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 { 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 { 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 { 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上兩種訪(fǎng)問(wèn)方式的測(cè)試結(jié)果:

要實(shí)現(xiàn)應(yīng)用程序直接訪(fǎng)問(wèn)ISA外設(shè)地址空間需要更新ISA驅(qū)動(dòng)程序,需要的用戶(hù)可與英創(chuàng)聯(lián)系。
-
ISA
+關(guān)注
關(guān)注
0文章
57瀏覽量
44543 -
嵌入式主板
+關(guān)注
關(guān)注
7文章
6107瀏覽量
37154
發(fā)布評(píng)論請(qǐng)先 登錄
ISA(PC/104)總線(xiàn)信號(hào)時(shí)序簡(jiǎn)介
單片機(jī)P口接PCI/ISA數(shù)據(jù)總線(xiàn)
EM335x主板ISA總線(xiàn)的高級(jí)應(yīng)用
PCI9052總線(xiàn)接口芯片及其ISA模式應(yīng)用
ISA總線(xiàn)信號(hào)時(shí)序簡(jiǎn)介
ISA總線(xiàn)引腳定義
ISA總線(xiàn)接口定義
ISA總線(xiàn)原理
ISA插槽,什么是ISA插槽,ISA插槽外形圖
PCI9052總線(xiàn)接口芯片及其ISA模式應(yīng)用
ISA總線(xiàn)和Futurebus+總線(xiàn)
基于ISA總線(xiàn)的高速同步數(shù)據(jù)采集系統(tǒng)設(shè)計(jì)
英創(chuàng)信息技術(shù)精簡(jiǎn)ISA總線(xiàn)Linux編程–Part1
英創(chuàng)信息技術(shù)精簡(jiǎn)ISA總線(xiàn)WinCE編程簡(jiǎn)介
如何快速訪(fǎng)問(wèn)ISA總線(xiàn)端口
評(píng)論