EBAZ4205 第十四个工程的PS部分UART功能演示

本文用MIO和EMIO两种方式在EBAZ4205矿机上演示串口的hello world例程(适用于主板uart,和转接板UART)

1.硬件资源介绍

串口的实现有两种方式,方式1 ebaz4205主板上有串口的资源引出,在靠近按键的地方,有一个4脚的排针接插件,这个接插件中的 tx和rx是连接到ZYNQ的PS硬件UART上的。 方式2,PS端的UART 通过EMIO方式映射到任意PL端口进行引出。

如果是用的扩展板,第一种方式可以摘去扩展板的跳线帽,然后用杜邦线将 扩展板上的GND,TX,RX和主板的 UART口连接, 第二种方式下,转接板的串口部分跳线帽插上即可实现串口的通讯。

(备注,早期的转接板上的TX 和RX 的丝印是画反的 ,在连线时候请注意, TX 和RX 对应 主芯片的TX,RX ,FPGA管脚设置可以参考这个丝印, 但是对于拔掉跳线帽的时候单独用USB转UART部分来说 丝印是标反的)(最新的板子丝印是正确的)

可能看着有点绕, 看下图原理图上两个画框的地方就能理解了

2. 创建工程(本处将同时介绍方式1 ps 直连的uart,和方式2 emio连接的uart 的创建方法)

1)新建一个项目,芯片型号选择 XC7Z010CLG400-1(略掉部分过程,详细图文过程可以参考前面的几个帖子)

2) 创建一个BLOCK设计,并添加ZYNQ7 PROCESSING SYSTEM模块,软件自动生成了一个 zynq的block 如下图所示,接下来要做一些相应的设置,双击下图中的ZYNQ核

3)在ZYNQ中设置时钟功能:

找到 设置项目中的 Clock Configuration 选项, 在PL Fabric Clocks 设置自己需要的时钟频率,这里一共有4种频率可以设置 类似于我们的PLL功能。这里我们设置50M时钟

4)在zynq中设置DDR功能:

依次在弹窗里找到DDR Configuration→DDR Controller Configuration→DDR3,在Memory Part下拉菜单中根据自己板子上的DDR来选择相应的DDR3,本实验所用到型号:MT41K128M16JT 125,数据位宽选择16bit 最后点击“OK”,如下图所示。

5) 添加 uart功能

a (主板直接引出方式),由下图可知, ebaz4205 的uart连接到的是 主板的功能1脚

可以看出 用方式A连接,实际连接到 PS部分的MIO24 和MIO 25管脚上, 在设置页面 将UART1对应管脚设置成 MIO24 MIO 25即可

b (主板 通过EMIO 连接到扩展板方式)

因为 uart 1已经被 MIO 方式a 占用,所以这里 EMIO 只能连接到 UART 0上了

6)完成上述操作后, 点击“Run Block Automation”如下图所示。在弹出的选项中保持默认,点击“OK”,即可完成对ZYNQ7 Processing System的配置,并用鼠标连接FCLK_CLK和 M_AXI_GP0_ACLK,得到下图

在上图中分别点击IO口进行以下操作:

右键UART_0选择Make External(这一步仅仅 用到EMIO 的UART时需要用到,扩展板)

7)source→Design Source ,右键我们创建的BLOCK工程,点击create HDL wrapper,打包BLOCK文件并生成.v代码

8) 点击绿色箭头RUN 对代码进行编译

9) 点击RTL 中的SCHEMATIC , 并选择右边出现的 IO Ports 来增加UART 0 EMIO部分的管脚定义(这一步也可以在约束文件中定义, 可看之前的例子)(这一步仅仅 用到EMIO 的UART时需要用到,扩展板)

将 UART 部分的 TX RX 分别设置成 H17 H16,电压属性设置成 LVCMOS33(这一步仅仅 用到EMIO 的UART时需要用到,扩展板)

10) 生成bit文件 :按下Generate Bitstream 完成综合以及生成bit文件(会弹出窗口要求保存 约束规则文件)

5.SDK程序编写

1)File→Export→Export hardware…,在弹出的对话框中勾选“include bitstream”,点击“OK”确认,如下图所示。

2)File→Lauch SDK,在弹出的对话框中,保存默认,点击“OK”,如下图所示。

系统将自动打开SDK开发环境

3)新建一个工程 file→new→Application Project,来新建一个“Application Project”,如下图所示。

4)在新建工程名中输入自己的工程名称(UART),点击NEXT

5)选择一个空工程,点击完成

6) 在空工程中创建我们自己的代码

展开我们创建的工程,在src目录上右键,选择New->Source File,如下图所示:

在弹出的窗口中创建一个main.c文件

7)书写自己的代码

7.1小贴士:

在初次写PS部分的代码时,如GPIO代码 和UART代码,不知道怎么写的情况下,其实可以通过打开 BSP工程下的 system.mss文件, 然后在右边导入需要的参考例程, 然后将例程中自己需要的部分(如GPIO初始化,或者UART的写和读代码COPY到自己工程的main函数中)

7.2 复制 下列代码 到 main.c

#include "xparameters.h"
#include "xuartps.h"
#include "xil_printf.h"

XUartPs Uart_Ps_0;		/* The instance of the UART Driver */
XUartPs Uart_Ps_1;		/* The instance of the UART Driver */

int UART_init(){
	XUartPs_Config *Config;
	int Status;

	Config = XUartPs_LookupConfig(XPAR_XUARTPS_0_DEVICE_ID);
	Status = XUartPs_CfgInitialize(&Uart_Ps_0, Config, Config->BaseAddress);
	XUartPs_SetBaudRate(&Uart_Ps_0, 115200);

	Config = XUartPs_LookupConfig(XPAR_XUARTPS_1_DEVICE_ID);
	Status = XUartPs_CfgInitialize(&Uart_Ps_1, Config, Config->BaseAddress);
	XUartPs_SetBaudRate(&Uart_Ps_1, 115200);

	return Status;
}

void UartPs_HelloWorld()
{
	u8 HelloWorld[] = "Hello World  ";
	int SentCount = 0;

	while (SentCount < (sizeof(HelloWorld) - 1)) {
		 XUartPs_Send(&Uart_Ps_0, &HelloWorld[SentCount], 1);
		 XUartPs_Send(&Uart_Ps_1, &HelloWorld[SentCount], 1);
		SentCount++;
	}
}

int main(void)
{
	int Delay;
	UART_init();
	while(1){
		UartPs_HelloWorld();
		for (Delay = 0; Delay < 100000000; Delay++);
	}
}

我这边参考了官方的代码, 并做了一定的删减(删除了不必要的初始化验证等),并将UART 0,和UART 1一起进行了初始化, 并且在helloworld的代码中,两个端口 同时进行helloworld的字符串输出,反复循环。(实际做工程的时候 ,需要用到哪路,单独初始化就好,不用两边都调用)

8.代码下载验证

先对 RUN AS 的环境进行配置

在弹出的窗口中 对4个 方框都进行勾选操作,以确保每次运行都会重新启动系统,并且重新编程FPGA, 这样就不会出现下载程序debug的时候概率性不工作的问题了(不勾选情况下,板子本身运行程序的时候,再重新debug会概率性出现下载报错的情况)

设置好之后,选择Run As -> Launch on Hardware (System Debugger) 或者 Launch on Hardware (GDB).

经过上述操作后,两个串口就会同时正常输出数据了,此时用串口助手去查看,可以看到 系统再不停的发送 hello world字符串(串口波特率 115200)

当用跳线帽直接连接的时候用的是EMIO 的串口

当用杜邦线去连接主板上UART 的时候用的是MIO的串口

以下是本文中提到的完整工程 ,仅供参考

备注 ZYNQ芯片功能非常强大,上述仅进行简单的helloworld演示, 实际串口功能还可以调用中断,调用FIFO等,这个各自自行学习尝试了

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注