2022.05.07:
每次调试的时候,都需要重新Program FPGA,如下图所示。
如果你把这两个√取消掉的话,再次Debug的时候,它只会加载.elf程序,不会重新Program FPGA,这的确能节省一些加载Debug的时间,但这么做的话PL端的有些IP核没有复位,你再次执行程序的时候就可能会出错。
比如我用DMA读写FFT 9.1 IP核的时候就会出错。它会永远接收不到DMA发送/接收中断的信号。
这个时候就需要重新手动Program FPGA
之后再次Relaunch你的工程
可我这个人偏偏不喜欢等,况且我需要频繁地Debug我的代码。一天我能Debug上百次。
于是乎,我寻求有没有这么一种解决办法,就是只需要在Debug程序开始前就只Program一遍FPGA,而后只需要relaunch SDK工程的办法。
问题的关键,在于如何才能不通过Program FPGA这种对PL端重新编程的笨拙办法来复位我们的IP核。
于是我想到了FCLK_RESET0_N这个信号,既然接上了,为什么不用呢?
也就是说只需要在程序main()函数刚开始的时候就对PL端用程序发出FCLK_RESET0_N信号进行复位,就可以了。
通过网上一顿搜索,我将我收集到的信息整理为:
FCLK_RESET0_N 在PS中对应的寄存器是0xF8000240(1才复位)。
但在操作这个寄存器之前需要解锁SLCR(寄存器地址为0xF8000008)。
所以代码如下:
#include "xil_io.h"
///SLCR寄存器,绝对地址,
#define SLCR_UNLOCK_ADDR 0xF8000008
#define SLCR_LOCK_ADDR 0xF8000004
//FPGA_RST_CTRL寄存器,绝对地址,
#define FPGA_RST_CTRL 0xF8000240
#define UNLOCK_KEY 0xDF0D //解锁码
#define LOCK_KEY 0x767B //加锁码
#define PL_RST_MASK 0x01//低四位对应FCLK_RESETN[3:0]
#define PL_CLR_MASK 0x00
void PlSoftwareReset(void)
{
Xil_Out32(SLCR_UNLOCK_ADDR, UNLOCK_KEY); //解锁
Xil_Out32(FPGA_RST_CTRL, PL_RST_MASK); //复位
Xil_Out32(FPGA_RST_CTRL, PL_CLR_MASK); //拉起复位
Xil_Out32(SLCR_LOCK_ADDR, LOCK_KEY); //加锁
}
只需要在main()函数刚开始的时候调用这个函数。
然后就可以
再次Debug的时候,就只需要加载你的SDK工程就可以了,节省了Debug加载时间,节省了设备的擦写寿命。
2022.05.08:
补充说明:
1.再教一下大家从哪里找这个寄存器地址和复位应该写什么值。
在UG585(UG是User Guide,PG是Product Guide),也就是Zynq-7000 SoC Technical Reference
Manual(TRM),这个可以从Xilinx的DocNav中搜到。
2.这里有一个注意的点,那就是如果启用了多个不同频率的FCLK,最好使用“对应的”FCLK_RESET,因为这个复位脉冲的宽度可能会不同。有些情况下复位可能会失效。