内存映射的I / O和编程的I / O之间的区别

lau*_*ura 5 computer-science cpu-architecture

在研究计算机体系结构时,我了解了控制I / O设备的不同方法,

  1. 编程的I / O
  2. 中断I / O
  3. DMA

我学习了所有三种方法。
但是我遇到了另一个术语“ 内存映射I / O”

编程I / O和内存映射I / O之间有什么关系 ?
我对这两个感到困惑。它们相似吗?

Mar*_*oom 5

这些术语大多是独立的,而不是相互排斥的。
下面我将使用伪汇编代码使示例更清晰,它是演示代码,不是真正的代码。

如何访问设备?

如果设备可在专用地址空间中访问,与地址空间或内存分开,则 IO 的类型称为端口映射 IO隔离 IO

如果设备可作为唯一地址空间的一部分访问,内存也位于该地址空间,则 IO 的类型称为内存映射 IO

例如一些嵌入式控制器和一些主流架构有特殊的指令来访问 IO 地址空间。

in r0, 0x34          #Read address 0x34 from IO address space
ld r0, 0x34          #Read address 0x34 from memory address space
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,两个地址 0x34 生成两个不同的总线地址,然后以不同的方式处理。
请注意,ld指令的类型与用于访问内存的指令类型相同,因此例如ld r1, 0x1000可以访问内存而不是设备。

如何从设备中读取数据?

这也适用于将数据写入设备。

如果软件被强制显式读取数据的每个字节/字,则 IO 的类型被编程为 IO

如果可以告诉设备启动操作并将数据自动传输到内存,那么 IO 的类型是Direct Memory Access IO

例如,要从磁盘读取一个扇区,比如说 512 字节,软件可以

#Setup read parameters omitted

movi r0, $0x20      #r0 = 0x20 (say it's READ_SECTORS command)
out 0x102, r0       #Tell the device to start reading

movi r1, 512 / 4    #r1 = number of words in a sector
_read:
 in r0, 0x103        #Read a word (32-bit)
 ...
 decbnz r1, _read        #Decrement r1 and branch back if not zero
Run Code Online (Sandbox Code Playgroud)

使用 DMA 可以执行相同的读取

#Setup read parameters omitted

movi r0, $0x21      #r0 = 0x21 (say it's READ_DMA_SECTORS command)
out 0x102, r0       #Tell the device to start reading

#Done, the software can do something else
Run Code Online (Sandbox Code Playgroud)

我如何获得事件通知?

操作完成和新数据到达是软件可能希望收到通知的两个事件示例。

如果设备使用中断来通知 CPU 一个事件,则 IO 的类型称为中断驱动 IO

如果设备只有一个状态寄存器,软件必须定期检查该寄存器,则 IO 的类型称为轮询 IO

例如,检查 UART 是否有新数据,软件可以使用中断

#Setup isr
la r0, myISR
call setup_isr

#Example of device configuration

in r0, 0x100
or r0, 0x80
out 0x100, r0        #Set bit7 to enable generation of interrupt

#Done, myISR is called whenever new data arrives
Run Code Online (Sandbox Code Playgroud)

如果 IO 正在轮询,则软件必须定期检查

_check_data:
 in r0, 0x102              #Say 102 is a status resister
 btbz r0, 7, _check_data   #Test if bit7 of r0 is set, if not jump back

 #New data is available
Run Code Online (Sandbox Code Playgroud)

因此,例如 IO 可以是内存映射 DMA 中断驱动的 IO
这实际上是 PCI(e) 设备在 x86 架构上通常使用的。

有关端口映射 DMA 中断驱动 IO(读取样本时)和端口映射编程轮询 IO(向 DSP 发出命令时)的真实示例,您可以查看我关于对声卡进行编程以播放波形文件的回答


小智 1

有两种不同的方法来寻址 I/O 设备。1.隔离I/O——会有专门的I/O操作指令。- 与内存相比,I/O 设备在单独的域中处理。- 总共允许1mb的地址空间用于内存申请。- 为了最大化 I/O 操作(隔离),始终提供单独的指令来执行这些操作。-.缺点之一是数据传输仅发生在I/O端口和AL、AX寄存器之间。

2.内存映射I/O——在此汇编语言程序中可以对I/O设备进行寻址。- I/O 设备仅被视为内存的一部分。-完整的1MB内存不能被使用,因为它们是内存的一部分。- 在内存映射 I/O 操作的情况下,不需要外部单独的指令。-内存映射指令存在数据传输限制。- 内存映射 I/O 的优点是它使指令集保持较小。