4、ZYNQ PS外设GPIO之MIO/EMIO
1、ZYNQ PS外设简介
ZYNQ PS 中包含一组丰富的外设,如 USB 控制器、 UART 控制器、 I2C 控制器以及 GPIO 等等,他们提供了各种工业标准的接口, 用于和外部设备进行通信。
ZYNQ 分为 PS 和 PL 两部分,那么器件的引脚( Pin)资源同样也分成了两部分。 ZYNQ PS 中的外设可以通过 MIO( Multiuse I/O,多用输入/输出)模块连接到 PS 端的引脚上,也可以通过 EMIO 连接到 PL端的引脚。
PS MIO 一般会分配到固定的外设, 包括 FLASH、 EMMC、 TFCARD、 UART、 USB2.0、 ETH 以太网等,也可以单独配置成普通的 GPIO。 如果 IO 不够用也可以通过 EMIO 扩展更多 IO,对于 ZYNQ 最多支持扩展 64 个EMIO。
ZYNQ PS 部分的 IO 包括 PS-MIO 和 PS-EMIO,PS-MIO 的 IO 位置是固定好的, 功能也是预先定义好了, 而 PS-EMIO 是通过把芯片内部 PS 的 PS-EMIO 引线接到了 PL 部分的 FPGA Pin 脚上。
MIO分配在bank0和bank1直接与PS部分相连, EMIO分配在bank2和bank3 和PL部分相连。除了bank1是22-bit之外,其他的 bank 都是 32-bit。所以 MIO 有 54 个引脚可供我们使用,而 EMIO 有 64 个引脚可供我们使用。使用 EMIO 的好处就是,当 MIO 不够用时, PS 可以通过驱动 EMIO 控制 PL 部分的引脚。
Zynq7000 系列芯片有 54 个 MIO(multiuse I/O),个别芯片如 7z007s 只有 32 个,它们分配在 GPIO 的 Bank0 和 Bank1 隶属于 PS 部分,这些IO 与 PS 直接相连,不需要添加引脚约束。
MIO 信号对 PL 部分是透明的,不可见,所以对 MIO 的操作可以看作是纯PS 的操作。
在实际的应用中 PS-MIO 主要满足必要常用的外设 IO 需求, 比如串口、 SDIO、 以太网等, 而 PS-EMIO 按需配置, 用多少, 配置多少。
PS 的 54 个 MIO 与 PS 直接相连。 不需要添加 FPGA 的引脚约束, 对于 EMIO 是通过 FPGA 的 IO 扩展的, 除了需要对 PS 的 ZYNQ IP 设置, 还需要绑定到 FPGA 的引脚, 所以需要对 EMIO 做 IO 引脚约束。
2、ZYNQ PS外设GPIO
GPIO 是英文“general purpose I/O”的缩写,即通用的输入/输出。它是 ZYNQ PS 中的一个外设,用于观测和控制器件引脚的状态。
GPIO 外设一般用于控制一些简单的外设,如LED 和蜂鸣器,此时 GPIO 用作输出;也可以用于观测一些简单外设的状态,如按键,此时 GPIO 用作输入。
下图是GPIO 的框图,从中我们可以看到 GPIO 分为 4 个 Bank,其中 Bank0和 Bank1 连接到 MIO;而 Bank2 和 Bank3 连接到 EMIO。
除 Bank1 之外的 Bank 都具有 32bit, Bank1 只具有 22bit 是因为总共只有 54 个 MIO,其中 32bit 的 Bank0控制了 MIO[0~31],剩下的 MIO[31~53]就由 22bit 的 Bank1 控制。 Bank2 和 Bank3 用于控制扩展的 MIO 即EMIO,也就是说总共可以有 32+32=64 个 EMIO。
GPIO 的控制和状态寄存器基地址为: 0xE000_A000, SDK 软件底层操作是对于内存地址空间的操作。
EMIO 的使用和 MIO 的使用其实是非常相似的。区别在于, EMIO 的使用相当于 PS + PL 的结合使用。所以, EMIO 需要分配引脚,以及编译综合生成 bit 文件。
在大多数情况下, PS 端经由 EMIO 引出的接口会直接连接到 PL 端的器件引脚上, 通过 IO 管脚约束来指定所连接 PL 引脚的位置。 通过这种方式, EMIO 可以为 PS 端实现额外的 64 个输入引脚或 64 个带有输出使能的输出引脚。 EMIO 还有一种使用方式,就是用于连接 PL 内实现的功能模块( IP 核) , 此时 PL 端的 IP 作为 PS 端的一个外部设备。 如图 3.1.2 所示:
PS-MIO:
Bank0:MIO[31:0] GPIO PIN 脚号: MIO31~MIO0
Bank1:MIO[53:32] GPIO PIN 脚号: MIO53~MIO32
PS-EMIO:
Bank2:EMIO[ 0:31] 可以分配到任意的 FPGA IO
Bank3:EMIO[32:63] 可以分配到任意的 FPGA IO
所以 PS-MIO 和 EMIO 最多 118 个 IO 可用
Bank0:MIO [31:0] GPIO PIN 脚号: 0~31
Bank1:MIO[32:53] GPIO PIN 脚号: 32~53
Bank2:EMIO [31 : 0] GPIO PIN 脚号: 54~85
Bank3:EMIO [63:32] GPIO PIN 脚号: 86~ 117
PS 所有的外设都可以通过 MIO 访问,这些外设也是与 MIO 进行连接,每个 MIO 虽然可以独立控制,以及独立驱动单个引脚的外设,但对于 QSPI、 USB、以太网等这些外设,其于 MIO 的连接有着特殊的要求,如图 2.1.2 所示,(图中灰色框表示在 CLG225 封装的芯片中不可用)对于以太网而言,其只能与 MIO16~27和 MIO28~39 引脚连接,而且以太网与 MIO28 连接的引脚只能作为以太网的 tx_clk 使用,可见当其作为以太网的接口引脚时,相应的 MIO 的功能就已经确定下来了。 MIO 还有一特点,如 MIO28~39 引脚即可以与以太网进行连接,也可以作为 USB 以及其它外设的接口引脚,所以当我们设计 PS 的外设时要合理分配 MIO。从图 2.1.2 MIO 一览表中我们可以看到 MIO 一但选定,引脚位置就已经确定下来了,不需要添加引脚约束。
通过图 2.1.2 我们了解到了 MIO 与外设的连接情况,例如当我们想要两个 MIO 作为 UART 的接口时,可以使用 MIO8、 9 或者 MIO10、 11 等引脚,如果选用 MIO8、 9 作为 UART 的接口, MIO8 就是 UART 的tx 引脚, MIO9 为 rx 引脚。那么 MIO 与 PS 是怎么连接的呢?
图 2.1.3 展示了 MIO 与 PS 的连接。 MIO 的 PS 外设的大多数 I/O 信号( USB 除外)可以通过 MIO 路由到 PS 引脚,或通过 EMIO 路由到 PL 引脚。除千兆以太网外,大多数外设还在 MIO 和 EMIO 之间保持相同的协议。千兆以太网为减少引脚数,使用 4 位的 RGMII 接口以 250 MHz 数据速率( 125 MHz 时钟,双倍数据速率)通过 MIO。如果接到 EMIO,就使用一个以 125 MHz 数据速率运行的 8 位 GMII 接口。需要注意的是 Quad-SPI、 USB 和 SMC 接口不适用于 PL 的 EMIO 接口。
这里我们重点介绍图 2.1.3 I/O 外设系统图中箭头所指的部分。从该图中我们可以看到 PS 通过 APB 总线对控制、状态寄存器的读写实现对 GPIO 的驱动,具体可以参见下图。
图左边的一列是寄存器,上半部分是关于中断的,这部分我们在涉及到中断的时候会讲解,这里我们重点介绍下红色框圈出的下半部分。
DATA_RO 是数据只读寄存器,通过该寄存器能够观察器件引脚上的值。如果 GPIO 信号配置为输出,则通常会反映输出上驱动的值,写入此寄存器将被忽略。
DATA 是数据寄存器,该寄存器控制 GPIO 信号配置为输出时要输出的值。该寄存器的所有 32 位都是一次写入的。读取该寄存器返回写入 DATA 或 MASK_DATA_ {LSW, MSW}的先前值,它不会返回器件引脚上的当前值。
MASK_DATA_LSW 和 MASK_DATA_MSW 是数据掩码寄存器,该寄存器使软件能够有选择地一次更改所需的的输出值。可以写入最多 16 位的任意组合, MASK_DATA_LSW 控制 Bank 的低 16 位,MASK_DATA_MSW 控制高 16 位。未写入的那些位保持不变并保持其先前的值。读取该寄存器返回写入DATA 或 MASK_DATA_ {LSW, MSW}的先前值;它不会返回器件引脚上的当前值。该寄存器避免了对未更改位的读-修改-写序列的需要。
DIRM 是方向模式寄存器,用于控制 I/O 引脚是用作输入还是输出。当 DIRM [x] == 0 时,输出驱动器被禁用,该引脚作为输入引脚使用。
OEN 是使能输出寄存器。将 I/O 配置为输出时,该寄存器控制是否启用输出。禁用输出时,引脚为 3态。当 OEN [x] == 0 时,输出被禁用。
从这些寄存器中我们可以看到,如果配置引脚为输出,不仅需要设置方向,还要使能输出。关于这些寄存器的具体介绍,可参考 ug585 手册的 Appx.B:Register Details 中的 General Purpose I/O (gpio)一节。需要说明的是我们在程序中操作 MIO 时直接调用 Xilinx 官方提供的函数即可,无需直接操作这些寄存器。
另外需要说明的是 MIO 信号对 PL 部分是透明的,所以对 MIO 的操作是纯 PS 的操作,且每个 GPIO都可独立动态编程为输入、输出或中断检测,此处需要注意的是 MIO7 和 8 只能做为输出 IO 使用。