在烧录QSPI Flash程序时,不知道烧录成功的标志(代码里只有写入固定数据、读取、擦除的部分),所以想加上PS控制LED的部分,这样的话只要烧录成功,就可以看到LED被点亮。
所以先来学习PS-PL连接,参考:
PYNQ(zynq) PS端+PL端gpio使用 实现软件驱动按键点led灯_pynq led-CSDN博客
在ZYNQ-7000平台上利用PS点亮PL上的LED灯-CSDN博客
一、新建project
此部分不多赘述,主要使用vivado,新建project,新建block design,然后添加zynq system(选择AXI),然后在block里面添加AXI Gpio模块:
选上FCLK_CLK0(PS的clk,50MHz),FCLK_RESET_N。(必须要选,不然后面generate bitstream时会报错)
然后自动连线:
检查地址映射:
然后生成顶层的HDL wrapper。
管脚配置:
Export(含bitstream) --> SDK
(AXi必须要配置中断吗?)
ZYNQ开发系列——GPIO_AXI、MIO、EMIO点灯_zynq a9 mio-CSDN博客
基于ZYNQ7000的SOC点灯实验2--使用AXI_GPIO接口实现PS和PL的交互,PS端点亮PL端的LED-CSDN博客
修改之后仍然报错:
#define LED 0x01
//PL端器件ID: XPAR_AXI_GPIO_0_DEVICE_ID = XPAR_GPIO_0_DEVICE_ID
#define GPIO_EXAMPLE_DEVICE_ID XPAR_GPIO_0_DEVICE_ID
#define LED_DELAY 1000000
#define LED_CHANNEL 1 // AXI GPIO通道1
int main(void)
{
u32 Data;
int Status;
volatile int Delay;
//Initialize the GPIO driver
Status = XGpio_Initialize(&Gpio, GPIO_EXAMPLE_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("Gpio Initialization Failed\r\n");
return XST_FAILURE;
}
//Set the direction for all signals to be inputs except the LED output
XGpio_SetDataDirection(&Gpio, LED_CHANNEL, ~LED); //1:input 0:output
xil_printf("Successfully run Gpio Example\r\n");
/* Loop forever blinking the LED */
while (1) {
XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0x11);
}
return XST_SUCCESS;
}
在Status=初始化 时,程序就跑飞了 :(说明初始化不成功?这样的话应该会打印xil_printf才对。)
接下来就是各种报错:
PYNQ上手笔记 | ③PS端+PL端点灯_pynq z2 点灯-CSDN博客
define LED(引脚)的时候,因为是4个LED,所以应该define为0x00...01111,意思是第0、1、2、3位连接了LED。
现在的疑惑是,为什么程序一点都运行不了,直接跑飞。
Debug发现在Initialize函数这里就进行不下去了,DEVICE_ID检测不到:
是define错了?
此时,不断电再次Debug或者Program FPGA时就会报错。
在想是不是block design时弄错了。
重新new project,也不行。那再加上中断试试。
宣告失败。。。。
修改debug参数也不行:
二、没有AXI也可行
想试试没有AXI,只配置system,与GPIO、EMIO,看看在SDK端对GPIO进行配置(使能、高低电平设置),能否可以实现PL端LED灯的点亮。
烧写时有时会出现错误:(有时烧写成功但是LED没有闪烁)
#include <stdio.h>
#include "platform.h"
#include "stdio.h"
#include "xparameters.h"
#include "xgpiops.h"
#include "sleep.h"
#define LED_1 54
#define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID
XGpioPs_Config *ConfigPtr;
XGpioPs Gpio;
void Delay_us_for(u32 us)
{
//...
}
int main()
{
init_platform();
printf("Hello World\n\r");
//根据器件id,查找器件的配置信息
ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
XGpioPs_CfgInitialize(&Gpio,ConfigPtr,ConfigPtr->BaseAddr);
//初始化GPIO驱动
XGpioPs_SetDirectionPin(&Gpio, 54, 1);
XGpioPs_SetOutputEnablePin(&Gpio, 54, 1);
while(1){
XGpioPs_WritePin(&Gpio, 54, 1-XGpioPs_ReadPin(&Gpio,54));//电平翻转
Delay_us_for(1000000);//1s
}
cleanup_platform();
return 0;
}
Debug时,程序到printf这里就进行不下去了。为什么呢?因为没有配置UART?还是这条路本就不可行?明天再继续吧。
---------------------------------------------------------------------------------
其实并不是进行不下去,而是没有配置bsp的Support Package Settings:
这样的话不需要uart,可以在控制台看到printf的输出了!
代码其实是没错的,重新试了一下,有时会因为头文件的原因而报错:
按F5重新加载一下.h文件即可。
然后Debug,一切正常,LED也开始闪烁。
插一句,在block design时最开始是没有选择DDR的,只有EMIO,这样在SDK的界面,Debug也一切正常,printf也可以输出,所有语句都能正常执行,但是LED不闪烁。
所以DDR的用途和功能是什么?
继续我们马不停蹄地学习吧!
等下!突然有个疑问,怎么在while(1)里让4和LED以不同的频率闪烁呢?(比如LED1-2s,LED2-1s)
int i;
while(1){
for(i = 0; i < 2; i ++){
if(i == 0){
XGpioPs_WritePin(&gpiops_inst, 54, 1);
Delay_us_for(2000000);
XGpioPs_WritePin(&gpiops_inst, 54, 1-XGpioPs_ReadPin(&gpiops_inst,54));
}
else if (i == 1){
XGpioPs_WritePin(&gpiops_inst, 55, 1);
Delay_us_for(1000000);
XGpioPs_WritePin(&gpiops_inst, 55, 1-XGpioPs_ReadPin(&gpiops_inst,55));
}
else {
i = 0;
}
}
这样试了一下,结果为:
LED1亮2s灭,LED2亮1s灭。是类似流水灯的效果。
main.c里面不能写多个always并行块确实是不太方便。难道要写多个while(1)?
但是不太推荐写多个while(),除非嵌套。
找了一下资料,可以用并发线程thread。(还没尝试)