场景:
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)();
}
}