实测STM32F4中printf的效率问题

实测STM32F4中printf的效率问题

一直认为printf所做的工作就是格式化字符串,然后依次调用fputc函数发送出去。于是以前都认为printf函数的瓶颈是在fputc这里,是因为发送一个字节所占的时间太长,才导致printf效率慢。也就是说,一直认为如果串口的波特率设置成115200的话,printf至少也是能达到115200的波特率的。

而这几天在学习ucOS,于是想到,如果printf的瓶颈是在等在串口发送完成的话,那么我在等待串口发送完成中断的时候是不是挂起一个信号量,然后就可以去做点别的事情了呢?这也正是RTOS的目的之一嘛————最大化利用CPU。

花了点时间时间试了下之后,发现完全没有改善!于是有了测试两次进入fputc间隔时间的想法。

测试环境:MDK5.12 + 自带STM32F4 HAL层 + UCOS3.04.04
硬件平台:安富莱V5板卡,主芯片STM32F407IG,USB转串口线CH430芯片,ThinkPad T420

代码如下:

  1. int fputc(int ch, FILE *f)
  2. {
  3. OS_ERR err;
  4. CPU_TS ts;
  5. Dbg_printf_time[Dbg_printf_cnt++] = STK_VAL_REG; //进入函数前读取systick的寄存器值
  6. Dbg_printf_inter[Dbg_printf_cnt] = Dbg_printf_time[Dbg_printf_cnt-2] - Dbg_printf_time[Dbg_printf_cnt-1];//用刚读取的寄存器值减去上一次退出该函数的寄存器值,从而得到两次进入该函数之间的时间
  7. while (HAL_UART_Transmit_IT(&huart, (uint8_t *)&ch, 1) != HAL_OK)
  8. {
  9. OSTaskSemPend(10, OS_OPT_PEND_BLOCKING, &ts, &err);
  10. //check “err”
  11. }
  12. Dbg_printf_time[Dbg_printf_cnt++] = STK_VAL_REG; //退出函数前读取systick的寄存器值
  13. Dbg_printf_inter[Dbg_printf_cnt] = Dbg_printf_time[Dbg_printf_cnt-2] - Dbg_printf_time[Dbg_printf_cnt-1];//用刚读取的寄存器值减去进入该函数的寄存器值,从而得到两次进入该函数之间的时间
  14. if (Dbg_printf_cnt > 90)
  15. {
  16. Dbg_printf_cnt = 1;
  17. }
  18. return ch;
  19. }

重点关注Dbg_printf_inter的值,结果如下:

可以看到进入两次fputc之间的间隔达到了15937个tick,考虑到主频为168M



time=tick/sysfreq

可以计算得出time=94.86us。

而115200波特率的串口在发送两个Byte之间的时间是:86.5us

也就是说:用115200波特率的速度打印printf就已经把STM32的CPU都耗光了!

实在是好奇printf里面都做了什么??作为库函数,它不应该是精简,效率的典范吗?怎么会这么慢?

抛出这个问题,求高手解答,同时也欢迎像我这么无聊的同学在别的平台上验证两次fputc之间的时间差

时间: 2024-10-25 00:40:45

实测STM32F4中printf的效率问题的相关文章

linux 中printf的使用

linux 中printf的使用printf "helloworld\n"printf 中换行必须加上\n printf '%d %s\n' 1 "abc" [email protected]:~/linux$ a=2[email protected]:~/linux$ printf 'a is %s\n' $aa is 2 使用printf结合变量的使用

编程学习中要注意效率和感受

早一个多月,收到了一位网友的求助信,请我帮他做一道程序题.这样的求助我是不会直接解答的.如果要想通过读程序来学习,可读的程序太多了,不在乎由我写的这一段程序. 我给他的回信是,他可以自己做出来一个版本,无论对错,我们就他的做法进行讨论.这是我认为有效的交流.提问者没有做,靠着人给讲,这种学习方式,可以休矣.无论对错.好坏,他自己做过了,针对他自己的讨论点就出来了.我当时的答复是: 我的时间有限,将你做过的给我发来,并提出具体问题再讨论为佳.在学习中,这种交流的方式(有一个问题,不说自己的见解,直

C/C++中printf和C++中cout的输出格式

C/C++中printf和C++中cout的输出格式 一. Printf 输出格式 C中格式字符串的一般形式为: %[标志][输出最小宽度][.精度][长度]类型,其中方括号[]中的项为可选项.各项的意义介绍如下: 1.类型类型字符用以表示输出数据的类型,其格式符和意义下表所示: 表示输出类型的格式字符 格式字符意义 a 浮点数.十六进制数字和p-计数法(C99) A 浮点数.十六进制数字和p-计数法(C99) c 输出单个字符 d 以十进制形式输出带符号整数(正数不输出符号) e 以指数形式输

Python中字符串查找效率比较

Python中字符串查找方式有多种,常见的有re.match/search or str.find 用一个例子来说明各种方式的效率如下: from timeit import timeit import re def find(string, text): if string.find(text) > -1: pass def re_find(string, text): if re.match(text, string): pass def best_find(string, text): i

GCC中printf四舍五入的原则

VC++ is using Round half away from zero GCC is using Round half to even which is also known as banker's rounding. Nearest integer function In computer science, the nearest integer function of real number x denoted variously by Round(x), is a function

[转] C/C++中printf和C++中cout的输出格式

原文地址 一. Printf 输出格式 C中格式字符串的一般形式为: %[标志][输出最小宽度][.精度][长度]类型,其中方括号[]中的项为可选项.各项的意义介绍如下:1.类型类型字符用以表示输出数据的类型,其格式符和意义下表所示:表示输出类型的格式字符 格式字符意义a                                                                  浮点数.十六进制数字和p-计数法(C99)A                          

Snapman系统中TCC执行效率和C#执行效率对比

Snapman集合了TCC编译器可以直接编译执行C语言脚本,其脚本执行效率和C#编译程序进行效率对比,包括下面3方面: 1.函数执行效率 2.数字转换成字符串 3.字符串的叠加 这是C#代码: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Tex

linux编程中printf显示不加换行的缓冲问题

最近在编写linux网络编程时,总是遇到这样的事,程序逻辑没错误,但是程序运行到某个地方就停在那里了,后来才发现在prinrf()中加入换行能正常运行了,如“ printf("123"); ”改成“ printf("123\n"); ”就好了 慢慢的找到了一篇博文可以解释这个问题:博文链接:http://blog.csdn.net/ferlansue/article/details/7925522 解释如下: printf会把东西送到缓冲区,而如果缓冲区不刷新到话,

linux shell 中 printf 与 echo的区别

     echo echo是非常常用的shell命令.参数如下: -e:打开反斜杠字符backslash-escaped的解析,即对/n,/t等字符进行解析,而不视之为两个字符 -E:关闭反斜杠字符的解析,/n作为两个字符,这是系统缺省模式 -n:删除最后的换行 /a : 发出警告铃音(ALERT or CTRL-G (bell)) /b : 退格(BACKSPACE or CTRL-H ) /c : 删除最后的字符及最后的换行(Omit final NEWLINE ) /e : 删除后面的一