http://segger.com/jlink-real-time-terminal.html
Real Time Terminal
SEGGER's Real Time Terminal (RTT) is the new technology for interactive user I/O in embedded applications.
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 behaviour.
![](https://i-blog.csdnimg.cn/blog_migrate/2064e4d9246b1795e8e43b7d5b42484f.png)
RTT supports multiple up (to the host) and down (to the target) channels to write and read data of different kinds. The default implementation uses one channel per direction:
Channel | Typical Purpose |
---|---|
Up-channel 0 | Terminal output |
Down-Channel 0 | Keyboard input |
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.
Data from Up-channel 0 can be read via a Telnet connection to localhost:19021, which is opened by the J-Link software locally on the computer, when the J-Link is active. The Telnet connection also receives keyboard input for Down-channel 0.
The J-Link RTT Client, which automatically connects and re-connects to an open J-Link connection is part of the J-Link Software and Documentation Pack and can be used instead of a simple Telnet client.
With J-Link RTT Logger, data from Up-Channel 1 can be read and logged to a file. This channel can for example be used to send performance analysis data to the host.
J-Link RTT Logger opens a dedicated connection to J-Link and can be used stand-alone, without running a debugger.
The application is part of the J-Link Software and Documentation Pack.
//
// Allocate buffers for channel 0
//
static char _acUpBuffer [BUFFER_SIZE_UP];
static char _acDownBuffer[BUFFER_SIZE_DOWN];
//
// Initialize SEGGER Real-time-Terminal control block (CB)
//
static SEGGER_RTT_CB _SEGGER_RTT = {
"SEGGER RTT",
SEGGER_RTT_MAX_NUM_UP_BUFFERS,
SEGGER_RTT_MAX_NUM_DOWN_BUFFERS,
{{ "Terminal", &_acUpBuffer[0], sizeof(_acUpBuffer), 0, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP }},
{{ "Terminal", &_acDownBuffer[0], sizeof(_acDownBuffer), 0, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP }},
};
_SEGGER_RTT 会有两个副本, 第一个副本用来初始化第二个副本
当在FLASH中运行, 第一个副本位于FLASH, 第二个副本位于SRAM, 程序启动时, 从第一个副本复制到第二个副本.
这样在SRAM中只有一个字符串 "SEGGER RTT" RTT 可以正确定位 _SEGGER_RTT 在 SRAM 中的地址 ( 搜索整个SRAM区域 )
当在SRAM中运行, 两个副本均在 SRAM, 这样 RTT 可能错误定位 _SEGGER_RTT 于用来初始化第二个副本的第一个副本
用来初始化第二个副本的第一个副本的 RING_BUFFER 的 WrOff 和 RdOff 一直是 0, 所以没有数据可读取.
修改 static SEGGER_RTT_CB _SEGGER_RTT = { "SEGGER RTT", ...
成为 static SEGGER_RTT_CB _SEGGER_RTT = { "SEGGER_RTT", ...
然后添加函数
void SEGGER_RTT_Init( void )
{
_SEGGER_RTT.acID[6] = ' '; // SEGGER RTT
}
然后
SEGGER_RTT_Init(); // 初始化之后, RTT 可以正确定位 _SEGGER_RTT 在 SRAM 中的地址 ( 搜索整个SRAM区域 )
SEGGER_RTT_ConfigUpBuffer( 0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL );
SEGGER_RTT_WriteString( 0, "SEGGER Real-Time-Terminal Sample\r\n\r\n" );
在SRAM调试解决方法
修改 static SEGGER_RTT_CB _SEGGER_RTT = { "SEGGER RTT", ...
成为 static SEGGER_RTT_CB _SEGGER_RTT = { "SEGGER_RTT", ...
然后添加函数
void SEGGER_RTT_Init( int UpFlags, int DownFlags )
{
_SEGGER_RTT.acID[6] = ' '; // SEGGER RTT _SEGGER_RTT.aUp[ 0 ].Flags = UpFlags;
_SEGGER_RTT.aDown[ 0 ].Flags = DownFlags;
}
// 初始化之后, RTT 可以正确定位 _SEGGER_RTT 在 SRAM 中的地址 ( 搜索整个SRAM区域 )
SEGGER_RTT_Init( SEGGER_RTT_MODE_NO_BLOCK_SKIP, SEGGER_RTT_MODE_NO_BLOCK_SKIP );
SEGGER_RTT_WriteString( 0, "SEGGER Real-Time-Terminal Sample\r\n\r\n" );
JLINK RTT 新版本 SRAM 调试解决方案
新版本 SRAM 调试解决方案 : RTT_Implementation_140925.zip // ******************************* SEGGER_RTT_Conf.h ************************************ // // Define SEGGER_RTT_IN_RAM as 1 // when using RTT in RAM targets (init and data section both in RAM). // This prevents the host to falsly identify the RTT Callback Structure // in the init segment as the used Callback Structure. // // When defined as 1, // the first call to an RTT function will modify the ID of the RTT Callback Structure. // To speed up identifying on the host, // especially when RTT functions are not called at the beginning of execution, // SEGGER_RTT_Init() should be called at the start of the application. // #define SEGGER_RTT_IN_RAM (1) // ******************************* SEGGER_RTT.c ************************************ // // Initialize SEGGER Real-time-Terminal control block (CB) // static SEGGER_RTT_CB _SEGGER_RTT = { #if SEGGER_RTT_IN_RAM "SEGGER RTTI", #else "SEGGER RTT", #endif SEGGER_RTT_MAX_NUM_UP_BUFFERS, SEGGER_RTT_MAX_NUM_DOWN_BUFFERS, {{ "Terminal", &_acUpBuffer[0], sizeof(_acUpBuffer), 0, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP }}, {{ "Terminal", &_acDownBuffer[0], sizeof(_acDownBuffer), 0, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP }}, }; /********************************************************************* * * _Init * * Function description * In case SEGGER_RTT_IN_RAM is defined, * _Init() modifies the ID of the RTT CB to allow identifying the * RTT Control Block Structure in the data segment. */ static void _Init(void) { #if SEGGER_RTT_IN_RAM if (_SEGGER_RTT.acID[10] == 'I') { _SEGGER_RTT.acID[10] = '\0'; } #endif } |