SEGGER RTT 使用指南

SEGGER RTT 使用指南

简介

SEGGER的实时传输(RTT)技术用于嵌入式应用中的交互式用户输入输出。它结合了SWO和半托管(semihosting)的优点,同时实现了极高的性能。通过RTT,可以在不影响目标微控制器实时行为的情况下,以非常高的速度从目标微控制器输出信息并发送输入到应用。

SEGGER RTT可以与任何J-Link型号和任何支持背景内存访问的目标处理器(如Cortex-M和RX目标)配合使用。RTT支持多个双向通道,可以用于不同的目的,为用户提供最大的灵活性。默认实现中,每个方向使用一个通道,用于可打印的终端输入和输出。通过J-Link RTT Viewer,这个通道可以用于多个“虚拟”终端,允许在多个窗口中打印(例如,一个用于标准输出,一个用于错误输出,一个用于调试输出),只需一个目标缓冲区。此外,还可以使用一个额外的上行(到主机)通道,例如用于发送性能分析或事件跟踪数据。

在硬件没有预留调试串口的情况下,我们可以使用 RTT 来进行调试打印。

使用步骤

引入驱动

1、在 SEGGER 官网选择合适版本的 JLINK 进行下载安装

jlink

2、找到对应 JLINK 版本的 RTT 驱动

rtt

3、将驱动文件添加到工程

project

接口使用

interface

在工程中添加头文件 SEGGER_RTT.h,在打印前调用 SEGGER_RTT_Init() 初始化 RTT,打印时使用 SEGGER_RTT_printf 函数。

这里我们将 SEGGER_RTT_printf 定义为 printf_dbg,并将打印通道指向 0,后面就可以使用 printf_dbg 宏进行打印了。

可能遇到的问题

坑1

现象:单片机程序分为 BLD、APP 两个部分,两边都使用 RTT 进行打印时,打开 J-Link RTT Viewer 发现 BLD 部分的打印丢失。

原因:BLD 与 APP 中都调用了 SEGGER_RTT_Init(),这个函数在调用后会重置 RTT 控制块结构体,在打开 J-Link RTT Viewer 后只记录了 APP 内的打印。

措施:只在 BLD 程序中调用 SEGGER_RTT_Init(),去掉 APP 中的初始化调用。

坑2

现象:按上面修改后,打开 J-Link RTT Viewer 发现 BLD 中的打印正常了,但 APP 的打印缺失。

原因:APP 中 RTT 控制块结构体在内存中的地址可能与 BLD 中该结构体地址不一致,打开 J-Link RTT Viewer 后软件从扫描到的内存地址读取打印,但 APP 中的打印地址与 BLD 中不一致,导致 APP 内的打印丢失。

措施:固定 RTT 控制块的内存地址

1、用宏指定 RTT 控制块所在的段

section

2、指定使用自定义分散加载文件

linker

3、修改分散加载文件,指定 RTT 控制块所在段的内存位置

scatter

注意事项

1、在 map 文件中确认 RTT 控制块的内存地址

map

2、BLD 中 RTT 控制块初始时应该用 0 填充,而 APP 中不对 RTT 控制块所在内存做任何操作,所以 APP 对应的分散加载文件中,RTT 控制块段的内存描述中使用 UNINIT 修饰

uninit

3、使用 Arm Compiler 6 时,设置非零初始化变量的方式与 Arm Compiler 5 不同

Arm Compiler 5 属性Arm Compiler 6 属性描述
__attribute__((at(address)))__attribute__((section(".ARM.__at_address")))Arm Compiler 6 中的 armlink 仍然支持以 .ARM.__at_address 的形式放置段
__attribute__((at(address), zero_init))__attribute__((section(".bss.ARM.__at_address")))Arm Compiler 6 中的 armlink 支持以 .bss.ARM.__at_address 的形式放置零初始化段。 .bss 前缀区分大小写,并且必须全部小写。
__attribute__((section(name), zero_init))__attribute__((section(".bss.name")))name 是你选择的名字。 .bss 前缀区分大小写,并且必须全部小写
__attribute__((zero_init))不支持默认将零初始化变量放在.bss 段。如果变量具有初始值设定项,则 Arm Compiler 5 会生成错误。 否则,它将零初始化变量放在 .bss段。

RTT 控制块所在段属性应当设置为 ZI,使用 Arm Compiler 6 编译时,定义变量使用 __attribute__((section(".bss.RTT"))) 来进行修饰。

4、使用 GCC 进行编译时,修改 .s 启动文件和 .ld 链接文件

BLD:

  1. 添加自定义段的起始地址与结束地址
/* start address for the .custom_ram section. defined in linker script */
.word  _scustom
/* end address for the .custom_ram section. defined in linker script */
.word  _ecustom
  1. 用 0 初始化自定义段
/* Zero fill the custom_ram segment. */
  ldr r2, =_scustom
  b LoopFillZeroCustom
  
FillZeroCustom:
  movs r3, #0
  str r3, [r2]
  adds r2, r2, #4
  
LoopFillZeroCustom:
  ldr r3, =_ecustom
  cmp r2, r3
  bcc FillZeroCustom

BLD && APP:

  1. 修改链接文件
/* Specify the memory areas */
MEMORY
{
RAM_CUSTOM (xrw): ORIGIN = 0x20000000, LENGTH = 0x4b8
RAM (xrw)       : ORIGIN = 0x20000000 + 0x4b8, LENGTH = 0x2000 - 0x4b8
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 15K
}
  /* Uninitialized data section */
  . = ALIGN(4);
  .custom_ram :
  {
    _scustom = .;

    *(.bss.RTT)

    . = ALIGN(4);
    _ecustom = .;
  } >RAM_CUSTOM
  1. 添加宏指定 RTT 控制块所在段
-DSEGGER_RTT_SECTION=\".bss.RTT\"

5、使用 SEGGER Embedded Studio 编译时,修改.icf 链接脚本

APP:

  1. APP 中不初始化 RTT 控制块
do not initialize { section .RTT };

BLD && APP:

  1. 将 RTT 控制块所在段放到 RAM1 开头
place in RAM1 { section .RTT, section .RAM1, section .RAM1.* };
  1. Preprocessor Definitions 添加宏指定 RTT 控制块所在段
SEGGER_RTT_SECTION=".RTT"
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值