古老、经过验证且真正的调试技术是在整个嵌入式软件中散布printf语句,以期获得对系统行为的洞察力。嵌入式开发人员使用printf并不总是可取的,并且可能会对系统产生不可预见的实时影响。让我们检查一下printf的基本问题,然后是一些可用于从中获得最大性能的技术。

了解printf的问题

使用printf会带来一些开发人员经常忽略的问题。首先,开发人员必须引入一个标准的C库,这无疑会增加ROM和RAM的使用。其次,每次使用printf stamen 时,系统都会阻塞,直到所有字符都已传输完毕,这会导致实时性能显着下降。举个例子,输出一个简单的字符串,例如“Hello World!”在9600处打印出UART(仍然很常见)。例如在STM32上执行了一个简单的时序测量,如图1所示,格式化字符串并打印到终端需要12.5毫秒。

图 1 – 打印“Hello World!”

添加任何字符串格式会使情况变得更糟!使用 printf(“The system state is %d”, State) 将系统状态打印到终端会导致21毫秒的应用程序延迟,因为字符串被格式化和传输。有人可能会争辩说,以9600波特运行是荒谬的,但即使增加到 115200仍然会分别导致传输这两条消息的时间分别为1.05和1.75毫秒。大量处理器带宽和潜在的实时性能会影响最少的有用信息。

性能技巧 1 – 创建非阻塞printf

如果printf 版本是阻塞类型,嵌入式开发人员一旦调用 printf,应用程序就会停止执行,直到每个字符都被成功传输,效率低得惊人!另一种方法是创建一个非阻塞版本,非阻塞printf版本将

格式化字符串

将格式化的字符串填充到传输缓冲区中

启动第一个字符的传输

让中断服务程序处理发送缓冲区中的剩余字符

继续执行代码

非阻塞printf的最大亮点是设置时间,在9600波特的STM32上它在0.8到1.8毫秒之间变化。在初始设置时间之后,发送中断大约每毫秒发生一次,需要35微秒将下一个字符填充到UART发送寄存器中,然后再返回执行有用的工作。图 2 显示了周期性中断以及中断执行时间。请记住,执行时间不包括在这种情况下少于25个时钟周期的中断开销。

图 2 – 非阻塞 printf 性能

性能技巧 2 – 提高波特率

许多嵌入式开发人员仍将他们的UART默认设置为9600,今天的串行硬件可以处理1 Mbps 或更高的波特率!有些足够大胆的人将波特率设置为115200。除非运行时钟存在潜在的电气或硬件相关问题,否则将波特率设置为1 Mbps并将调试消息输出为尽可能快,以尽量减少实时性能问题。 “Hello World!”的原始阻塞 printf只会阻塞120微秒,远比12.5毫秒更可接受。

性能技巧3 – 使用SWD

现代微控制器在开发芯片时考虑到了printf性能问题。例如,利用ARM Cortex-M 部件的调试功能的开发人员可以跳过UART并使用内部调试模块将printf消息通过调试器传输回IDE。以这种方式跳过UART不仅可以节省设置,而且内部硬件机制可以最大限度地减少软件开销!内部缓冲区充满消息,调试硬件自动处理传输到调试探针的传输,从而将对应用程序实时性能的影响降至最低。

结论

很少有嵌入式开发人员会放弃他们最喜欢的、尝试过的、真正的printf调试技术。在当今的现代微控制器硬件中,有多种选项可以提高printf的性能和效率,从而最大限度地减少对实时性能的影响。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部