嵌入式开发实战JLINK RTT日志打印与高级调试技巧引言在嵌入式系统开发过程中日志输出是调试和问题排查的重要手段。传统上开发者依赖串口输出日志信息但在资源受限或硬件接口不足的场景下这种方法的局限性就显现出来了。JLINK的Real Time TransferRTT技术提供了一种创新的解决方案它不需要额外的硬件接口仅通过调试接口就能实现高效的日志传输。RTT技术最吸引人的地方在于它的实时性和低资源占用。想象一下在调试一个复杂的嵌入式系统时你不再需要为串口线缆的物理连接而烦恼也不必担心串口波特率导致的传输瓶颈。RTT直接在芯片内存中建立通信缓冲区通过JLINK调试器高速读取这些数据实现了近乎实时的日志监控。本文将带你从零开始掌握RTT技术的核心应用包括基础配置、高级颜色控制技巧以及实际项目中的优化策略。无论你是刚接触嵌入式开发的新手还是希望提升调试效率的资深工程师这些内容都将为你的开发工作带来实质性的帮助。1. RTT技术基础与工作原理1.1 RTT架构解析RTT技术的核心在于它在目标设备内存中创建了一个特殊的数据结构——RTT控制块RTT Control Block。这个控制块包含了多个上行和下行通道每个通道都有自己的缓冲区和指针系统。让我们用一个表格来清晰地展示这个结构的组成结构成员数据类型描述acIDchar[16]固定为SEGGER RTT的标识字符串MaxNumUpBuffersint上行缓冲区的最大数量MaxNumUpBuffersint下行缓冲区的最大数量aUpSEGGER_RTT_BUFFER_UP[]上行缓冲区数组aDownSEGGER_RTT_BUFFER_DOWN[]下行缓冲区数组上行通道用于从目标设备向主机通常是开发PC传输数据如日志信息而下行通道则用于从主机向目标设备发送数据比如控制命令。这种双向通信机制使得RTT不仅仅是一个日志工具还能实现更复杂的调试交互。1.2 内存缓冲区管理RTT使用环形缓冲区来管理数据传输这种设计既高效又节省资源。每个通道的缓冲区都有三个关键指针pBuffer指向缓冲区起始地址WrOff写指针指示下一个写入位置RdOff读指针指示下一个读取位置当写指针追上读指针时缓冲区满当读指针追上写指针时缓冲区空。这种设计避免了数据拷贝极大提高了传输效率。在SEGGER_RTT_Conf.h配置文件中你可以调整以下关键参数#define BUFFER_SIZE_UP 1024 // 上行缓冲区大小 #define BUFFER_SIZE_DOWN 16 // 下行缓冲区大小 #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // 最大上行通道数 #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // 最大下行通道数提示对于日志量大的应用适当增大BUFFER_SIZE_UP可以防止数据丢失但会占用更多RAM空间。1.3 与串口日志的对比理解RTT与传统串口日志的区别有助于我们在不同场景下做出合适选择特性RTT日志串口日志硬件需求仅需调试接口需要专用串口硬件速度高速通常1MB/s受波特率限制通常1MB/s资源占用少量RAM需要UART外设和引脚实时性极高受波特率影响多通道支持是通常单通道双向通信是通常单向从对比中可以看出RTT在大多数调试场景下都具有明显优势特别是在高速数据传输和实时性要求高的场合。2. 快速配置RTT日志系统2.1 环境准备与基础配置要在项目中使用RTT功能首先需要确保你的开发环境满足以下要求硬件需求支持JLINK调试的硬件平台兼容的JLINK调试器如JLINK BASE以上版本软件组件SEGGER J-Link软件包包含RTT源代码嵌入式开发工具链如Keil、IAR或GCCRTT Viewer工具随JLINK软件包安装将RTT组件添加到项目中的步骤如下从JLINK安装目录通常位于C:\Program Files (x86)\SEGGER\JLink\Samples\RTT复制以下文件到你的项目目录SEGGER_RTT.cSEGGER_RTT.hSEGGER_RTT_Conf.h在项目配置中添加这些文件的编译SRCS SEGGER_RTT.c INCLUDES -I/path/to/rtt/files根据你的目标平台修改SEGGER_RTT_Conf.h中的配置参数// 调整缓冲区大小以适应你的应用需求 #define BUFFER_SIZE_UP (1024) #define BUFFER_SIZE_DOWN (16) // 在资源受限的设备上可以减少通道数量 #define SEGGER_RTT_MAX_NUM_UP_BUFFERS (1) #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (1)2.2 基础日志输出方法RTT提供了多种日志输出函数满足不同场景的需求简单字符串输出#include SEGGER_RTT.h void log_test(void) { SEGGER_RTT_Write(0, Hello, RTT!\n, sizeof(Hello, RTT!\n)); }第一个参数0表示使用上行通道0第二个参数是要输出的字符串第三个参数是字符串长度格式化输出int value 42; SEGGER_RTT_printf(0, The answer is %d\n, value);SEGGER_RTT_printf支持标准的printf格式化语法使用起来非常方便。多通道输出你可以配置多个上行通道将不同类型的日志分开// 通道0用于普通日志 SEGGER_RTT_Write(0, System started\n, 15); // 通道1用于错误信息 SEGGER_RTT_Write(1, ERROR: Sensor timeout\n, 22);2.3 RTT Viewer工具使用SEGGER提供的RTT Viewer是查看RTT日志的主要工具其基本使用步骤如下启动RTT Viewer并连接目标设备选择正确的JLINK型号和目标芯片设置正确的接口速度通常自动检测即可配置RTT控制块地址方法一自动搜索适用于大多数情况方法二手动指定在map文件中查找_SEGGER_RTT的地址终端窗口操作可以打开多个终端标签分别监控不同通道支持基本的文本操作如清除屏幕、保存日志等注意如果遇到连接问题尝试降低JLINK接口速度或检查目标板供电是否稳定。3. 高级颜色控制技巧3.1 RTT颜色控制原理RTT Viewer支持ANSI转义序列允许你在日志中添加颜色信息极大地提升了日志的可读性。颜色控制通过特殊的控制序列实现这些序列定义在SEGGER_RTT.h中控制序列效果RTT_CTRL_RESET重置所有属性RTT_CTRL_TEXT_BLACK黑色文本RTT_CTRL_TEXT_RED红色文本RTT_CTRL_TEXT_GREEN绿色文本RTT_CTRL_TEXT_YELLOW黄色文本RTT_CTRL_TEXT_BLUE蓝色文本RTT_CTRL_TEXT_MAGENTA品红色文本RTT_CTRL_TEXT_CYAN青色文本RTT_CTRL_TEXT_WHITE白色文本RTT_CTRL_BG_BLACK黑色背景RTT_CTRL_BG_RED红色背景RTT_CTRL_BG_GREEN绿色背景RTT_CTRL_BG_YELLOW黄色背景RTT_CTRL_BG_BLUE蓝色背景RTT_CTRL_BG_MAGENTA品红色背景RTT_CTRL_BG_CYAN青色背景RTT_CTRL_BG_WHITE白色背景3.2 实际应用示例让我们看几个颜色控制的实际例子基本颜色应用// 红色错误信息 SEGGER_RTT_Write(0, RTT_CTRL_TEXT_RED Error: Sensor failure! RTT_CTRL_RESET \n, sizeof(RTT_CTRL_TEXT_RED Error: Sensor failure! RTT_CTRL_RESET \n)); // 带背景色的警告信息 SEGGER_RTT_printf(0, RTT_CTRL_BG_YELLOW RTT_CTRL_TEXT_BLUE Warning: Low battery (%d%%) RTT_CTRL_RESET \n, battery_level);创建彩色日志宏为了简化代码可以定义一些实用的宏#define LOG_ERROR(fmt, ...) \ SEGGER_RTT_printf(0, RTT_CTRL_TEXT_RED ERROR: fmt RTT_CTRL_RESET \n, ##__VA_ARGS__) #define LOG_WARNING(fmt, ...) \ SEGGER_RTT_printf(0, RTT_CTRL_TEXT_YELLOW WARN: fmt RTT_CTRL_RESET \n, ##__VA_ARGS__) #define LOG_INFO(fmt, ...) \ SEGGER_RTT_printf(0, RTT_CTRL_TEXT_GREEN INFO: fmt RTT_CTRL_RESET \n, ##__VA_ARGS__) // 使用示例 LOG_ERROR(File not found: %s, filename); LOG_INFO(System initialized, version %s, version);多颜色组合你可以在一条日志中组合多种颜色效果SEGGER_RTT_printf(0, RTT_CTRL_TEXT_BLUE [ RTT_CTRL_TEXT_WHITE %s RTT_CTRL_TEXT_BLUE ] RTT_CTRL_TEXT_GREEN %s RTT_CTRL_RESET \n, module_name, message);3.3 颜色使用最佳实践在项目中使用颜色日志时建议遵循以下准则保持一致性在整个项目中统一颜色使用规范比如红色始终表示错误黄色表示警告等适度使用不要过度使用颜色否则会适得其反降低可读性考虑背景确保文本颜色与背景有足够的对比度提供无颜色选项有些环境可能不支持颜色应提供回退方案以下是一个推荐的日志颜色方案日志级别颜色适用场景FATAL红色闪烁系统无法继续运行的严重错误ERROR红色需要立即关注的错误WARNING黄色潜在问题或异常情况INFO绿色常规运行信息DEBUG青色调试信息TRACE蓝色详细跟踪信息4. 实战技巧与性能优化4.1 解决地址变化问题在开发过程中每次重新编译后_SEGGER_RTT变量的地址可能会发生变化这会导致RTT Viewer需要重新配置。有几种方法可以解决这个问题固定地址分配使用GCC的__attribute__语法将RTT控制块固定在特定内存地址SEGGER_RTT_CB _SEGGER_RTT __attribute__((section(.rtt_section), aligned(16))); // 在链接脚本中添加 .rtt_section 0x20000000 : { KEEP(*(.rtt_section)) }自动地址检测在RTT Viewer中启用Auto Detection选项它会自动扫描内存查找RTT控制块。通过map文件获取地址创建一个脚本自动从map文件中提取地址并更新RTT Viewer配置。4.2 性能优化策略为了确保RTT日志系统的高效运行特别是在资源受限的嵌入式系统中可以考虑以下优化措施缓冲区大小调优根据实际日志量调整BUFFER_SIZE_UP监控缓冲区使用情况int buf_usage SEGGER_RTT_GetAvailWriteSpace(0); SEGGER_RTT_printf(0, Buffer free space: %d\n, buf_usage);日志级别控制实现动态日志级别过滤避免生产环境输出过多调试信息#define LOG_LEVEL_DEBUG 0 #define LOG_LEVEL_INFO 1 #define LOG_LEVEL_WARN 2 #define LOG_LEVEL_ERROR 3 extern int current_log_level; #define LOG_DEBUG(fmt, ...) \ if(current_log_level LOG_LEVEL_DEBUG) \ SEGGER_RTT_printf(0, fmt, ##__VA_ARGS__)异步日志记录对于时间敏感的应用可以考虑将日志先存入临时缓冲区在非关键时段批量写入RTT。4.3 多任务环境下的RTT使用在RTOS或多任务环境中使用RTT时需要注意线程安全问题互斥保护// 使用RTOS的互斥量保护RTT访问 void safe_rtt_printf(const char *fmt, ...) { osMutexAcquire(rtt_mutex, osWaitForever); va_list args; va_start(args, fmt); SEGGER_RTT_vprintf(0, fmt, args); va_end(args); osMutexRelease(rtt_mutex); }任务专用通道为每个重要任务分配独立的RTT通道便于调试#define TASK1_CHANNEL 1 #define TASK2_CHANNEL 2 void task1(void) { SEGGER_RTT_printf(TASK1_CHANNEL, Task1 running\n); }时间戳添加在日志中添加精确的时间戳uint32_t get_timestamp(void) { return osKernelGetTickCount(); } #define LOG_TIMED(fmt, ...) \ SEGGER_RTT_printf(0, [%08lu] fmt, get_timestamp(), ##__VA_ARGS__)4.4 高级调试技巧数据可视化RTT Viewer支持简单的数据绘图功能可以用于实时显示传感器数据// 发送数据到图形窗口 float sensor_data read_sensor(); SEGGER_RTT_Write(2, sensor_data, sizeof(sensor_data));交互式调试使用下行通道实现简单的命令行接口char cmd[32]; if(SEGGER_RTT_HasKey()) { int len SEGGER_RTT_Read(0, cmd, sizeof(cmd)-1); cmd[len] \0; process_command(cmd); }崩溃信息捕获在异常处理程序中输出关键信息void HardFault_Handler(void) { SEGGER_RTT_printf(0, RTT_CTRL_TEXT_RED Hard Fault occurred!\n); // 输出寄存器内容等调试信息 while(1); }
嵌入式开发必备:5分钟搞定JLINK RTT日志打印(附颜色控制技巧)
发布时间:2026/6/23 11:34:05
嵌入式开发实战JLINK RTT日志打印与高级调试技巧引言在嵌入式系统开发过程中日志输出是调试和问题排查的重要手段。传统上开发者依赖串口输出日志信息但在资源受限或硬件接口不足的场景下这种方法的局限性就显现出来了。JLINK的Real Time TransferRTT技术提供了一种创新的解决方案它不需要额外的硬件接口仅通过调试接口就能实现高效的日志传输。RTT技术最吸引人的地方在于它的实时性和低资源占用。想象一下在调试一个复杂的嵌入式系统时你不再需要为串口线缆的物理连接而烦恼也不必担心串口波特率导致的传输瓶颈。RTT直接在芯片内存中建立通信缓冲区通过JLINK调试器高速读取这些数据实现了近乎实时的日志监控。本文将带你从零开始掌握RTT技术的核心应用包括基础配置、高级颜色控制技巧以及实际项目中的优化策略。无论你是刚接触嵌入式开发的新手还是希望提升调试效率的资深工程师这些内容都将为你的开发工作带来实质性的帮助。1. RTT技术基础与工作原理1.1 RTT架构解析RTT技术的核心在于它在目标设备内存中创建了一个特殊的数据结构——RTT控制块RTT Control Block。这个控制块包含了多个上行和下行通道每个通道都有自己的缓冲区和指针系统。让我们用一个表格来清晰地展示这个结构的组成结构成员数据类型描述acIDchar[16]固定为SEGGER RTT的标识字符串MaxNumUpBuffersint上行缓冲区的最大数量MaxNumUpBuffersint下行缓冲区的最大数量aUpSEGGER_RTT_BUFFER_UP[]上行缓冲区数组aDownSEGGER_RTT_BUFFER_DOWN[]下行缓冲区数组上行通道用于从目标设备向主机通常是开发PC传输数据如日志信息而下行通道则用于从主机向目标设备发送数据比如控制命令。这种双向通信机制使得RTT不仅仅是一个日志工具还能实现更复杂的调试交互。1.2 内存缓冲区管理RTT使用环形缓冲区来管理数据传输这种设计既高效又节省资源。每个通道的缓冲区都有三个关键指针pBuffer指向缓冲区起始地址WrOff写指针指示下一个写入位置RdOff读指针指示下一个读取位置当写指针追上读指针时缓冲区满当读指针追上写指针时缓冲区空。这种设计避免了数据拷贝极大提高了传输效率。在SEGGER_RTT_Conf.h配置文件中你可以调整以下关键参数#define BUFFER_SIZE_UP 1024 // 上行缓冲区大小 #define BUFFER_SIZE_DOWN 16 // 下行缓冲区大小 #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // 最大上行通道数 #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // 最大下行通道数提示对于日志量大的应用适当增大BUFFER_SIZE_UP可以防止数据丢失但会占用更多RAM空间。1.3 与串口日志的对比理解RTT与传统串口日志的区别有助于我们在不同场景下做出合适选择特性RTT日志串口日志硬件需求仅需调试接口需要专用串口硬件速度高速通常1MB/s受波特率限制通常1MB/s资源占用少量RAM需要UART外设和引脚实时性极高受波特率影响多通道支持是通常单通道双向通信是通常单向从对比中可以看出RTT在大多数调试场景下都具有明显优势特别是在高速数据传输和实时性要求高的场合。2. 快速配置RTT日志系统2.1 环境准备与基础配置要在项目中使用RTT功能首先需要确保你的开发环境满足以下要求硬件需求支持JLINK调试的硬件平台兼容的JLINK调试器如JLINK BASE以上版本软件组件SEGGER J-Link软件包包含RTT源代码嵌入式开发工具链如Keil、IAR或GCCRTT Viewer工具随JLINK软件包安装将RTT组件添加到项目中的步骤如下从JLINK安装目录通常位于C:\Program Files (x86)\SEGGER\JLink\Samples\RTT复制以下文件到你的项目目录SEGGER_RTT.cSEGGER_RTT.hSEGGER_RTT_Conf.h在项目配置中添加这些文件的编译SRCS SEGGER_RTT.c INCLUDES -I/path/to/rtt/files根据你的目标平台修改SEGGER_RTT_Conf.h中的配置参数// 调整缓冲区大小以适应你的应用需求 #define BUFFER_SIZE_UP (1024) #define BUFFER_SIZE_DOWN (16) // 在资源受限的设备上可以减少通道数量 #define SEGGER_RTT_MAX_NUM_UP_BUFFERS (1) #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (1)2.2 基础日志输出方法RTT提供了多种日志输出函数满足不同场景的需求简单字符串输出#include SEGGER_RTT.h void log_test(void) { SEGGER_RTT_Write(0, Hello, RTT!\n, sizeof(Hello, RTT!\n)); }第一个参数0表示使用上行通道0第二个参数是要输出的字符串第三个参数是字符串长度格式化输出int value 42; SEGGER_RTT_printf(0, The answer is %d\n, value);SEGGER_RTT_printf支持标准的printf格式化语法使用起来非常方便。多通道输出你可以配置多个上行通道将不同类型的日志分开// 通道0用于普通日志 SEGGER_RTT_Write(0, System started\n, 15); // 通道1用于错误信息 SEGGER_RTT_Write(1, ERROR: Sensor timeout\n, 22);2.3 RTT Viewer工具使用SEGGER提供的RTT Viewer是查看RTT日志的主要工具其基本使用步骤如下启动RTT Viewer并连接目标设备选择正确的JLINK型号和目标芯片设置正确的接口速度通常自动检测即可配置RTT控制块地址方法一自动搜索适用于大多数情况方法二手动指定在map文件中查找_SEGGER_RTT的地址终端窗口操作可以打开多个终端标签分别监控不同通道支持基本的文本操作如清除屏幕、保存日志等注意如果遇到连接问题尝试降低JLINK接口速度或检查目标板供电是否稳定。3. 高级颜色控制技巧3.1 RTT颜色控制原理RTT Viewer支持ANSI转义序列允许你在日志中添加颜色信息极大地提升了日志的可读性。颜色控制通过特殊的控制序列实现这些序列定义在SEGGER_RTT.h中控制序列效果RTT_CTRL_RESET重置所有属性RTT_CTRL_TEXT_BLACK黑色文本RTT_CTRL_TEXT_RED红色文本RTT_CTRL_TEXT_GREEN绿色文本RTT_CTRL_TEXT_YELLOW黄色文本RTT_CTRL_TEXT_BLUE蓝色文本RTT_CTRL_TEXT_MAGENTA品红色文本RTT_CTRL_TEXT_CYAN青色文本RTT_CTRL_TEXT_WHITE白色文本RTT_CTRL_BG_BLACK黑色背景RTT_CTRL_BG_RED红色背景RTT_CTRL_BG_GREEN绿色背景RTT_CTRL_BG_YELLOW黄色背景RTT_CTRL_BG_BLUE蓝色背景RTT_CTRL_BG_MAGENTA品红色背景RTT_CTRL_BG_CYAN青色背景RTT_CTRL_BG_WHITE白色背景3.2 实际应用示例让我们看几个颜色控制的实际例子基本颜色应用// 红色错误信息 SEGGER_RTT_Write(0, RTT_CTRL_TEXT_RED Error: Sensor failure! RTT_CTRL_RESET \n, sizeof(RTT_CTRL_TEXT_RED Error: Sensor failure! RTT_CTRL_RESET \n)); // 带背景色的警告信息 SEGGER_RTT_printf(0, RTT_CTRL_BG_YELLOW RTT_CTRL_TEXT_BLUE Warning: Low battery (%d%%) RTT_CTRL_RESET \n, battery_level);创建彩色日志宏为了简化代码可以定义一些实用的宏#define LOG_ERROR(fmt, ...) \ SEGGER_RTT_printf(0, RTT_CTRL_TEXT_RED ERROR: fmt RTT_CTRL_RESET \n, ##__VA_ARGS__) #define LOG_WARNING(fmt, ...) \ SEGGER_RTT_printf(0, RTT_CTRL_TEXT_YELLOW WARN: fmt RTT_CTRL_RESET \n, ##__VA_ARGS__) #define LOG_INFO(fmt, ...) \ SEGGER_RTT_printf(0, RTT_CTRL_TEXT_GREEN INFO: fmt RTT_CTRL_RESET \n, ##__VA_ARGS__) // 使用示例 LOG_ERROR(File not found: %s, filename); LOG_INFO(System initialized, version %s, version);多颜色组合你可以在一条日志中组合多种颜色效果SEGGER_RTT_printf(0, RTT_CTRL_TEXT_BLUE [ RTT_CTRL_TEXT_WHITE %s RTT_CTRL_TEXT_BLUE ] RTT_CTRL_TEXT_GREEN %s RTT_CTRL_RESET \n, module_name, message);3.3 颜色使用最佳实践在项目中使用颜色日志时建议遵循以下准则保持一致性在整个项目中统一颜色使用规范比如红色始终表示错误黄色表示警告等适度使用不要过度使用颜色否则会适得其反降低可读性考虑背景确保文本颜色与背景有足够的对比度提供无颜色选项有些环境可能不支持颜色应提供回退方案以下是一个推荐的日志颜色方案日志级别颜色适用场景FATAL红色闪烁系统无法继续运行的严重错误ERROR红色需要立即关注的错误WARNING黄色潜在问题或异常情况INFO绿色常规运行信息DEBUG青色调试信息TRACE蓝色详细跟踪信息4. 实战技巧与性能优化4.1 解决地址变化问题在开发过程中每次重新编译后_SEGGER_RTT变量的地址可能会发生变化这会导致RTT Viewer需要重新配置。有几种方法可以解决这个问题固定地址分配使用GCC的__attribute__语法将RTT控制块固定在特定内存地址SEGGER_RTT_CB _SEGGER_RTT __attribute__((section(.rtt_section), aligned(16))); // 在链接脚本中添加 .rtt_section 0x20000000 : { KEEP(*(.rtt_section)) }自动地址检测在RTT Viewer中启用Auto Detection选项它会自动扫描内存查找RTT控制块。通过map文件获取地址创建一个脚本自动从map文件中提取地址并更新RTT Viewer配置。4.2 性能优化策略为了确保RTT日志系统的高效运行特别是在资源受限的嵌入式系统中可以考虑以下优化措施缓冲区大小调优根据实际日志量调整BUFFER_SIZE_UP监控缓冲区使用情况int buf_usage SEGGER_RTT_GetAvailWriteSpace(0); SEGGER_RTT_printf(0, Buffer free space: %d\n, buf_usage);日志级别控制实现动态日志级别过滤避免生产环境输出过多调试信息#define LOG_LEVEL_DEBUG 0 #define LOG_LEVEL_INFO 1 #define LOG_LEVEL_WARN 2 #define LOG_LEVEL_ERROR 3 extern int current_log_level; #define LOG_DEBUG(fmt, ...) \ if(current_log_level LOG_LEVEL_DEBUG) \ SEGGER_RTT_printf(0, fmt, ##__VA_ARGS__)异步日志记录对于时间敏感的应用可以考虑将日志先存入临时缓冲区在非关键时段批量写入RTT。4.3 多任务环境下的RTT使用在RTOS或多任务环境中使用RTT时需要注意线程安全问题互斥保护// 使用RTOS的互斥量保护RTT访问 void safe_rtt_printf(const char *fmt, ...) { osMutexAcquire(rtt_mutex, osWaitForever); va_list args; va_start(args, fmt); SEGGER_RTT_vprintf(0, fmt, args); va_end(args); osMutexRelease(rtt_mutex); }任务专用通道为每个重要任务分配独立的RTT通道便于调试#define TASK1_CHANNEL 1 #define TASK2_CHANNEL 2 void task1(void) { SEGGER_RTT_printf(TASK1_CHANNEL, Task1 running\n); }时间戳添加在日志中添加精确的时间戳uint32_t get_timestamp(void) { return osKernelGetTickCount(); } #define LOG_TIMED(fmt, ...) \ SEGGER_RTT_printf(0, [%08lu] fmt, get_timestamp(), ##__VA_ARGS__)4.4 高级调试技巧数据可视化RTT Viewer支持简单的数据绘图功能可以用于实时显示传感器数据// 发送数据到图形窗口 float sensor_data read_sensor(); SEGGER_RTT_Write(2, sensor_data, sizeof(sensor_data));交互式调试使用下行通道实现简单的命令行接口char cmd[32]; if(SEGGER_RTT_HasKey()) { int len SEGGER_RTT_Read(0, cmd, sizeof(cmd)-1); cmd[len] \0; process_command(cmd); }崩溃信息捕获在异常处理程序中输出关键信息void HardFault_Handler(void) { SEGGER_RTT_printf(0, RTT_CTRL_TEXT_RED Hard Fault occurred!\n); // 输出寄存器内容等调试信息 while(1); }