RTT打印仅占用JLINK的带宽,比串口传输更快更简洁,同时RTT可以使用jscope对代码里面的变量实时绘图显示波形,而采用串口打印波形无法实时打印。同时可以保存原始数据到本地进行分析,RTT在各方面完胜串口。
正常使用RTT没有太大的问题,而对FLASH进行分区后,跳转不同的分区需要重新连接RTT才可以输出,造成极大的不便。
RTT跳转后,都会重新初始化RTT的block地址,就会导致RTT VIEWER不能及时识别新的blcik地址,从对应的地址取数据显示了。那么通过固定RTT的block地址是不是就可以了,打开SEGGER_RTT.c在290行的位置,注销_SEGGER_RTT
_acDownBuffer
_acUpBuffer
的初始化,将其固定在0x2000000的地址,如下:
// #if SEGGER_RTT_CPU_CACHE_LINE_SIZE
// #if ((defined __GNUC__) || (defined __clang__))
// SEGGER_RTT_CB _SEGGER_RTT __attribute__ ((aligned (SEGGER_RTT_CPU_CACHE_LINE_SIZE)));
// static char _acUpBuffer [SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_UP)] __attribute__ ((aligned (SEGGER_RTT_CPU_CACHE_LINE_SIZE)));
// static char _acDownBuffer[SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_DOWN)] __attribute__ ((aligned (SEGGER_RTT_CPU_CACHE_LINE_SIZE)));
// #elif (defined __ICCARM__)
// #pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE
// SEGGER_RTT_CB _SEGGER_RTT;
// #pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE
// static char _acUpBuffer [SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_UP)];
// #pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE
// static char _acDownBuffer[SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_DOWN)];
// #else
// #error "Don't know how to place _SEGGER_RTT, _acUpBuffer, _acDownBuffer cache-line aligned"
// #endif
// #else
// SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT));
// SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer [BUFFER_SIZE_UP]));
// SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN]));
// #endif
__attribute__((section(".ARM.__at_0x20000000"))) SEGGER_RTT_CB _SEGGER_RTT;
__attribute__((section(".ARM.__at_0x200000B0"))) static char _acDownBuffer[BUFFER_SIZE_DOWN];
__attribute__((section(".ARM.__at_0x200000C0"))) static char _acUpBuffer[BUFFER_SIZE_UP];
但是发现还是不行,每次烧录完芯片都要重新连接RTT,而且要很久,RTT每次都要搜索地址很费时间,搜索block后,分区都已经跳转完毕,跳转前的信息无法查看。最后需要RTT VIEWER中的地址为固定地址后就实时打印跳转的信息了。
测试后发现分区跳转后可以打印,但是还是存在偶尔打印缺失的情况,查找后发现block中还有内容未被RTT VIEWER读取就执行了跳转,block里面的内容被重置,也就无法读取了,在跳转前判断一下block是否还有内容就Ok了,跳转的内容如下:
uint32_t *inputAddr; // !声明为全局变量,防止执行__set_MSP后,变量被释放
uint32_t jumpAddr; // !设置MSP后改变了栈底地址,导致原来的局部变量范围出了新栈的空间,被系统释放
void JumpToCode(uint32_t addr) {
inputAddr = (uint32_t *)addr;
jumpAddr = *(uint32_t *)(addr + 4);
if ((*inputAddr & 0x2FFE0000) == 0x20000000) {
// 等待rtt打印完毕 超时退出, rtt viewer中需要指定block地址,避免搜索地址耗费太长时间
uint32_t start = HAL_GetTick();
while (SEGGER_RTT_GetBytesInBuffer(0) > 0) {
if (HAL_GetTick() - start > 100)
break;
}
HAL_RCC_DeInit();
HAL_DeInit();
__set_FAULTMASK(1);
__set_CONTROL(0);
__set_MSP(*inputAddr);
((void (*)(void))jumpAddr)();
}
}
#ifndef LOG_H
#define LOG_H
#include "SEGGER_RTT.h"
#define USE_LOG_DEBUG 1
#define TERMINAL_0 0
#define TERMINAL_1 1
#define TERMINAL_2 2
#define TERMINAL_3 3
#define TERMINAL_4 4
#define TERMINAL_5 5
#if USE_LOG_DEBUG
#define LOG_PROTO(type, color, format, ...) SEGGER_RTT_printf(0, " %s%s" format "\r\n%s", color, type, ##__VA_ARGS__, RTT_CTRL_RESET)
#define LOG_INFO(format, ...) LOG_PROTO("[INFO]:", "", format, ##__VA_ARGS__) // 无颜色日志输出
#define LOG_DEBUG(format, ...) LOG_PROTO("[DEBUG]:", RTT_CTRL_TEXT_BRIGHT_GREEN, format, ##__VA_ARGS__) // 绿色日志输出
#define LOG_WARN(format, ...) LOG_PROTO("[WARN]:", RTT_CTRL_TEXT_BRIGHT_YELLOW, format, ##__VA_ARGS__) // 黄色日志输出
#define LOG_ERROR(format, ...) LOG_PROTO("[ERROR]:", RTT_CTRL_TEXT_BRIGHT_RED, format, ##__VA_ARGS__) // 红色日志输出
#define LOG_CLEAR() SEGGER_RTT_WriteString(0, "\r\n" RTT_CTRL_CLEAR) // 清屏
// 打印数组
#define LOG_ARRAY(pbuf, len, terminal) \
do { \
SEGGER_RTT_SetTerminal(terminal); \
uint8_t* _pbuf = (pbuf); \
int _len = (len); \
for (int _i = 0; _i < _len; _i++) { \
SEGGER_RTT_printf(0, "%02x ", _pbuf[_i]); \
} \
SEGGER_RTT_printf(0, "\r\n"); \
SEGGER_RTT_SetTerminal(0); \
} while (0)
#else
#define LOG_INFO(format, ...)
#define LOG_DEBUG(format, ...)
#define LOG_WARN(format, ...)
#define LOG_ERROR(format, ...)
#define LOG_CLEAR()
#define LOG_ARRAY(pbuf, len, terminal)
#endif
#endif
同时RTT不能打印浮点数,RTT的格式化字符串函数没有对浮点进行格式化,可以手动添加即可,参考了某论坛的(找不到出处了),在SEGGER_RTT_printf.c的523行switch的default语句前面添加下面的case
case 'f': // 添加输出浮点数的功能。默认带两位小数。
case 'F': {
float fv = (float)va_arg(*pParamList, double); // 取出输入的浮点数值
if (fv < 0)
_StoreChar(&BufferDesc, '-'); // 判断正负号
v = abs((int)fv); // 取正整数部分
_PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags); // 显示整数
_StoreChar(&BufferDesc, '.'); // 显示小数点
v = abs((int)(fv * 100));
v = v % 100;
_PrintInt(&BufferDesc, v, 10u, 2, FieldWidth, FormatFlags); // 显示小数点后两位
break;
}