版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zhoutaopower/article/details/114557387
1、MIO 配置以及寄存器
Zynq 7020 的 PS 端(ARM 端)的外设 IO(也叫 IOP)分为 MIO 和 EMIO,他们有什么区别呢?
首先他们都是 PS 端的 IO 资源,MIO 有 54 个 Pin 脚,分为两个 Bank(Bank0、Bank1)是 PS 直接的管脚连接,可以接诸如 UART、SPI、IIC、GPIO 等具体的外设引脚;
EMIO 也是 PS 的资源,它接到了 PL 端,由 PL 端输出信号;
这里,我们可以简单的理解为,MIO 是可以通过 Pinmux 配置而直接连接到 PS 端外设的管脚,而 EMIO 是连接到 PL 端用于扩展的引脚;
外设的 MIO/EMIO 的链接如下所示:
这里,我们暂时只关心 MIO(后续看 EMIO),MIO 分为了两个 Bank(Bank0、Bank1),这两个 Bank 分别叫做 Bank 500 和 Bank 501,他们可以配置为不同的电压等级;
注意,这个是电压等级的 Bank,与后面的 GPIO bank 作区分;
Bank 500:MIO[15:0]
Bank 501:MIO[16:53]
提供 54 个 MIO 资源;
根据管脚复用的配置以及外设相关的资源,整个可实现的配置如下所示
MIO 的管脚复用配置逻辑如下所示:
每一路的 MIO(从 MIO[0] ~ MIO[53])都有一个这样的逐级配置,L3 的 MUX 结果可以作为 L2 MUX 的输入......最后配置出来成为最后的管脚;
举个例子,直接看寄存器;
MIO 配置的寄存器位于系统控制寄存器 slcr:
在 slcr 中:
很多类似这样的寄存器:slcr.MIO_PIN_[PIN_MUN] 其中的 PIN_MUN 就是每个 MIO 的编号,从 0 到 53,一共 54 个;
每一个的寄存器内容大致一样,我们随便抓一个看:MIO_PIN_00:
可以看到,每个 MIO 都可以配置是否上拉,电平标准(同一个 Bank 500 或者 Bank 501 电平标准必须一致),还有就是 Level 0 ~ Level 3 的 MUX,这个就是对应的上面那个 4 级 MUX 图的;
DisableRcvr:HSTL 的配置,是 High Speed Transceiver Logic 的简写,这个域是配置 MIO 的 HSTL 的;
PULLUP:配置 Piin 脚是否带上拉;
IO TYPE:配置 IO 的电平标准;
Speed:配置速度;
L3_SEL:配置管脚复用 L3 逻辑,参考管脚复用的 MIO Signal Routing 那个图;
L2_SEL:配置管脚复用 L2 逻辑,参考管脚复用的 MIO Signal Routing 那个图;
L1_SEL:配置管脚复用 L1 逻辑,参考管脚复用的 MIO Signal Routing 那个图;
L0_SEL:配置管脚复用 L0 逻辑,参考管脚复用的 MIO Signal Routing 那个图;
TRI_ENABLE:用于配置 MIO 是否三态;
注意:这个是 slcr 寄存器的配置,关于所有 slcr 寄存器的配置,都需要往 slcr.SLCR_UNLOCK 寄存器(0xF8000008)写入 0xDF0D,来解锁 slcr 寄存器的写权限;
2、工程中的配置
具体工程中,我们使用 Vivado 进行配置,首先创建 Block Design 来生成一个 PS:
双击这个大的 ZYNQ 图标,进入配置界面:
选择红色部分,并配置每个 IO 的管脚复用,并选择好他的电平标准(绿色);
配置时钟,板载 33.333333 MHZ,使用 6:2:1 时钟比例(参考 ZYNQ 时钟子系统)
配置完毕,并导出硬件,Launch SDK;
3、使用 MIO-GPIO
硬件原理图中 PS 端的 LED 连接如下:
分别使用了 MIO0_LED 和 MIO13_LED,都属于 Bank 500(V3.3),此刻,我们如果想点个灯,那么需要将其配置为输出,并置 0 即可导通;
3.1、GPIO 硬件描述
UG585 的 Chapter 14 就是 PS 的 GPIO 的使用说明(这里包含了 MIO 和 EMIO,这一章,我们看 MIO)
它支持 MIO 和 EMIO 的配置,MIO 分为 2 个 IO Bank (0~1),EMIO 也分为 2 个 IO Bank(2~3):
GPIO 支持中断输入和正常的写和读:INT 开头的,是中断配置:
针对每一个pin,它都有如下寄存器:
注意:如果 MIO 的 TRI_ENABLE 这个被设置为 1,那么输出就为 3 态了;
3.2、GPIO 寄存器描述
每个 GPIO Bank 提供了一组寄存器用来描述他的行为,一共 4组,我们以 GPIO Bank 0 为例:
GPIO Bank 0 一共有 32bits 根信号;
3.2.1、MASK_0_LSW、MASK_0_MSW
Zynq 针对 GPIO 的操作,增加了一组方式,以避免对 32bit 寄存器进行读改写的操作,它的方式是将(以 GPIO Bank0 为例)的 32bit 的信号(对应 32 个 IO)分为两组,每组代表 16 bits 的 IO 信号,用两个寄存器描述:
高 16 位使用叫 MASK_0_MSW 的寄存器描述:低位 16 位使用叫 MASK_0_LSW 的寄存器描述:
他们分别有两个域,一个 Mask 域,一个 Data 域,Zynq 使用 MASK + DATA 的方式,来避免对 GPIO 寄存器的读改写;用法是:
往 Mask 中写入 1 的位置,不会被对应的 Data 中的写入改变;换句话来说,16 bit 信号中,可以选择哪些信号被 Mask,Mask 中被写入了 1 的信号,即便是 在 Data 域写入任何值, GPIO 的电平状态都不会被改变;举个栗子:
往 MIO[0] 写 1,那么就可以配置寄存器 MASK_0_LSW 寄存器的值为:0xFFF70001;
意思是,除了 MIO GPIO0 以外的其他的 1~15 都被 Mask,你往里面写什么,都无效;
3.2.2、Data_0
当然,你也可以使用读改写的方式来对 IO 进行配置,直接配置 Data_0 寄存器就可以(以 GPIO Bank0 为例):
3.2.3、Data_0_RO
当然,也可以读 GPIO 的电平值,通过直接读取 Data_0_RO 寄存器(以 GPIO Bank0 为例):
3.2.4、DIRECTION_0
GPIO 呢,当然要配置它的方向,即,输入还是输出(以 GPIO Bank0 为例):
3.2.5、OP_ENABLE_0
如果 GPIO 配置为输出了后,要真的输出信号,要配置这个输出使能寄存器(以 GPIO Bank0 为例):
3.2.6、INT_
这个是 IO 输入中断相关的配置以后用到中断在仔细介绍;
3.3、代码
Xilinx SDK 关于 GPIO 的操作,有专门的 API 接口(其实就是按照前面的寄存器配置逻辑来配置),按照具体的硬件原理图的 LED(MIO_0 和 MIO_13),代码如下:
XGpioPs Gpio;
#define STEPH_MIO_0 0
#define STEPH_MIO_1 13
#define MIO_OUTPUT 1
#define MIO_INPUT 0
#define MIO_OUTPUT_EN 1
#define MIO_OUTPUT_DIS 0
uint32_t Steph_LEDInit(void)
{
XGpioPs_Config *ConfigPtr = NULL;
int Status = XST_SUCCESS;
ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
if(!ConfigPtr)
{
xil_printf("XGpioPs_LookupConfig Error.\r\n");
return XST_FAILURE;
}
Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr,
ConfigPtr->BaseAddr);
if (Status != XST_SUCCESS) {
xil_printf("XGpioPs_CfgInitialize Error.\r\n");
return XST_FAILURE;
}
XGpioPs_SetDirectionPin(&Gpio, STEPH_MIO_0, MIO_OUTPUT);
XGpioPs_SetDirectionPin(&Gpio, STEPH_MIO_1, MIO_OUTPUT);
XGpioPs_SetOutputEnablePin(&Gpio, STEPH_MIO_0, MIO_OUTPUT_EN);
XGpioPs_SetOutputEnablePin(&Gpio, STEPH_MIO_1, MIO_OUTPUT_EN);
xil_printf("Steph_LED Initialize Finished...\r\n");
return Status;
}
void LED_ON(uint32_t led_pin)
{
XGpioPs_WritePin(&Gpio, led_pin, 0x0);
}
void LED_OFF(uint32_t led_pin)
{
XGpioPs_WritePin(&Gpio, led_pin, 0x1);
}
相关代码和工程在 gitee 持续更新:https://gitee.com/stephenzhou-tech/Zynq7020_PS