ZYNQ开发系列——SDK输出串口选择以及打印函数print、printf、xil_printf的差别
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
ZYNQ开发系列——SDK输出串口选择以及打印函数print、printf、xil_printf的差别
- 前言
- 两个串口到底是谁在打印?
- print 和 printf 和 xil_printf
前言
在最初的helloworld工程中,我们实现了通过串口每个1秒钟打印一次Hello World。
#include "platform.h"
#include "xil_printf.h"int main()
{init_platform();while(1){print("Hello World\n\r");sleep(1);}cleanup_platform();return 0;
}
这里我们就来搞清楚以下几个问题,从简单到复杂问题依次为:
1、 我们有两个串口,那怎么区分是从哪个串口打印的
2、 为什么是print函数,一般C标准打印函数是printf呢
3、 如果我两个串口都想打印东西怎么弄
4、 串口的波特率如何修改,最大能支持多少
后面2点放到另一篇文章讲。
两个串口到底是谁在打印?
一开始我们就定义了两个串口,在xparameter.h中的描述如下# 二、使用步骤
/* Definitions for driver UARTPS */
#define XPAR_XUARTPS_NUM_INSTANCES 2/* Definitions for peripheral PS7_UART_0 */
#define XPAR_PS7_UART_0_DEVICE_ID 0
#define XPAR_PS7_UART_0_BASEADDR 0xE0000000
#define XPAR_PS7_UART_0_HIGHADDR 0xE0000FFF
#define XPAR_PS7_UART_0_UART_CLK_FREQ_HZ 100000000
#define XPAR_PS7_UART_0_HAS_MODEM 0/* Definitions for peripheral PS7_UART_1 */
#define XPAR_PS7_UART_1_DEVICE_ID 1
#define XPAR_PS7_UART_1_BASEADDR 0xE0001000
#define XPAR_PS7_UART_1_HIGHADDR 0xE0001FFF
#define XPAR_PS7_UART_1_UART_CLK_FREQ_HZ 100000000
#define XPAR_PS7_UART_1_HAS_MODEM 0
那怎么知道以及设置是要从UART_0打印还是UART_1打印呢?
我们进入print.c文件,找到outbyte函数,里面内容为
XUartPs_SendByte(STDOUT_BASEADDRESS, c);
这个STDOUT_BASEADDRESS的定义为:
#define STDIN_BASEADDRESS 0xE0000000
#define STDOUT_BASEADDRESS 0xE0000000
这个就正好和XPAR_PS7_UART_0_BASEADDR吻合了,也即是说,我们当前使用的哪个串口,与这两个宏定义设置有关。
因此我们如果想换成UART_1打印,只要将STDOUT_BASEADDRESS 改成0xE0001000即可,同时STDIN_BASEADDRESS这个也应同步修改。
还有一种方式是,直接在mss文件中修改
而且这里修改会同步对xparameter.h处的STDIN_BASEADDRESS和STDOUT_BASEADDRESS进行修改。
因此如果我们要修改要打印的串口,我觉得最好还是通过第二种方式修改(修改mss文件中的配置),因为第一种方式修改后会和mss中显示的stdin和stdout不一致。
print 和 printf 和 xil_printf
参考 https://www.youtube.com/watch?v=f2pPIRHc0bM
我们阐述下三种打印的差别
差别1:
1、printf 是调用C标准库,使用printf的时候需要加头文件 #include <stdio.h>
2、print 和 xil_printf是使用xilinx自己的库 #include “xil_printf.h”
差别2:
1、 print只能打印字符串
2、 xil_printf和printf,可以带参量打印,但是xil_printf不支持打印浮点数
xilinx的SDK工具支持标准的c库,比如我们最日常使用的printf函数,就是标准c库里的一个重要函数。但是标准c库所谓的标准性,或者所谓的通用性带来的问题就是它必须面对所有的情况,而一些情况在fpga设计中是普通情况下是极少碰到的,比如正常情况下,浮点处理是很少用的。如此之后,这个函数必然会变得体态臃肿。比如这里的printf函数。不知道大家有没有这样的经验,使用printf函数,你的程序最后编译出来变的很大~其实xil_printf和printf的功能是一样的,只是xil_printf除去了浮点的所有功能,如此之后,一下子程序就变得很小了。
如果用专业一点的术语描述,就是使用printf链接过程是静态链接,静态链接的时候他进行链接的是一整个<stdio.h>,而且静态链接的特点在于他是直接把这个对象文件加入到了可执行文件当中,极大的浪费了内存空间。而另外两个函数是动态链接,其链接过程是动态的在可执行程序执行的时候进行链接的。
既然提到使用print 和 printf 和 xil_printf的内存问题,那么,我们就来做个实验看看,到底怎么节省内存法。
(1)printf打印字符串
#include <stdio.h>
void main(void){printf("helloworld\n");
}
(2)print打印字符串
void main(void){print("helloworld\n");
}
(3)xil_printf打印字符串
#include "xil_printf.h"
void main(void){xil_printf("helloworld\n");
}
这三个实验结论:使用print打印字符串最节省内存
(4) printf打印带参数语句
#include <stdio.h>
void main(void){printf("helloworld,%d\n",1);
}
(5) xil_printf打印带参数语句
#include "xil_printf.h"
void main(void){xil_printf("helloworld,%d\n",1);
}
结论:除非是打印浮点数,打印整点使用xil_printf节省内存
(6)多个xil_printf打印带参数语句
#include "xil_printf.h"
void main(void){xil_printf("helloworld,%d\n\r",1);xil_printf("helloworld,%d\n\r",1);xil_printf("helloworld,%d\n\r",1);xil_printf("helloworld,%d\n\r",1);xil_printf("helloworld,%d\n\r",1);xil_printf("helloworld,%d\n\r",1);xil_printf("helloworld,%d\n\r",1);xil_printf("helloworld,%d\n\r",1);xil_printf("helloworld,%d\n\r",1);xil_printf("helloworld,%d\n\r",1);xil_printf("helloworld,%d\n\r",1);xil_printf("helloworld,%d\n\r",1);xil_printf("helloworld,%d\n\r",1);
}
(7) 多个printf打印带参数语句
#include <stdio.h>
void main(void){printf("helloworld,%d\n\r",1);printf("helloworld,%d\n\r",1);printf("helloworld,%d\n\r",1);printf("helloworld,%d\n\r",1);printf("helloworld,%d\n\r",1);printf("helloworld,%d\n\r",1);printf("helloworld,%d\n\r",1);printf("helloworld,%d\n\r",1);printf("helloworld,%d\n\r",1);printf("helloworld,%d\n\r",1);printf("helloworld,%d\n\r",1);printf("helloworld,%d\n\r",1);printf("helloworld,%d\n\r",1);}
结论:无论是printf 还是xil_printf 多个打印语句不会显著增加内存
总之,需要打印字符串就使用print函数,需要打印浮点数就使用printf,需要打印整点数就使用xil_printf就没错了。可能的话最好所有打印都不要出现printf,只要有一个都会使内存增加不少。
ZYNQ开发系列——SDK输出串口选择以及打印函数print、printf、xil_printf的差别相关推荐
- ZYNQ开发中SDK输出串口选择以及打印函数print、printf、xil_printf的差别
ZYNQ开发系列--SDK输出串口选择以及打印函数print.printf.xil_printf的差别 前言 两个串口到底是谁在打印? print 和 printf 和 xil_printf 前言 在 ...
- zynq开发系列5:通过AXI GPIO的中断实现PL端按键控制PS端LED(SDK开发详解)
axi_gpio是PL端gpio(FPGA资源搭建的软核),ps7_gpio是ps端gpio(硬核).打开Documentation的示例Examples,可知第二个是关于中断的示例.导入示例impo ...
- ZYNQ开发系列——双串口打印以及串口波特率设置
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 ZYNQ开发系列--双串口打印以及串口波特率设置 前言 双串口打印 串口波特率的修改 前言 上一篇,我们遗留了这两个问题: 1. 如果 ...
- ZYNQ开发系列——PS开发之HelloWorld
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 ZYNQ开发系列--PS开发之HelloWorld 前言 外设接口 SDK建立工程相关操作记录 前言 俗话说一日不见,如隔三秋.两年没 ...
- ZYNQ开发系列——把PS和PL程序烧写到FLASH中
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 ZYNQ开发系列--把PS和PL程序烧写到FLASH中 生成 fsbl.elf 生成 BOOT.bin 下载 BOOT.bin 文件到 ...
- zynq开发系列4:MIO按键中断控制LED
与实验三类似 zynq开发系列3:GPIO连接MIO通过按键控制LED灯亮起 ,PS部分设置为与实验一helloword相同的最小系统,但按键控制LED的方式设置为中断,即通过按下按键为中断这一方式从 ...
- zynq开发系列3:GPIO连接MIO通过按键控制LED灯亮起
按键和LED由MIO连接,在PS端用按键控制LED,按键按下时发出信号,LED接收到信号后亮起 可以参考上一节实验 zynq开发系列2:GPIO连接MIO控制LED闪烁 的流程和代码,在vivado操 ...
- ZYNQ开发系列——hw_platform包和BSP包中的一些理解
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 ZYNQ开发系列--hw_platform包和BSP包中的一些理解 前言 hw_platform BSP包 前言 前面我们完成了PS输 ...
- ZYNQ开发系列——为PS和PL的交互做准备
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 ZYNQ开发系列--为PS和PL的交互做准备 我们使用ZYNQ的片子,肯定存在PS和PL交互的情况.一般来说大部分应用都是以PS为主机 ...
最新文章
- 002.Docker安装部署
- 进击的Waymo,掘进无人驾驶深水区
- 通过7个函数解密区块链(附代码)
- linux主题文件,美化你的Linux!23个精美Ubuntu主题下载
- mysql中文乱码的一点理解
- 小白的markdown基础语法总结
- GitHub 回滚操作
- Angular里ngModel双向绑定的一个使用例子
- easyui 图标_logo设计和图标设计有哪些不同?
- 大华监控摄像机接入到小程序、公众号、网站视频直播配置流程
- 深度学习——PReLU激活
- Windows下设置Tomcat自启动
- Vue2在使用Element-UI的分页组件遇到的问题(如PageSize,PageNum等)
- 证明:模n加法满足结合律
- 十一则:程序员冷“笑话”据说只有真正的程序员才看得懂
- leetcode884. 两句话中的不常见单词(你肯定会被惊呆了)
- linux 开头是减号的文件名 如何进行文件操作 删除复制移动
- Cesium不改源码支持坐标系为4490的ArcGIS Rest缓存服务的解决方案,代码为TypeScript编写(vx gzh【图说GIS】)
- 计算机技术实训的内容,计算机专业生产实习目的及内容
- CVPR ECCV ICCV 计算机视觉顶会论文下载