最近在SEGGER的博客上看到Johannes Lask写的一篇关于在调试时使用printf函数从目标MCU输出信息到调试器的文章,自我感觉很有启发,特此翻译此文并推荐给各位同仁。当然限于个人水平,有不当之处恳请指正。原文网址:https://blog.segger.com/getting-printf-output-from-target-to-debugger/

Erich Styger最近发布了一篇《关于如何使用ARM Cortex-M目标上的单线输出(SWO)添加控制台功能》的伟大教程。

这激发了我写一篇在嵌入式目标(包括SWO和RTT)上的调试输出(“printf”)实现的更普遍的文章。

从目标调试输出

有不同的方法来从目标应用程序获取调试输出。

自从早期嵌入式系统以来,已经有了硬件依赖的解决方案,如使用UART或USB CDC。但是应用程序可能已经使用了UART,CDC需要目标硬件上的USB堆栈和USB连接器。

第一个软件解决方案是semihosting。使用semihosting,CPU停止打印输出,并由调试器重新启动“幕后”操作。打印一个消息可能需要几毫秒到几百毫秒的时间,因为这是一个昂贵的操作。调试器需要意识到目标已经停止执行,读取寄存器和内存,写入内存,然后重新启动CPU。这意味着目标CPU在这段时间内不运行。因此,semihosting可以简单地不用于需要实时行为的应用,例如通信栈。另外,semihosting实现是依赖于调试器的,而使用semihosting的应用程序可能在没有连接调试器的情况下运行。

然后还有ARM的SWO跟踪端口和SEGGER的实时传输(RTT)。

单线输出

SWO是由ARM为Cortex-M3,M4和M7设备设计的单引脚接口。引脚可以使用标准调试连接器连接到调试探头,并与SWD接口(而不是JTAG)一起使用。目标MCU可以在CPU引脚上传输数据包,类似于UART TX引脚,时钟速率来自CPU时钟。在调试器上设置SWO需要知道CPU时钟速度。如果应用程序的某些部分在启动前必须在初始化之前进行输出,或者在应用程序运行时时钟速度发生变化,那么这一点尤为重要。SWO不会如semihosting发送输出那样停止CPU。通过SWO的输出速度取决于组态的SWO速度。数据分组,即调试输出分组,以特殊格式编码。这允许发送多达32个数据包类型(刺激),但也会导致一些协议开销,这将以10 MHz SWO速度将事情减慢到〜1.5 us / char。这意味着输出80个字符大约需要120个微秒。要在RTOS或中断程序中使用来自多个任务的SWO,在SWO输出期间应禁用中断,这可能会影响系统的实时行为。

尽管SWO最常用于打印调试消息。它也可用于记录中断进入/退出和功能进入/退出,定期对PC值或内存中的变量进行采样,或者用于事件通知。

Erich全面介绍了如何在调试消息中使用SWO,如何在目标上进行设置,以及如何在主机上获取输出。

实时传输

RTT是SEGGER的调试终端解决方案。它将SWO的优点与其他方法的特点相结合。RTT是一种仅用于软件的解决方案,而不是标准调试连接以外的目标设备上不需要额外的硬件。它可以与任何J-Link一起使用,即使使用诸如J-Link OB,OpenSDA或转换的ST-LINK等小型板载机型。

RTT允许非常高的传输速度,而不会影响目标的实时行为。没有协议开销,打印消息可以在一微秒或更短的时间内完成,基本上只需要做一个单个memcpy()的时间。由于RTT的速度非常快,所以输出可以通过锁定中断来保证线程安全,而这种中断对系统的实时行为影响最小。当目标应用程序正在运行时,输出消息由J-Link读取并传输到主机。

与UART类似,RTT是双向的。您可以从主机向目标应用程序发送输入。双向通信允许您控制目标系统,而无需任何其他输入设备。使用RTT可以实现全功能终端。

RTT实现源代码可以自由地在任何系统中使用,提供功能和自由。

在主机上使用RTT是灵活并且容易的。J-Link软件包括可以与任何调试工具并行使用的RTT Viewer,一个GUI。您还可以使用Telnet客户端连接到调试会话(端口19031)并与目标进行通信。一些调试器甚至直接集成RTT。Embedded Studio和独立调试器Ozone可以在其终端窗口中通过RTT显示目标输出,并且不需要任何其他工具。

概要

printf调用与不同实现的速度比较

在从嵌入式目标执行SWO调试输出之前,只能使用低效或依赖硬件的方法。

使用SWO ARM设计了一个快速的解决方案。它重量轻且快速,但具有一些缩写,因为它仅在某些Cortex-M器件上可用,需要额外的引脚连接到MCU,并且是单向的。

RTT结合了SWO的所有优点,并增加了更多功能。它比SWO更快,不仅限于Cortex-M,允许通过标准调试连接进行双向通信,并且在任何需要系统的实时情况下都是最不具有干扰性的。

当您可以使用RTT时,没有任何理由使用SWO。

通过printf从目标板到调试器的输出的更多相关文章

  1. iOS LLDB调试器和断点调试

    技巧一:运行时修改变量的值 你以前怎么验证是不是某个变量的值导致整段程序不能正常工作?修改代码中的变量的值,然后cmd+r重新启动app?现在你不需要这么做了,只需要设置一个断点,当程序在这进入调试模 ...

  2. 第二章排错的工具:调试器Windbg(下)

    感谢博主 http://book.51cto.com/art/200711/59874.htm 2.2  读懂机器的语言:汇编,CPU执行指令的最小单元2.2.1  需要用汇编来排错的常见情况 汇编是 ...

  3. xcode 调试器 LLDB

    本文完全转载,转载地址:点击这里 你是否曾经苦恼于理解你的代码,而去尝试打印一个变量的值? NSLog(@"%@", whatIsInsideThisThing); 或者跳过一个函 ...

  4. 与调试器共舞 - LLDB 的华尔兹

    你是否曾经苦恼于理解你的代码,而去尝试打印一个变量的值? 1 NSLog(@"%@", whatIsInsideThisThing); 或者跳过一个函数调用来简化程序的行为? 1 ...

  5. 嵌入式调试器原理和各类调试器集锦(JLINK、STLINK、CCDEBUG)

    工欲善其事,必先善其器.调试器在嵌入式开发调试中的重要性不言而喻,单步.断点和监察的效率远高于串口打印.但是,调试器对于一般开发人员往往是一个黑匣子.今天我们就来谈谈调试器的原理,顺便把自己的几类调试 ...

  6. 调试器GDB的基本使用方法

    GDB调试的三种方式: 1. 目标板直接使用GDB进行调试. 2. 目标板使用gdbserver,主机使用xxx-linux-gdb作为客户端. 3. 目标板使用ulimit -c unlimited ...

  7. GDB 调试器使用手冊

    使用GDB: 本文描写叙述GDB,GNU的原代码调试器. (这是4.12版1994年一月.GDB版本号4.16) * 文件夹: * 摘要: GDB的摘要 * 实例: 一个使用实例 * 入门: 进入和退 ...

  8. ARM调试器只能偶尔连接成功问题

    这里分析一个ARM板子JTAG调试器经常连接失败,只能偶尔连上目标板问题. 背景 这是原先另一个部门的板子,在部门合并之后,最近要对这个板子的代码体系进行转移,在过问开发进度时,工程师反映这个板子调试 ...

  9. 把 STM32 bluepill 变成调试器(daplink)

    在调一块 ARM M0 内核的板子,使用官方的 DEMO 板子来调,板子上集成了 daplink 调试器. 为了方便使用,我把目标板跟 daplink 剪开了,然后用杜邦线把 daplink 跟目标板 ...

随机推荐

  1. 一、linux 内核介绍

    参考文档: linux 内核剖析:https://www.ibm.com/developerworks/cn/linux/l-linux-kernel/ 1.1 linux 内核历史 在 20 世纪 ...

  2. 六、文件IO——fcntl 函数 和 ioctl 函数

    6.1 fcntl 函数 6.1.1 函数介绍 #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd ...

  3. treap基本操作

    利用rand保持堆的特性 const int N=; int ls[N],rs[N],v[N],p[N],cnt[N],siz[N]; // 权值 优先级 inline void update(int ...

  4. div行高不确定,文字和图片居中

    // 加在父级div中 垂直居中:align-items:center; display: -webkit-flex;水平居中:justify-content:center; display: -we ...

  5. ubuntu18.04下安装mysql后无法用mysqlworkbench访问

    问题描述:我在ubuntu18.04下执行以下命令安装mysql时遇到了mysqlworkbench无法连接root用户的问题.ubuntu18.04下默认安装mysql时是5.7版本的,但是5.7版 ...

  6. webpack学习笔记——--save-dev和--save

    --save-dev 是你开发时候依赖的东西,--save 是你发布之后还依赖的东西. dependencies是运行时(发布后)依赖,devDependencies是开发时的依赖 比如,你写 ES6 ...

  7. struts2简单入门

    框架是什么,框架有什么作用 框架 实现部分功能的代码. 作用 控制请求和响应. 相对于WEB项目的执行流程 struts2项目搭建流程 配置web.xml 配置前端控制器[核心控制器] ---一个fi ...

  8. undefined symbol

    参考链接:  https://blog.csdn.net/shatterheart/article/details/52440149

  9. 【Thymeleaf】Thymeleaf模板对html实时刷新

    解决方案 spring: thymeleaf: cache: false 修改完html代码后Ctrl+Shift+F9,重新编译即可刷新页面内容!

  10. python(九)迭代器和生成器

    一.迭代 迭代就是逐个并且单向访问容器 (这里的容器暂时指数据类型,比如list和dict) 中的元素的行为.举个例子:将一个长度为五的数组逐个从头到尾(即单向)打印的方式称之为迭代.如下图. > ...