zynq 7000 PS MIO +PL GPOI 流水灯
我用的是微相 MicroZus的板子1.2版本的
官方给的案例是ps控制pl gpoi来点亮,只有pl的4个LED每隔0.5秒暗掉,因为1.2版本的LED是0亮1暗。。。
ps端的两个红色led并没有参与到流水中
版本不同会有些操作的不同,请参考阅读 从vivado 2015 到 vivado 2023
先在vivado中建立硬件平台
一、新建项目
打开vivado--Creat New Project--一直点NEXT--随便填个项目名字--RTL Project
不用添加Source IP Constraints,设备根据你所购的开发版来设置。我的是Zynq-7000 clg400,Speed Grade 为-2
二、设置IP INTERGRATOR
Create Block Design随便填个名字当然也可以直接用默认名字,点ok确认--在Diagram点+添加模块,添加zynq7 processing system,双击模块
在设置Peripheral I/O Pins中选中MIO 48,49 对应的UART1,根据你的开发版对应的接口来定。然后开启剩下的GPIO MIO。修改DDR3 Configuration
MicroZus对应的是MT41J253M16 RE-125,就是最后一个。
添加gpio,这个是给PL的LED用,PL 和 PS之间是通过AXI总线联系的。双击AXI GPIO设置为All Output,因为只有4个PL联接的LED,所以GPIO Width
设为4。然后Default Output Value设置为0x0000000F,也就是二进制的1111,可以通过这里转换。当然不初始输出也没问题。。。毕竟主要是PS运行C编译的程序控制的只有在JTAG刷入的一瞬间会显示全亮。
点击 Run Connection Automation 选中窗口中所有能勾选的,然后Run Block Automation勾选窗口中全部的option不用管默认就行自动生成模块,直接保存。去到source窗口先Generate Output Producs,需要等一会儿,再Create HDL Wrapper。
三、添加I/O Pin
在RTL Analysis下Open Elaborated Design,设置I/O Std LVMOS33也就是对应给3.3V到输出。输出到LED对应的Site,MicroZus的LED对应的是G15、M17、G14、M15。然后保存Constraints随便啥名字。点击Generate Bitstream有可能需要一段时间,等完成后Export Hardware。有些版本可能直接Export反正2023.1版本的不行。
Vivado阶段结束,打开Vitis旧版本需要在File当中Launch SDK,新版本还是直接桌面图标吧,因为根本不会自动读取export harddware的.xsa文件
我习惯把workspace改到vivado项目下新建的 vivado项目名.ide 然后新建项目:在Create a new platform from hardware (XSA) 选择 Browse 浏览到vivado项目中的export的.xsa文件。一路next按照helloworld然后把代码改成如下
#include <stdio.h>
#include "platform.h"
#include "xgpio.h"
#include "xparameters.h"
#include <unistd.h> // sleep(), usleep()
#include "xgpiops.h" //MIO
#define LED1 50 //Microzus对应的MIO地址
#define LED2 51
int main()
{
init_platform();
XGpio GpioInst;
u32 led;
XGpio_Initialize(&GpioInst, XPAR_AXI_GPIO_0_DEVICE_ID); // initialize GPIO IP
XGpio_SetDataDirection(&GpioInst, 1, 0); // set GPIO as output
//MIO 初始化
//这样初始化太长了吧,真有人去看uart初始化失败信心???
/* XGpioPs_Config *ps_config;
ps_config = XGpioPs_LookupConfig(XPAR_XGPIOPS_0_DEVICE_ID);
int status;
status = XGpioPs_CfgInitialize(&ps_mio, ps_config,ps_config->BaseAddr);
if(status!=XST_SUCCESS){
printf("初始化失败\n");
return XST_FAILURE;
}
status = XGpioPs_SelfTest(&ps_mio);
if(status!=XST_SUCCESS){
printf("自检失败\n");
return XST_FAILURE;
}
*/
XGpioPs ps_mio;
XGpioPs_CfgInitialize(&ps_mio,
XGpioPs_LookupConfig(0),
XGpioPs_LookupConfig(0)->BaseAddr);
XGpioPs_SetDirectionPin(&ps_mio,LED1,1);//设置LED为输出
XGpioPs_SetDirectionPin(&ps_mio,LED2,1);
XGpioPs_SetOutputEnablePin(&ps_mio, LED1, 1);//启用
XGpioPs_SetOutputEnablePin(&ps_mio, LED2, 1);
printf("Led start looping ...\n");
while(1)
{
for(led = 0; led < 6; led++)
{
if(led<4){
XGpio_DiscreteWrite(&GpioInst, 1, 0xF-(1 << led));
XGpioPs_WritePin(&ps_mio,LED1,1);
XGpioPs_WritePin(&ps_mio,LED2,1);
}
else
{
if(led==4){
XGpio_DiscreteWrite(&GpioInst, 1, 0xF);
XGpioPs_WritePin(&ps_mio,LED1,0);
XGpioPs_WritePin(&ps_mio,LED2,1);
}
if(led==5){
XGpio_DiscreteWrite(&GpioInst, 1, 0xF);
XGpioPs_WritePin(&ps_mio,LED1,1);
XGpioPs_WritePin(&ps_mio,LED2,0);
}
}
// printf("%d\n",0xF-(1 << led));
//sleep(1);
usleep(500000); // 500_000 us = 0.5s
}
}
cleanup_platform();
return 0;
}
本文参考自: