0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何快速访问ISA总线端口

英创信息技术 作者:英创信息技术 2019-09-26 10:35 次阅读

精简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 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 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 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 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驱动程序,需要的用户可与英创联系。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • ISA
    ISA
    +关注

    关注

    0

    文章

    52

    浏览量

    43660
  • 嵌入式主板
    +关注

    关注

    7

    文章

    6064

    浏览量

    34605
收藏 人收藏

    评论

    相关推荐

    ISA(PC/104)总线信号时序简介

    ISA(PC/104)总线信号时序简介 1.0 ISA概况2.0 ISA文献2.1 ISA规范2.2 I
    发表于 05-25 01:13

    单片机P口接PCI/ISA数据总线

    RT当我单片机P口直接连接PCI/ISA数据总线的时候计算机启动时会不会出现数据总线占线情况而启动不了还是为了保险起见中间接244另:STM8单片/51单片机上电时端口默认是输入还是输
    发表于 08-01 11:09

    EM335x主板ISA总线的高级应用

    一次API调用对一个地址端口读写多个数据的操作。数据块读写能有效提高数据读写的效率,在数据采集传输中有广泛的应用。  要对ISA总线进行读写,首先需要打开设备文件“ISA1:”如下: 
    发表于 07-11 11:04

    PCI9052总线接口芯片及其ISA模式应用

    或I/O映射可直接使PCI总线ISA总线相连,从而将ISA总线快速地转换到PCI
    发表于 12-17 11:23

    ISA总线信号时序简介

    ISA总线信号时序简介:1.0 ISA概况2.0 ISA文献2.1 ISA规范2.2 ISA书籍
    发表于 05-21 11:06 242次下载

    基于ISA总线的虚拟万用表设计

    摘要:基于ISA总线的虚拟万用表,分计算机和ISA总线板卡两部分,由A/D转换、交变电压测量、电阻测量及接口电路组成。其主程序先完成系统初始化,再根据相应模式和档位,通过
    发表于 05-19 09:59 35次下载

    ISA总线引脚定义

    ISA总线引脚定义 ISA 是 Industry Standard Architecture 的缩写
    发表于 11-23 18:46 4789次阅读
    <b class='flag-5'>ISA</b><b class='flag-5'>总线</b>引脚定义

    ISA总线接口定义

    ISA总线接口定义     为16位系统总线ISA槽有98个脚,数据线有16条,地址线有27条,其余为控制信号线,接地线,电源线和时钟。其工作频率为
    发表于 05-31 14:17 5746次阅读

    ISA总线原理

    ISA总线的原理 ISA总线概况   ISA总线来源于IBM-PC微计
    发表于 12-09 11:22 8269次阅读
    <b class='flag-5'>ISA</b><b class='flag-5'>总线</b>原理

    ISA插槽,什么是ISA插槽,ISA插槽外形图

    ISA插槽,什么是ISA插槽,ISA插槽外形图 ISA插槽是基于ISA总线(Industria
    发表于 04-26 18:12 7022次阅读

    ISA总线和Futurebus+总线

    ISA总线和Futurebus+总线 ISA总线1. ISA
    发表于 05-21 11:15 2721次阅读
    <b class='flag-5'>ISA</b><b class='flag-5'>总线</b>和Futurebus+<b class='flag-5'>总线</b>

    EM9000下的ISA总线软件开发环境配置

    英创EM9000嵌入式模块保留了极具特色的精简 ISA总线 接口,用户可以利用该接口快速、便捷地与其他功能模块相连,以构成符合自己需要的应用平台。在不使用精简ISA
    发表于 06-09 15:42 22次下载
    EM9000下的<b class='flag-5'>ISA</b><b class='flag-5'>总线</b>软件开发环境配置

    英创信息技术ISA总线扩展定时器的应用介绍

    的应用方案也很简单、方便,一片82C54能扩展3路PWM信号输出。 基于英创公司的ARM9工控主板的ISA总线扩展82C54的连接图如下所示: 1、与ARM9工控主板评估套件的 ISA总线
    的头像 发表于 01-14 14:34 967次阅读
    英创信息技术<b class='flag-5'>ISA</b><b class='flag-5'>总线</b>扩展定时器的应用介绍

    英创信息技术精简ISA总线Linux编程–Part1

    精简ISA总线接口是一种8-bit宽度的双向并行扩展总线,其特点是地址数据分时复用8-bit总线,加上4条总线控制信号,即可实现对外部数据的
    的头像 发表于 02-07 11:19 950次阅读
    英创信息技术精简<b class='flag-5'>ISA</b><b class='flag-5'>总线</b>Linux编程–Part1

    英创信息技术精简ISA总线WinCE编程简介

    据线加上4条总线控制信号,即可实现对外部数据的快速读写,异步访问的最高速率在5MB/s左右。同步访问需要再使能一条总线时钟信号(共13条信号
    的头像 发表于 02-11 16:55 1048次阅读
    英创信息技术精简<b class='flag-5'>ISA</b><b class='flag-5'>总线</b>WinCE编程简介