Overview
在介绍 PCI 总线之前,我们先看下 CPU 对 EMMC 是如何访问?
假设 SoC 中有个 EMMC 控制器,控制器后面接入一个内存(存储范围)很大EMMC,当CPU想去访问 EMMC FLash 中的内容时,CPU 只能先将要访问的地址发到 EMMC 控制器上 而不是直接访问EMMC 中的地址,CPU 发出的地址属于 CPU 地址空间的,而EMMC Controller 发出的地址属于 EMMC 地址空间的,它们两个是不相等的。
所以在访问 EMMC Flash 的过程中都是通过软件的驱动程序来进行的,在驱动程序中 CPU 通过读写 EMMC Contorller 来让EMMC 发出读写信号来读写 EMMC 中的Flash, 根本原因就是 EMMC 中的地址空间和 CPU 地址空间是隔离的。所以这个时候就有个需求:CPU 发出的地址是否可以直接到达 EMMC Flash 中。这个就是PCI 的做法,如下图所示:
CPU 发出的地址直接转换为 PCI/PCIe 地址空间中的地址,当 CPU 去读写某个地址时,PCI/PCIe 控制器会将CPU发出的地址转化为 PCI/PCIe 地址空间中的某个地址,用这个地址去读取PCIe/PCIe 设备,得到数据之后再一路返回给CPU。这样对于软件来说就省了很多事情,不必去写复杂的驱动程序,也通过硬件的设计来减少软件的工作量。
接下来就是CPU 如何知道 PCI/PCIe 设备的地址?
每个PCI/PCIe 设备都会有一段配置空间,在配置空间中 PCI/PCIe 设备会去声明需要多大的地址空间,Host 主机会去读取PCIe 配置空间中的信息,获取它需要的地址空间大小,然后给它分配。
假设 PCIe 配置空间有32位地址线,也即 0-4G的地址空间,某个PCI/PCIe 设备需要1M的地址空间大小,那么就可以从PCIe 4G的地址空间中分配出来1M大小,比如位 0x0-0xFFFFF
, 然后可以将这段空间的起始地址和长度写入到 PCIe 设备的配置空间中,这个时候就出现了一个问题:CPU 需要访问CPU 地址空间的那一段地址才能访问到 PCIe 地址空间的 0x0-0xFFFFF
这段地址呢? 这个问题解决是通过设置PCI/PCIe 控制器进行一个地址空间的转换,通常是将CPU 地址空间的偏移值和PCIe 地址空间的偏移值配置到PCIe controller 中的寄存器即可。
当CPU 发出一个地址,这个地址属于某个 PCIe 设备时,这时会选中PCIe 控制器,PCIe 控制器会把CPU发出来的地址加上偏移值得到PCI地址空间的地址,然后把得到的地址通过PCIe/PCI 总线发给对应的PCI/PCIe 设备,PCI/PCIe 设备会检测PCI总线或者PCIe 总线上的信号,但它发现PCI/PCIe 总线上的地址属于自己的范围时,它就会进行回应。
PCI 插槽上有哪些信号呢?
在 PCI 地址空间中,地址线和数据线是复用的, 如下图的 AD 信号,
那么如何区分PCI 插槽上的信号时地址还是数据呢?
是通过 FRAM 信号来进行区分的?
PCIe Interface
PCI 接口使用的并行信号,当速率达到一定程度时,它们之间会有相互的干扰,所以在传输速率到达一定程度时就选择使用穿行接口了,也即 PCIe 接口,它使用的时差分信号。
如下图所示,cpu 通过地址线和data线来访问 PCIe 控制器,PCIe 控制器来控制差分信号给PCIe 设备发送数据或者接收数据,把CPU 发过来的 addres 和 data 进行转换,然后使用串行的信号发给PCIe 设备,设备接收端也是使用两条差分信号进行接收,串行信号会把地址和数据放到一块,PCIe controller 会进行解码,解码完成后会发给CPU。
对于软件来说 PCIe 或者 PCI 总线都是一样的,它们都是兼容的,软件程序只是去访问某个地址。
接下来会继续介绍 PCI 总线是如何通过PCI Bridge 选中 PCI 设备的,PCIe 总线通过 PCIe Bridge 是如何选中 PCIe 设备的?
推荐阅读:
https://blog.csdn.net/qq_27846717/article/details/123153459