基于Zedboard及Petalinux实现PTPD工程总结——(1)硬件工程篇

    毕业设计在做一些关于PTPD相关的毕业设计。原工程基于ISE以及XPS平台实现,由于项目需要,需要移植在VIVADO上,因此写一篇BLOG记录一下近三周来踩过的坑。

    首先先记录一下硬件的搭建。关于PTP协议的实现,通过软硬件结合的方式,至于源码以及在XPS上实现的工程在github上均可以找到,本篇文章不再提供,重点在于记录软硬件协同工作及调试的过程。


1.硬件搭建部分:

    搭建硬件的方式不再赘述,具体请参考米联客提供的《ZYNQ修炼秘籍》。具体做法即使用VIVADO中的Block Design。首先将各个模块独立封装成IP核,并且调入Block Design中。本其建立方法为:首先先配置ZYNQ,其中必须要的资源为UART, TTC(供后续的Petalinux使用),ENET(供项目中的以太网收发数据)SD(Linux启动方式为SD启动)。配置时,需要将ZYNQ中的ENET口配置为EMIO接口,只有这样才可以连入外部的以太网芯片,使得以太网直接接入PL端。时钟啥的自己配吧,根据项目需求对时钟的要求也不一样。本次项目核心模块为ha1588IP核,使用VIVADO自带的自动连接进行配置即可。在自动连接时,只连接AXI接口,时钟以及其他接口自行连接。

    在编译和综合时,笔者出现过由于时序约束不满足的,而编译不通过的问题。后续了解到可以通过修改综合策略影响,见博文https://blog.csdn.net/FPGADesigner/article/details/82052504。然而比较玄学的是,笔者第二次再次搭建工程时,VIVADO貌似自己修改了综合策略,虽然时序要求不满足,但是编译可以通过。

    编译通过后,首先进行功能仿真。由于带ZYNQ的系统在调试时,需要软硬件协同调试,在硬件部分使用ILA进行信号抓取,在软件部分使用SDK的DEBUG进行断点调试。但本人尝试使用ILA调试时,本人的电脑编译一次ILA需要花费近一个半小时。因此只进行过一次ILA调试。调试部分如下:

    首先,在VIVADO工程中,本IP核选用的为AXI4_LITE接口,在分配地址时给的为64K的空间(其实4K即可)。地址空间分配如下:

   2.软件测试部分

    启动SDK,测试硬件工程是否可以使用。在新建一个空的工程后,进行最简单的读写测试。测试思想为让ZYNQ向IP核中设置一个时间周期,本次设置为8ns,将周期写入到对应寄存器中。IP核接到时钟周期后,开始进行计时累加,并且输出实时时间。因此在SDK上使用XilIn32函数读取对应寄存器中的数值。

    测试代码如下所示:


#include 
#include "platform.h"
#include "xil_printf.h"
#include 
#include "xparameters.h"
#include "xil_io.h"
#include "sleep.h"
#include "xil_types.h"
#define RTC_SET_CTRL_0 0x00

#define RTC_GET_TIME   0x01

#define RTC_SET_ADJ    0x02

#define RTC_SET_PERIOD 0x04
#define RTC_TIME_SEC_H 0x00000010

#define RTC_TIME_SEC_L 0x00000014

#define RTC_TIME_NSC_H 0x00000018

#define RTC_TIME_NSC_L 0x0000001C

#define RTC_SET_TIME   0x08
#define RTC_PERIOD_H   0x00000020
#define RTC_SET_PERIOD_H 0x8
#define RTC_PERIOD_L   0x00000024
#define RTC_SET_RESET  0x10
int main()
{
    init_platform();
	unsigned int ctrl_cmd;
	struct TimeRepresentation{
		int seconds_h;
		int seconds_l;
		int nanoseconds_h;
		int nanoseconds_l;
		int adj_h;
		int adj_l;
		int adj_num;
	};
	struct TimeRepresentation rtc_time_1588;
	Xil_Out32(XPAR_HA1588_AXI_0_BASEADDR+RTC_PERIOD_H,RTC_SET_PERIOD_H);
	Xil_Out32(XPAR_HA1588_AXI_0_BASEADDR+RTC_PERIOD_L,0);
	Xil_Out32(XPAR_HA1588_AXI_0_BASEADDR,RTC_SET_CTRL_0);
	Xil_Out32(XPAR_HA1588_AXI_0_BASEADDR,RTC_SET_PERIOD);
	printf("hello1\n");
	Xil_Out32(XPAR_HA1588_AXI_0_BASEADDR,0x00001000);
	printf("hello144\n");
	Xil_Out32(XPAR_HA1588_AXI_0_BASEADDR,RTC_SET_RESET);
	printf("hellow2\n");


	printf("hello3\n");
	for(int i=0;i<10;i++)
	{
		Xil_Out32(XPAR_HA1588_AXI_0_BASEADDR,RTC_GET_TIME);
		do{
			ctrl_cmd=(Xil_In32(XPAR_HA1588_AXI_0_BASEADDR));
		}while((ctrl_cmd&RTC_GET_TIME)==0x00);
		rtc_time_1588.seconds_h=Xil_In32(XPAR_HA1588_AXI_0_BASEADDR+RTC_TIME_SEC_H);
		rtc_time_1588.seconds_l=Xil_In32(XPAR_HA1588_AXI_0_BASEADDR+RTC_TIME_SEC_L);
		rtc_time_1588.nanoseconds_h=Xil_In32(XPAR_HA1588_AXI_0_BASEADDR+RTC_TIME_NSC_H);
		rtc_time_1588.nanoseconds_l=Xil_In32(XPAR_HA1588_AXI_0_BASEADDR+RTC_TIME_NSC_L);
		printf("user_time=%d+%d+%d+%d\n",rtc_time_1588.seconds_h,rtc_time_1588.seconds_l,rtc_time_1588.nanoseconds_h,rtc_time_1588.nanoseconds_l);
		sleep(1);
	}
    print("Hello World\n\r");

    cleanup_platform();
    return 0;
}

    调试方法如下:

    右击工程,选择Debug As后,选择Launch on Hardware(System Debugger),并且将Programm FPGA以及Reset entire system全部勾选。其次在程序中,在本次程序的printf中设置断点,在Memory窗口中,实时观测本IP核对应地址中的数据,即0x43C0_0000中的数据。并且也可以观测到结构体中的每个成员的变量。

    出现问题:

    在笔者第一次调试时,发现程序运行到第一段XilOut32函数时,程序崩溃。但是有时也会很玄学的跑完所有的XilOut32在进入XilIn32函数时,再次崩溃。测试了约20次,只有2次可以运行至XilIn32函数。无奈之举下,调用了ILA IP核,对ZYNQ与IP核之间的AXI4总线进行DEBUG,编译时长一小时二十分钟。再次启动SDK进行软硬件协同调试时,发现AXI总线上是可以正常进行写入的,但是SDK会崩溃。为此,曾一度怀疑IP核存在问题。然而,有大神建议,在ZYNQ上额外加一个额外的无用的AXI IP核,即可正常工作。

                                                基于Zedboard及Petalinux实现PTPD工程总结——(1)硬件工程篇_第1张图片

    抱着试一试的态度,新增添了一个无用的LED灯的IP,再次进行测试,项目设计中的IP即可正常工作。

    咱也不知道为啥……若有人知道为什么一个IP不能用,而再加一个IP好用的理由的话,欢迎指教。

    但总之,添加一个无用的IP以后,在SDK上可以观测到由FPGA产生的实时时钟,符合预期结果。下一篇博文中将描述在PetaLinux中遇见的坑。

你可能感兴趣的:(嵌入式,FPGA,ZYNQ)