赞
踩
目录
前面说过 PS 端可以使用 EMIO 来映射 IO,进而使用到 PL 端的 IO 口,另外一种办法就是使用 AXI 总线互联,在 PL 端实现一个逻辑,通过 AXI 总线进行配置和访问,这里先以一个最简单的 IO 控制为例;
板端 PS 有2个 LED 的 IO,PL 端有 4 个 LED 的 IO 和按键 IO,初步打算 IO 的分配如下,这样就可以覆盖到每种用法:
这里我们关心 AXI GPIO 一行,EMIO 和 MIO 的部分在前面的《Zynq-PS-SDK 之 EMIO 使用》 和 《Zynq-PS-SDK 之 MIO 使用》中已经描述,不在多说;
Xilinx 的 Vivado 软件集成了相关的 IP,我们只需要在 PL 端新增 AXI GPIO 的 IP 即可,这里我们新增两个 AXI GPIO,一个作为控制 LED,另一个作为控制 Key 产生中断;
如图所示,Zynq 的 PS 端使用到了一个 M_AXI_GP0 的资源(红色),连接到一个 AXI Interconnect 互联单元,互联单元连接了 axi_gpio_0 和 axi_gpio_1;
配置 AXI GPIO 端口,一个为输入,一个为输出,位宽都是 1b;
block design 连接完成后(点击 Run Connection Automation),点击 Optimize Routing 可以优化布局;
保存 block design,然后【Generate Output Products】:
【Generate Output Products】这样就会生成顶层文件:
./Zynq7020_PS.srcs/sources_1/bd/design_1/hdl/design_1_wrapper.v
此刻,我们需要为我们定义的管脚进行约束,打开 design_1_wrapper.v:
这个就是顶层的管脚名字,对应到原理图中,进行管脚 xdc 的约束:
- # PL EMIO LED
- set_property PACKAGE_PIN M14 [get_ports {pl_led1_emio_tri_io[0]}]
- set_property IOSTANDARD LVCMOS33 [get_ports {pl_led1_emio_tri_io[0]}]
- # PL AXI GPIO LED
- set_property PACKAGE_PIN M15 [get_ports {pl_led2_axi_tri_o[0]}]
- set_property IOSTANDARD LVCMOS33 [get_ports {pl_led2_axi_tri_o[0]}]
- # PL Input Interrupt
- set_property PACKAGE_PIN N15 [get_ports {pl_key_input_tri_i[0]}]
- set_property IOSTANDARD LVCMOS33 [get_ports {pl_key_input_tri_i[0]}]
约束完成后,生成 bitstream;
生成完 Bitstream 后,硬件部分就完成了,接下来导出硬件:【File】->【Export】->【Export Hardware】:
导出硬件的时候,记得勾选 【Include bitstream】:
此刻,硬件部分就完成了;
硬件弄完后,由于我们增加了 AXI GPIO,所以在系统信息中看得到:
我们展开 axi_gpio_0,可以看到 axi_gpio_0 的寄存器地址,以及相关的偏移:
针对 Xilinx 的 AXI GPIO 相关的内容,可以参考 Xilinx 方法的 AXI GPIO 的 IP 说明:PG144
可以看到,每一个 AXI GPIO IP 可以配置 2 路 GPIO,每一路的宽度为 WIDTH,我们这里就是 32;
寄存器的说明如下:
我们这里,只是用了 GPIO 的输出功能,
GPIO_DATA 寄存器描述为:
GPIOX_TRI 寄存器描述为(也就是配置输出还是输入):
GIER 是中断控制,这个 AXI GPIO IP 的全局中断控制:
IPIER 也是中断控制,可以理解为,GPIO 和 GPIO2 单独的控制:
IPISR 是中断状态:
OK,现在知道了这个 IP 的寄存器用法和绝对地址,而且硬件也 Ready了,那么咱们就可以动起来了,代码上:
- XGpioPs Gpio;
-
- #define RD_32BIT_REG(addr) (*(volatile uint32_t *)(addr))
- #define WR_32BIT_REG(addr, value) (*(volatile uint32_t *)(addr)) = (value)
-
- #define STEPH_MIO_0 0
- #define STEPH_MIO_1 13
-
- #define STEPH_EMIO_0 54
- #define STEPH_EMIO_1 55
- #define STEPH_EMIO_2 56
- #define STEPH_EMIO_3 57
-
- #define MIO_OUTPUT 1
- #define MIO_INPUT 0
-
- #define MIO_OUTPUT_EN 1
- #define MIO_OUTPUT_DIS 0
-
- /* Accroding to the system.hdf file axi_gpio_0 */
- #define AXI_GPIO_0_BASE_ADDR 0x41200000
- #define GPIO_DATA_OFFSET 0x00
- #define GPIO_TRI_OFFSET 0x04
- #define GPIO_2_DATA_OFFSET 0x08
- #define GPIO_2_TRI_OFFSET 0x0C
- #define GIER_OFFSET 0x11C
- #define IP_ISR_OFFSET 0x120
- #define IP_IER_OFFSET 0x128
-
- static void Steph_AXI_GPIO_Init(void)
- {
- // Set as output
- WR_32BIT_REG(AXI_GPIO_0_BASE_ADDR + GPIO_TRI_OFFSET, 0x00);
- }
-
- static void Steph_AXI_LED_On(void)
- {
- WR_32BIT_REG(AXI_GPIO_0_BASE_ADDR + GPIO_DATA_OFFSET, 0x00);
- }
-
- static void Steph_AXI_LED_Off(void)
- {
- WR_32BIT_REG(AXI_GPIO_0_BASE_ADDR + GPIO_DATA_OFFSET, 0x0F);
- }
-
-
- 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;
- }
-
- // For MIO
- 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 MIO Initialize Finished...\r\n");
-
- // For EMIO
- XGpioPs_SetDirectionPin(&Gpio, STEPH_EMIO_0, MIO_OUTPUT);
-
- XGpioPs_SetOutputEnablePin(&Gpio, STEPH_EMIO_0, MIO_OUTPUT_EN);
- xil_printf("Steph_LED EMIO Initialize Finished...\r\n");
-
- Steph_AXI_GPIO_Init();
- xil_printf("Steph_LED AXI GPIO Initialize Finished...\r\n");
-
-
- return Status;
- }
-
- void LED_OFF(uint32_t pin)
- {
- XGpioPs_WritePin(&Gpio, pin, 0x1);
- }
-
- void LED_ON(uint32_t pin)
- {
- XGpioPs_WritePin(&Gpio, pin, 0x0);
- }

相关代码和工程在 gitee 持续更新:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。