本文用EMIO的方式在主板上演示串口的hello world例程(适用于主板Type C 端口的UART资源)
本文在 vivado2018.3版本上 演示, 其他版本请自行研究
1.硬件资源介绍
PS端串口的映射有两种,方式一 直接通过ZYNQ的PS专用串口的IO口。 方式2 PS端的UART 通过EMIO方式映射到任意PL端口进行引出,两种方式的效果是完全一样的(方式2拓展性更强)。(因为我们的串口是连接在PL端的,所以这里我们用方式二 通过EMIO将UART 映射到PL端 IO上)
2. 创建工程(本处将同时介绍 emio映射的uart 创建方法)
1)新建一个项目,芯片型号选择 XC7Z010CLG400-1(略掉部分过程,详细图文过程可以参考前面的几个帖子)
2) 创建一个BLOCK设计,并添加ZYNQ7 PROCESSING SYSTEM模块,软件自动生成了一个 zynq的block 如下图所示,接下来要做一些相应的设置,双击下图中的ZYNQ核
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-3.png)
3)在ZYNQ中设置时钟功能:
找到 设置项目中的 Clock Configuration 选项, 在PL Fabric Clocks 设置自己需要的时钟频率,这里一共有4种频率可以设置 类似于我们的PLL功能。这里我们设置50M时钟
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-50.png)
4)在zynq中设置DDR功能:
依次在弹窗里找到DDR Configuration→DDR Controller Configuration→DDR3,在Memory Part下拉菜单中根据自己板子上的DDR来选择相应的DDR3,本实验所用到型号:MT41K128M16JT 125,数据位宽选择16bit 最后点击“OK”,如下图所示。
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-5.png)
5) 添加 uart功能
由下图可知, 主板的UART功能接在 ZYNQ PL端的 U13脚和T12脚了,这里要反着看,CH340的TX 对应 ZYNQ的RX, CH340的RX 对应ZYNQ的TX,所以这里 ZYNQ的TX是 U13,ZYNQ的RX是T12
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-117-1024x425.png)
使能UART 0 并在IO选项力 选择EMIO方式
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-118.png)
6)完成上述操作后, 点击“Run Block Automation”如下图所示。在弹出的选项中保持默认,点击“OK”,即可完成对ZYNQ7 Processing System的配置,并用鼠标连接FCLK_CLK和 M_AXI_GP0_ACLK,得到下图
![](http://www.hellofpga.com/wp-content/uploads/2022/07/image-5.png)
在上图中分别点击IO口进行以下操作:
右键UART_0选择Make External(这一步仅仅 用到EMIO 的UART时需要用到,扩展板)
![](http://www.hellofpga.com/wp-content/uploads/2022/07/image-6.png)
7)source→Design Source ,右键我们创建的BLOCK工程,点击create HDL wrapper,打包BLOCK文件并生成.v代码
8) 点击绿色箭头RUN 对代码进行编译
9) 点击RTL 中的SCHEMATIC , 并选择右边出现的 IO Ports 来增加UART 0 EMIO部分的管脚定义(这一步也可以在约束文件中定义, 可看之前的例子)
![](http://www.hellofpga.com/wp-content/uploads/2022/07/image-7-1024x482.png)
将 UART 部分的 TX RX 分别设置成 U13,T12 电压属性设置成 LVCMOS33, 之后保存
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-119.png)
10) 生成bit文件 :按下Generate Bitstream 完成综合以及生成bit文件(会弹出窗口要求保存 约束规则文件)
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-18.png)
5.SDK程序编写
1)File→Export→Export hardware…,在弹出的对话框中勾选“include bitstream”,点击“OK”确认,如下图所示。
![](http://www.hellofpga.com/wp-content/uploads/2022/07/image-10.png)
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-24.png)
2)File→Lauch SDK,在弹出的对话框中,保存默认,点击“OK”,如下图所示。
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-21.png)
系统将自动打开SDK开发环境
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-22.png)
3)新建一个工程 file→new→Application Project,来新建一个“Application Project”,如下图所示。
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-23.png)
4)在新建工程名中输入自己的工程名称(UART),点击NEXT
5)选择一个空工程,点击完成
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-73.png)
6) 在空工程中创建我们自己的代码
展开我们创建的工程,在src目录上右键,选择New->Source File,如下图所示:
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-76.png)
在弹出的窗口中创建一个main.c文件
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-77.png)
7)书写自己的代码
7.1小贴士:
在初次写PS部分的代码时,如GPIO代码 和UART代码,不知道怎么写的情况下,其实可以通过打开 BSP工程下的 system.mss文件, 然后在右边导入需要的参考例程, 然后将例程中自己需要的部分(如GPIO初始化,或者UART的写和读代码COPY到自己工程的main函数中)再进行修改。
![](http://www.hellofpga.com/wp-content/uploads/2022/07/image-11-1024x607.png)
7.2 复制 下列代码 到 main.c
#include "xparameters.h" #include "xuartps.h" #include "xil_printf.h" XUartPs Uart_Ps_0; /* 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); 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); SentCount++; } } int main(void) { int Delay; UART_init(); while(1){ UartPs_HelloWorld(); for (Delay = 0; Delay < 100000000; Delay++); } }
我这边参考了官方的代码, 并做了一定的删减(删除了不必要的初始化验证等),将UART 0,和进行了初始化, 并且在helloworld的代码中,端口进行helloworld的字符串输出,反复循环。
8.代码下载验证
先对 RUN AS 的环境进行配置
![](http://www.hellofpga.com/wp-content/uploads/2022/07/image-12.png)
在弹出的窗口中 对4个 方框都进行勾选操作,以确保每次运行都会重新启动系统,并且重新编程FPGA, 这样就不会出现下载程序debug的时候概率性不工作的问题了(不勾选情况下,板子本身运行程序的时候,再重新debug会概率性出现下载报错的情况)PS没有出现 下图对话框,可以先点绿色箭头DEBUG一下 ,再重新 点选上图RUN CONFIGURATIONS 的选项
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-120.png)
设置好之后,选择Run As
-> Launch on Hardware (System Debugger)
或者 Launch on Hardware (GDB).
![](http://www.hellofpga.com/wp-content/uploads/2022/07/image-14.png)
经过上述操作后,串口就会正常输出数据了,此时用串口助手去查看,可以看到 系统在不停的发送 hello world字符串(串口波特率 115200)
![](http://www.hellofpga.com/wp-content/uploads/2022/07/image-15.png)
以下是本文中提到的完整工程 ,仅供参考
备注 ZYNQ芯片功能非常强大,上述仅进行简单的helloworld演示, 实际串口功能还可以调用中断,调用FIFO等,这个各自自行学习尝试了
备注 如果你使用自己的TYPE C充电线 请注意,部分市面上的TYPE C充电线 是仅充电的,不带数据传输功能,需要用TYPE C 数据线才能实现通讯