精简ISA总线信号

英创公司的嵌入式主板产品,如ESM7000、ESM335x等,均配置有精简ISA总线接口,基本的精简ISA总线由8位地址数据总线(分时复用)+ 4条控制信号组成,通过异步操作的读写总线周期,来实现对外部逻辑单元的控制。精简ISA总线的最大优点是硬件接口简单、应用程序接口简单,读写速度可达4MB/s,特别适合在嵌入式系统中使用。实现主板与用户专用接口电路的控制与数据传输。

精简ISA总线核心的12条信号线定义如下:

信号名称

信号功能简要说明

ISA_AD0

地址数据总线,LSB

ISA_AD1

地址数据总线

ISA_AD2

地址数据总线

ISA_AD3

地址数据总线

ISA_AD4

地址数据总线

ISA_AD5

地址数据总线

ISA_AD6

地址数据总线

ISA_AD7

地址数据总线,MSB

ISA_RDn

总线数据读控制信号,低电平有效

ISA_WEn

总线数据写控制信号,低电平有效

ISA_ADVn

总线地址锁存控制信号,低电平有效

ISA_CSn

总线周期片选控制信号,低电平有效

上表的12条信号直接从ESMARC主板引出,再配置上总线复位信号和中断信号(通常由主板的GPIO信号来实现),就可驱动各种接口单元了。

精简ISA总线时序

基本的总线时序包括读总线周期和写总线周期。以下时序来自ESM7000嵌入式主板的精简ISA总线,ESM335x的精简ISA总线时序也完全同样的,其扩展外设逻辑电路可直接互换。

bios 内存时序 tcl_linux

 

异步读总线周期时序

bios 内存时序 tcl_嵌入式硬件_02

异步写总线周期时序

 

对异步读写操作,一个完整的读写操作时间包括上述的总线操作周期和总线周期间隔,大约在240ns – 250ns,对应着4MB/s – 4.2MB/s的数据读写速度。锁存的地址也是8-bit,对应精简ISA总线的寻址能力是256个8-bit寄存器,这对绝大多数嵌入式应用已足够使用。

WinCE平台编程方法

ESM7000和ESM335x均支持Windows CE平台(WEC7),对精简ISA总线配置了相应的驱动程序。用户的应用程序只需通过对其驱动程序进行操作,即可实现对ISA总线的读写操作。为方便应用调用,封装了几个基本操作函数:

HANDLE  ISA_Open( LPCWSTR lpDevName )
{
    return 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);   
}


BOOL    ISA_Close( HANDLE hISA)
{
    return CloseHandle( hISA );
}


BOOL    ISA_ReadUchar(HANDLE hISA, DWORD dwPortOffset, PBYTE pBuf)
{
    DWORD dwBufSize = sizeof(BYTE);
    DWORD dwNbBytesRead = 0;

    *pBuf = (BYTE)(dwPortOffset & 0xFF);
    return ReadFile(hISA, pBuf, dwBufSize, &dwNbBytesRead, NULL);
}


BOOL    ISA_WriteUchar(HANDLE hISA, DWORD dwPortOffset, BYTE ucValue)
{
    WORD  wValue;
    DWORD dwBufSize = sizeof(WORD);
    DWORD dwNbBytesWritten = 0;

    wValue = (WORD)(dwPortOffset & 0xFF);
    wValue = (wValue << 8) | ucValue;
    return WriteFile(hISA, &wValue, dwBufSize, &dwNbBytesWritten, NULL);
}


BOOL    ISA_ReadWord(HANDLE hISA, DWORD dwPortOffset, WORD* pBuf)
{
    DWORD dwBufSize = sizeof(WORD);
    DWORD dwNbBytesRead = 0;

    *pBuf = (WORD)(dwPortOffset & 0xFE);
    return ReadFile(hISA, pBuf, dwBufSize, &dwNbBytesRead, NULL);
}


BOOL    ISA_WriteWord(HANDLE hISA, DWORD dwPortOffset, WORD wValue)
{
    DWORD dwValue;
    DWORD dwBufSize = sizeof(DWORD);
    DWORD dwNbBytesWritten = 0;

    dwValue = (dwPortOffset << 16) | wValue;
    return WriteFile(hISA, &dwValue, dwBufSize, &dwNbBytesWritten, NULL);
}

打开设备文件Handle

HANDEL hISA = ISA_Open( _T("ISA1:"));
if( hISA == INVALID_HANDLE_VALUE) {
    // error processing
}

读操作

DWORD   dwPortOffSet = 0;  // 0x00 .. 0xFF
    BYTE    ucValue;
    WORD    wValue;
    BOOL    bRet;


    // read a byte
    bRet = ISA_ReadUchar(hISA, dwPortOffSet, &ucValue);

    // read a word
    bRet = ISA_ReadWord(hISA, dwPortOffSet, &wValue);

写操作

DWORD   dwPortOffSet = 0;  // 0x00 .. 0xFF
    BYTE    ucValue = 0x55;
    WORD    wValue = 0x55aa;
    BOOL    bRet;

    // write a byte
    bRet = ISA_WriteUchar(hISA, dwPortOffSet, ucValue);

    // write a word
    bRet = ISA_WriteWord(hISA, dwPortOffSet, wValue);

关闭设备文件Handle

ISA_Close(hISA);

Linux平台编程方法

ESM7000和ESM335x均支持Linux平台(Linux-4.x.x),对精简ISA总线配置了相应的驱动程序。在为用户的应用程序封装的函数中,除支持常规的端口读写外,同时支持了Linux特有的mmap操作,以提高读写速度。封装函数如下:

unsigned char *isa_base = NULL;
unsigned int  map_size = 4096;

// return >= 0: return file handle
// return < 0: return failed code
int isa_open()
{
    int fd;

    fd = open("/dev/em_isa", O_RDWR);
    if(fd < 0) {
        return fd;
    }

    isa_base = (unsigned char*)mmap(0,map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (isa_base == MAP_FAILED) {
        printf("%s mmap failed\n", __func__);
        isa_base = NULL;
        close(fd);
        return -1;
    }

    return fd;
}


int isa_close(int fd)
{
    if(isa_base != NULL) {
        munmap(isa_base, map_size);
        isa_base = NULL;
    }

    return close(fd);
}


// offset: port address in isa bus
unsigned char isa_read(int fd, unsigned int offset)
{
    unsigned char val_b;
    int           rc;

    offset &= 0xff;
    if(isa_base != NULL) {
        unsigned short int val_w;

        val_w = *((unsigned short int*)(isa_base + (offset << 1)));
        val_b = (unsigned char)(val_w & 0xff);
        return val_b;
    }

    val_b = offset;
    rc = read(fd, &val_b, sizeof(unsigned char));
    if(rc < 0) {
        // read error
        printf("%s failed %d\n", __func__, rc);
    }

    return val_b;
}


// offset: port address in isa bus
void isa_write(int fd, unsigned int offset, unsigned char val_b)
{
    unsigned short int val_w;
    int                rc;

    offset &= 0xff;
    if(isa_base != NULL) {
        val_w = val_b;
        *((unsigned short int*)(isa_base + (offset << 1))) = val_w;
        return;
    }

    val_w = ((offset & 0xff) << 8) | val_b;
    rc = write(fd, &val_w, sizeof(unsigned short int));
    if(rc < 0) {
        // write error
        printf("%s failed %d\n", __func__, rc);
    }
}


// offset: port address in isa bus
unsigned short int isa_read16(int fd, unsigned int offset)
{
    unsigned short int val_w;
    int                rc;

    // 2-byte alignment is required for offset
    offset &= 0xfe;

    if(isa_base != NULL) {
        unsigned int val;
        val = *((unsigned int*)(isa_base + (offset << 1)));
        val_w = (unsigned short int)((val >> 8) | (val & 0x00ff));
        return val_w;
    }

    val_w = (unsigned short int)offset;
    rc = read(fd, &val_w, sizeof(unsigned short int));
    if(rc < 0) {
        // read error
        printf("%s failed %d\n", __func__, rc);
    }

    return val_w;
}


// offset: port address in isa bus
void isa_write16(int fd, unsigned int offset, unsigned short int val_w)
{
    unsigned int val;
    int          rc;

    // 2-byte alignment is required for offset
    offset &= 0xfe;

    if(isa_base != NULL) {
        val = val_w;
        val = ((val << 8) & 0x00ff0000) | (val & 0x000000ff);
        *((unsigned int*)(isa_base + (offset << 1))) = val;
        return;
    }

    val = (offset << 16) | val_w;
    rc = write(fd, &val, sizeof(unsigned int));
    if(rc < 0) {
        // write error
        printf("%s failed %d\n", __func__, rc);
    }
}

打开设备文件Handle

//open file
int fd = isa_open();
if(fd < 0) {
   //open file failed
   printf("open file = %d\n", fd);
   return fd;      
}

读操作

unsigned int offset = 0x00;
    unsigned int value;

    // read a byte
    value = isa_read(fd, offset);

    // read a word
    value = isa_read16(fd, offset);

写操作

unsigned int offset = 0x00;
    unsigned int value = 0x55aa;

    // write a byte, lower byte
    value = isa_write(fd, offset, value);

    // write a word
    value = isa_write16(fd, offset, value);

关闭设备文件Handle

isa_close(fd);