参考
- xilinx ug1165
- pynq z-2 用户手册
背景
zynq7000 MIO有53个,在BANK0和BANK1,并且直接与PS相连;EMIO有64个,在BANK2和BANK3,与PL相连;PS可以通过EMIO连接PL端的引脚。
准备
- Vivado2020.1
- Vitis2020.1
- pynq z-2
功能
使用PL端口的SW0和LED1,SW0作为AXI GPIO,LED1作为EMIO;SW0的切换实现LED1的亮灭。
生成XSA文件
-
新建vivado工程;
-
创建Block Design;
-
添加zynq ip,做好基础设置;
-
添加EMIO,在MIO Configuration->I/O Peripherals->GPIO->EMIO GPIO,选择1个EMIO。
zynq会生成如下的一个gpio:
-
添加AXI GPIO,选择通道1,1位宽,设置如下:
-
自动连线得到如下图(axi timer是后续用来做定时器中断用的,本章节忽略):
-
接着就是添加引脚约束,生成bit流文件;
-
加入vitis之后,vivado好像就不生成hdf文件了,而是生成.xsa文件,点击File->Export Hardware Platform,选择:
编写APP
- 在Vivado中,launch vitis:
- 手动创建vitis工程,选择工作区
还是和以前SDK一样创建一个裸机的hello world工程,一路next。 - 参考了UG1165的demo,接着上代码:
#include <stdio.h>
#include "platform.h"
#include "xil_types.h"
#include "xgpio.h"
#include "xtmrctr.h"
#include "xparameters.h"
#include "xgpiops.h"
#include "xil_io.h"
#include "xil_exception.h"
#define PS_PIN_DIRECTION_OUT 0x1
#define PS_PIN_DIRECTION_IN 0x0
#define PL_PIN_DIRECTION_OUT 0x0
#define PL_PIN_DIRECTION_IN 0x1
#define PS_ENABLE_OUTPIN 0x1
#define PS_DISABLE_OUTPIN 0x0
#define CHANNEL1 0x1
#define CHANNEL2 0x2
#define LED1_ON() XGpioPs_WritePin(&psGpioInstancePtr,iPinNumberEMIO,1)
#define LED1_OFF() XGpioPs_WritePin(&psGpioInstancePtr,iPinNumberEMIO,0)
u32 ReadStatus = 0;
int main()
{
XGpioPs psGpioInstancePtr;//emio
XGpio GPIOInstance_Ptr;//mio
XGpioPs_Config *GpioConfigPtr;
XTmrCtr TimerInstancePtr;
int iPinNumberEMIO = 54;//mio 有53个
int xStatus;
//ps gpio initialize
GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
if(GpioConfigPtr == NULL)
return XST_FAILURE;
xStatus = XGpioPs_CfgInitialize(&psGpioInstancePtr,
GpioConfigPtr, GpioConfigPtr->BaseAddr);
if(XST_SUCCESS != xStatus)
print(" PS GPIO INIT FAILED \n\r");
XGpioPs_SetDirectionPin(&psGpioInstancePtr, iPinNumberEMIO, PS_PIN_DIRECTION_OUT);
XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, iPinNumberEMIO, PS_ENABLE_OUTPIN);
//axi gpio initialize
XGpio_Initialize(&GPIOInstance_Ptr,XPAR_AXI_GPIO_0_DEVICE_ID);
XGpio_SetDataDirection(&GPIOInstance_Ptr, CHANNEL1, PL_PIN_DIRECTION_IN);
if(XST_SUCCESS != xStatus)
print("AXI GPIO INIT FAILED\n\r");
// loop start
while(1) {
ReadStatus = XGpio_DiscreteRead(&GPIOInstance_Ptr, CHANNEL1);
if (ReadStatus == 0x1) {
LED1_ON();
} else if(ReadStatus == 0x0) {
LED1_OFF();
}
}
return 0;
}
总结
PS通过EMIO可以控制PL端的引脚