我做了一块CAN通信板(PC/104模块的,在硬件设计上采用了一片CPLD作为CAN和PC/104总线之间的桥梁),以前做的就是那种I/O方式的,比如说我用的地址是0x220和0x221,整个测试程序就是inportb(0x220)、outportb(0x221,dat)起CAN和PC/104之间数据交换作用,现在要求改设计,改成内存映射方式,把SMEMR和SMEMW以及ALE都连接到了CPLD上了。现在我的问题是:一方面在CPLD上具体如何编写VHDL语言以便实现内存映射,另一方面是在如何编写TC下的内存映射程序,即怎么样编写才是内存映射方式而不是I/O方式?对内存映射我只知道是在内存区开辟一块内存用作存取数据用,其他的具体操作我就不知道了(注:PC/104总线完全兼容ISA总线)谢谢!
LLM 解释
一、TC下内存映射程序的编写方法
内存映射I/O的核心是将硬件寄存器映射到CPU的物理内存地址空间,通过直接读写内存地址而非in/out指令访问硬件。在TC中实现需以下步骤:
1. 关键前提:硬件物理地址分配
需先为CAN板分配一个未被系统占用的物理内存地址段(通常为ISA总线的内存映射区,如1MB以下的保留区或扩展内存,但需注意:ISA总线的内存映射地址需满足AEN=0且SMEMR#/SMEMW#有效,地址范围通常为0xC0000~0xFFFFF中的未使用区域,需避免与显存、BIOS、扩展卡ROM冲突)。假设分配的基地址为0xD0000(需与CPLD设计一致)。
2. TC中的实现方式
TC运行于实模式,默认只能直接访问640KB以下的常规内存,而ISA内存映射区多在640KB~1MB之间(0xA0000~0xFFFFF),属于保留内存区,需通过段地址+偏移地址的方式访问(实模式下物理地址=段地址×16+偏移地址)。
示例代码框架(假设基地址0xD0000,寄存器偏移为0x00和0x01):
#include <dos.h>
#include <mem.h>
// 硬件物理基地址(需与CPLD一致)
#define BASE_ADDR 0xD0000
// 转换为段地址:BASE_ADDR / 16 = 0xD000
#define HW_SEG 0xD000
// 内存映射寄存器指针(通过段地址+偏移访问)
unsigned char far *pReg0 = (unsigned char far *)MK_FP(HW_SEG, 0x00); // 对应物理地址0xD0000
unsigned char far *pReg1 = (unsigned char far *)MK_FP(HW_SEG, 0x01); // 对应物理地址0xD0001
void main() {
unsigned char data;
// 读寄存器0(替代inportb(0x220))
data = *pReg0;
// 写寄存器1(替代outportb(0x221, dat))
*pReg1 = 0x5A;
// 注意:若地址段被系统标记为"不可写",需先修改内存控制寄存器(如EMS芯片或系统BIOS设置),但实模式下通常无需额外配置,硬件会直接响应
}
3. 与I/O方式的核心区别
- I/O方式:用
inportb/outportb函数,对应CPU的IN/OUT指令,访问I/O地址空间(地址范围0x0000~0xFFFF)。
- 内存映射方式:用
far指针直接读写内存地址,对应CPU的MOV指令,访问物理内存地址空间,无需额外指令。
二、当年常见误解的澄清
当年很多开发者混淆“内存映射”与“常规内存”,错误认为需要在常规内存(640KB以下)中“开辟空间”,实际内存映射I/O的地址是硬件直接响应的物理地址,并非从系统内存中划分,CPU只是通过内存读写指令触发硬件操作。
三、CPLD设计的VHDL逻辑提示(非代码,仅原理)
CPLD需实现地址译码+读写控制,核心逻辑如下:
-
地址译码:根据ISA总线的地址线(A0~A19)、
AEN(需为0,标识非DMA周期)、SMEMR#/SMEMW#(内存读写使能),判断是否访问CAN板的映射地址。
-
读写控制:当地址匹配且
SMEMR#有效时,将硬件数据输出到ISA总线的数据线(D0~D7);当SMEMW#有效时,锁存总线数据到硬件寄存器。
-
ALE信号:用于锁存地址线与控制线,确保读写周期中地址稳定。
(注:具体VHDL代码需根据地址分配、寄存器数量调整,当年常见的错误是忽略AEN信号导致DMA周期误触发,或地址译码不完整导致与其他设备冲突。)
四、补充说明
PC/104总线兼容ISA总线,内存映射的硬件与软件逻辑完全遵循ISA规范,需注意:
- 内存映射地址需通过跳线或DIP开关设置,确保与系统中其他设备无冲突;
- 实模式下TC无法直接访问1MB以上的扩展内存,若硬件映射到扩展内存,需进入保护模式(但当年很少这么做,通常使用1MB以下的ISA保留区)。
当年的跟帖可能会提到“内存地址冲突检测工具”(如MEM命令或第三方硬件检测软件),这是验证地址是否可用的关键步骤,需优先确认硬件地址的唯一性。