ARM 使用调试接口输出打印信息【RTT原理】

ARM 使用调试接口输出打印信息

      如果使用的是M3或者M4则可以直接使用ITM调试机制进行打印输出,具体请看:

keil+stm32+jlink利用swd方式进行printf输出:http://blog.****.net/shizhe0123/article/details/44178905

浅谈工程师的调试法宝(三)---SWO引脚的巧妙应用:http://www.360doc.com/content/16/1031/15/36367108_602789847.shtml


      如果使用的是M0,那就比较麻烦了,因为M0并不支持ITM机制,也就是上面两篇文章用到的调试方式,证明请看:

     ARMM0手册:

ARM 使用调试接口输出打印信息【RTT原理】

              ARM 使用调试接口输出打印信息【RTT原理】

ARM 使用调试接口输出打印信息【RTT原理】

        

       http://www.360doc.com/content/16/1031/15/36367108_602789847.shtml中提及:

ARM 使用调试接口输出打印信息【RTT原理】

     http://blog.****.net/shizhe0123/article/details/44178905中提及:

ARM 使用调试接口输出打印信息【RTT原理】


        对于M0而言,要是用SWD输出调试内容,只能够通过JLINK提供的RTT机制来实现,具体请看:http://blog.****.net/hongprove/article/details/56012129

ARM 使用调试接口输出打印信息【RTT原理】


RTT原理

本节博客摘录于:http://bbs.eeworld.com.cn/thread-493519-1-1.html

    jlink-rtt的基本原理就是仿真器可以读写目标单片机的内存,单片机cpu和仿真器通过预先明确的协议去访问一个环形缓存区来实现通信交互,仿真器再和电脑主机进行通信,最终完成单片机系统内核和电脑客户端间的人机交互。每个环形缓存区只能实现一个方向的通信,如cpu写数据仿真器读数据,即CPU发送信息到电脑;或仿真器写数据CPU读数据,即电脑向CPU发送信息。所以要实现双向通信需要两个环形缓冲区,还要有一个记录读写状态的控制块,合起来为一个双向信道。可以是多信道通信方便不同应用需求,但MsgOS中只使用一个双向信道用来做标准输入输出。在CPU中jlink-rtt通信除去代码部分还得有个总体的控制块来打包所有信道的内存变量,标注rtt一些重要参数,最总要的是在其实部位标注“SEGGER RTT”来告诉仿真器rtt控制块在这里放置。

    启动rtt通信时,仿真器先启动单片机仿真接口为swd,仿真接口启动后仿真器就可以读写单片机任意地址内存了,他根据pc端配置值对单片机内存扫描寻找“SEGGER RTT”字串,或者直接按配置值找到rtt控制块,接下来便可以通过环形缓存区和cpu进行通信了。

    相比于串口网络等接口打印调试信息或shell交互,rtt不涉及单片机特定外设,只需要耗费一些内存便可以通信,通用性可移植性极强。
swo接口虽然也是CPU内核支持通信模块,也不涉及单片机特定外设,但需要占用一个单片机引脚通信速补也低于rtt,最关键的是swo接口只能由CPU输出信息而不能接收外部输入信息不能双向通信这在shell交互上是无法接受的。

缺点是只能用jlink实现,stlink,ulink等仿真器无法使用。通信是需要先通过jlink的特定软件来启动仿真接口。

总得来讲人机交互接口会使得系统开发调试变得极为方便快捷,而jlinkRTT则是使人机交互接口的实现变得方便简洁。


官方介绍地址
https://www.segger.com/jlink-rtt.html

以下是官方部分内容摘取:

SEGGER's Real Time Transfer (RTT) is the new technology for interactive user I/O in embedded applications. It combines the advantages of SWO and semihosting at very high performance.
Main features

  • Bi-directional communication with the target application.
  • Very high transfer speed without affecting real-time behavior.
  • No additional hardware or pin on target required.
  • Supported by any J-Link model.
  • Supported by ARM Cortex-M0/M0+/M1/M3/M4/M7 and Renesas RX100/200/600.
  • Complete implementation code providing functionality and freedom.
  • What is RTT?
    With RTT it is possible to output information from the target microcontroller as well as sending input to the application at a very high speed without affecting the target's real time behavior.
    SEGGER RTT can be used with any J-Link model and any supported target processor which allows background memory access, which are Cortex-M and RX targets.
    RTT supports multiple channels in both directions, up to the host and down to the target, which can be used for different purposes and provide the most possible freedom to the user.
    The default implementation uses one channel per direction, which are meant for printable terminal input and output. With the J-Link RTT Viewer this channel can be used for multiple "virtual" terminals, allowing to print to multiple windows (e.g. one for standard output, one for error output, one for debugging output) with just one target buffer. An additional up (to host) channel can for example be used to send profiling or event tracing data.
  • ARM 使用调试接口输出打印信息【RTT原理】
  • RTT Communication
    Communication with the RTT implementation on the target can be done with different applications. The functionality can even be integrated into custom applications using the J-Link SDK.
    Using RTT in the target application is made easy. The implementation code is freely available for download and can be integrated into any existing application. To communicate via RTT any J-Link can be used.
    The simple way to communicate via the Terminal (Channel 0) is to create a connection to localhost:19021 with a Telnet client or similar, when a connection to J-Link (e.g. via a debug session) is active.
    The J-Link Software Package comes with some more advanced applications for different purposes.
  • How RTT worksTarget implementation
    Real Time Transfer uses a SEGGER RTT Control Block structure in the target's memory to manage data reads and writes.
    The control block contains an ID to make it findable in memory by a connected J-Link and a ring buffer structure for each available channel, describing the channel buffer and its state.
    The maximum number of available channels can be configured at compile time and each buffer can be configured and added by the application at run time. Up and down buffers can be handled separately.
    Each channel can be configured to be blocking or non-blocking. In blocking mode the application will wait when the buffer is full, until all memory could be written, resulting in a blocked application state but preventing data from getting lost. In non-blocking mode only data which fits into the buffer, or none at all, will be written and the rest will be discarded. This allows running in real-time, even when no debugger is connected. The developer does not have to create a special debug version and the code can stay in place in a release application.
    ARM 使用调试接口输出打印信息【RTT原理】
    Locating the control block
    When RTT is active on the host computer, either by using RTT directly via an application like RTT Viewer or by connecting via Telnet to an application which is using J-Link, like a debugger, J-Link automatically searches for the SEGGER RTT Control Block in the target's known RAM regions. The RAM regions or the specific address of the Control Block can also be set via the host applications to speed up detection or it the block cannot be found automatically.
    Internal structures
    The image shows the simplified structure in the target.
    There may be any number of "Up Buffer Descriptors" (Target -> Host), as well as any number of "Down Buffer Descriptors" (Host -> Target). Each buffer size can be configured individually.
    The gray areas in the buffers are the areas that contain valid data.
    For Up buffers, the Write Pointer is written by the target, the Read Pointer is written by the debug probe (J-Link, Host).
    When Read and Write Pointers point to the same element, the buffer is empty. This assures there is never a race condition.
    Requirements
    SEGGER RTT dies not need any additional pin or hardware, despite a J-Link connected via the standard debug port to the target. It does not require any configuration of the target or in the debugging environment and can even be used with varying target speeds.
    RTT can be used in parallel to a running debug session, without intrusion, as well as without any IDE or debugger at all.




Performance
The performance of SEGGER RTT is significantly higher than any other technology used to output data to a host PC. An average line of text can be output in one microsecond or less. Basically only the time to do a single memcopy().
ARM 使用调试接口输出打印信息【RTT原理】
The speed comparison was done on an STM32F407 Cortex-M4 running at 168 MHz . Overhead for printf() calls removed.

FAQ
Q:
How does J-Link find the RTT buffer?
A:        There are 2 ways: If the Debugger (IDE) knows the address of the SEGGER_RTT structure, it passes it to J-Link. This is for example done by J-Link Debugger. If an other debugger that is not SEGGER-RTT aware is used, such as IAR's Embedded Workbench or emIDE, then J-Link searches for the ID in the known target RAM during execution of the program, transparently in the background. The process of locating the ID string takes just fractions of a second and does not delay program execution.
         
Q:        I am debugging a RAM-only application. J-Link finds an RTT buffer, but I get no output. What can I do?
A:
In case the init section of an application is stored in RAM, J-Link might falsely identify the block in the init section instead of the actual one in the data section.
To prevent this, set the define SEGGER_RTT_IN_RAM to 1. Now J-Link will find the correct RTT buffer, but only after calling the first SEGGER_RTT function in the application. A call to SEGGER_RTT_Init() at the beginning of the application is recommended.
         
Q:        Can this also be used on targets that do not have the SWO pin?
A:        Yes, the debug interface is used. This can be JTAG or SWD (2pins only!) on most Cortex-M devices, or even the FINE interface on some Renesas devices, just like the Infineon SPD interface (single pin!)
         
Q:
Can this also be used on Cortex-M0 and M0+?
A:        Yes.
         
Q:
Some terminal output (printf) Solutions "crash" program execution when executed outside of the debug environment, because they use a Software breakpoint that triggers a hardfault without debugger or halt because SWO is not initialized. That makes it impossible to run a Debug-build in stand-alone mode.
What about SEGGER-RTT?
A:        SEGGER-RTT uses non-blocking mode per default, which means it does not halt program execution if no debugger is present and J-Link is not even connected. The application program will continue to work.
         
Q:        I do not see any output, although the use of RTT in my application is correct. What can I do?
A:
In some cases J-Link cannot locate the RTT buffer in the known RAM region.
In this case the possible region or the exact address can be set manually via a J-Link exec command:
Set ranges to be searched for RTT buffer: SetRTTSearchRanges <RangeStart [Hex]> <RangeSize >[, <Range1Start [Hex]> <Range1Size>, ...] (e.g. "SetRTTSearchRanges 0x10000000 0x1000, 0x2000000 0x1000")
Set address of the RTT buffer: SetRTTAddr <RTTBufferAddress [Hex]> (e.g. "SetRTTAddr 0x20000000")
Set address of the RTT buffer via J-Link Control Panel -> RTT
J-Link exec commands can be executed in most applications, for example in J-Link Commander via "exec <Command>", in J-Link GDB Server via "monitor exec <Command>" or in IAR EW via "__jlinkExecCommand("<Command>");" from a macro file.
         
Q:        Is it possible to call SetRTTAddr with the dynamic value of the RTT buffer?
A:
Yes. For most debuggers/IDEs this can be done.
With GDB the command can be created and executed with eval. The GDB command will be:
eval "monitor exec SetRTTAddr %p", &_SEGGER_RTT
In IAR the command can be created in a macro file funciton like this:
Set_RTT_Address () {
  __var addr;
  __var str;
  addr = &_SEGGER_RTT;
  str = __smessage "SetRTTAddr ",addr:%x;
  __jlinkExecCommand(str);
}