Printf函数看着简单,其实是比较复杂的,因为输入形参类型是可变的,他什么类型都可以打印,具体是怎么实现的呢?看了几个例子,大概是先把输入的数据格式化成字符串,如果硬件接口是串口(还有USBCDC、SWO等),那么通过串口把数据发出来。
在开发过程中,打印是很重要的功能,因为出现bug时需要看打印信息来解bug。本文说几个遇到过的打印相关的问题。
1、为什么就是打印不出来?
最近做的一个项目,NXP的芯片,用的开发编译工具是windows下的IDE工具,首先导入了一个Demo工程,用jlink仿真调试时发现已经能打印,打印的数据是在IDE的控制台中输出来,应该是通过Jlink 里的SWO?UART?(我也不确定)打印出来的。
后来想把打印用串口打出来,发现工程里已经有打印函数的实现,只是不是从串口3打出,我只需要把他改成串口3就行了。
但是奇怪的是,无论怎么改,打印就是从控制台通过jlink打出的,无法从串口打出!代码里面通过宏定义来控制打印从哪里打出,看到宏定义明明已经将SDK_DEBUGCONSOLE这个宏定义成从串口打出了啊!难道这个定义无效?
唉抄代码都抄错!有点伤心。
后来新建一个工程时发现有一个选项是选择从仿真器打出,还是从串口打出!
而最开始我是导入的Demo工程,demo工程这个选项不能选,默认是从仿真器打出!如下图。
那么建立两个一模一样的工程,一个选择从串口打出,一个选择从仿真器打出,他们的代码会有什么区别呢?
试了下,对比了一下,代码是一模一样的,只是有一个工程配置文件的一些配置选项不一样,看到了配置文件里对宏SDK_DEBUGCONSOLE的定义值不一样,从仿真器打出是0,从串口打出是1,如下图。
与上面贴出的代码里的定义是一样的,也就是代码里的SDK_DEBUGCOLE定义为1是无效的。为啥?
因为代码里用的是预编译命令”ifndef”,也就是如果还没定义这个宏,那现在来定义他为多少,如果定义了,那现在的定义就无效了。
在代码编译时,IDE应该是先会把工程的一些设置进行预编译,然后再对代码进行预编译à编译à链接。
2、为什么打着打着突然就断了?
曾经遇到过一个问题,打印数据打着打着突然就断了,但是程序似乎又没什么问题,好好的跑着,但就是时不时发现打着打着断掉了。后来发现是打印函数重新实现时,限制了最大打印长度为128,嵌入式系统资源有限,一般不能一次打印太多数据。
有些平台打印最长数据是256,总之对于不得不要打印大块数据时,可以再包一个可以打印大块数据的函数。
3、为什么有的log打出两遍?
与某公司合作项目,我们提供SDK,编成.a库文件提供,他们开发应用程序,发现SDK里的log,有时候会打出两遍来!太诡异了!而且重复打出的一般是简短的log或者一段长log的结尾处log,难道有两个一模一样的线程在跑?外面调用了两次SDK里的线程的主函数?一再确认没有啊,如果有两个一模一样的,那应该所有log都有双份啊!
后来发现SDK里用的是printf 打印函数,而外面应用程序将打印重新进行宏定义包了一下,pintf使用之前加了互斥锁,printf完了之后再释放互斥锁。
问题也许就在这里啊!
Printf前后要加锁保护,说明printf不是原子操作(即不能被线程调度打断的操作),这样做可以避免几个线程的log打串了,打印时大家都要先获得锁才能打,那就只能排队等别人打完再打了。
那么现在打印出两遍是怎么发生的呢?还原一下现场看看?
打印过程应该是先把数据送到驱动层的某个缓存里,然后驱动层串口程序从缓存取数据往串口写,现在是外面应用程序遵守规则打印之前都会去先等待互斥锁释放,SDK里没有加锁,那假设外面某个线程正在打印时,SDK插队打印,把SDK的数据传到驱动层,然后CPU转到应用程序继续打印,如果打印函数是一直打到数据结束为止,那么就会把SDK的数据也打出来了;接下来CPU回到SDK所在线程那里,刚刚已经把缓存传给驱动层,接下来应该是打印了,那刚刚SDK传过去的数据会不会再次打印呢?
刚刚打印完驱动层应该会把自己缓存里应用层传给他的数据清除,那SDK插队传过去的数据会不会也清除呢?没法确定,如果他只是按应用层传给他的长度清除那就还没清除。
具体到底是怎么发生的,其实我也没有想明白,后来SDK里也加了锁,接下来看实际效果了。
4、SDK里没法用printf,外面应用程序将打印函数注册进来
与某公司合作的一个项目,也是我们提供SDK,他们实现应用代码,SDK里用printf打印数据根本就没法打出来,发现他们用的打印函数是vmprintf,可能是重新实现了,后来只好在SDK初始化时应用程序把外面的打印函数注册进来,里面用注册的打印函数。
![01dc8982a37c245eb1bd813d59adb5f6.png](https://i-blog.csdnimg.cn/blog_migrate/9c961f38f1e5c0ee9be92bd2f0221962.jpeg)
1.美国再出狠手!这家中国创业公司被下禁令:技术无法转回国,IPO 计划搁浅
2.TIOBE 3 月编程语言排行榜:Java 大涨,Delphi 辉煌不再!
3.默默无闻的嵌入式技术,其实一直在创新中求发展
4.震惊!FPGA运算单元可支持高算力浮点
5.6 个步骤,搞定 AI 车牌识别器!(附详细分析)
6.WiFi芯片出现Kr00k漏洞
免责声明:本文系网络转载,版权归原作者所有。如涉及作品版权问题,请与我们联系,我们将根据您提供的版权证明材料确认版权并支付稿酬或者删除内容。