调试时没有串口怎么办

前言

基于RT-Thread Nano移植SEGGER/RTT

一、RTT是什么

J-Link RTT – Real Time Transfer: SEGGER’s Real Time Transfer (RTT) is the proven technology for system monitoring and interactive user I/O in embedded applications. It combines the advantages of SWO and semihosting at very high performance.

  • Bi-directional communication with the target application
  • Very high transfer speed without affecting real time behavior
  • Uses debug channel for communication
  • No additional hardware or pin on target required
  • Supported by any J-Link model
  • Supported by ARM Cortex-M0/M0+/M1/M3/M4/M7/M23/M33 and Renesas RX100/200/600
  • Complete implementation code providing functionality and freedom

简而言之,RTT是SEGGER基于J-Link开发的一款可使用SWO接口(仅SWDIO、SWCLK和GND三线即可)与嵌入式系统进行输入输出交互的组件,不影响、不占用系统中的任何硬件资源。

二、为什么要使用RTT

在一些项目中,由于成本考量等原因,选用了硬件资源较为紧张的STM32,譬如只有两个串口。如果这仅有的两个串口都被系统占用了的话,我们在调试的时候就没有办法使用串口来对接控制台以及打印调试信息了。

令人欣慰的是,RT-Thread(Nano)的FinSH(shell)组件并非只局限于串口,且它的输入输出接口都被剥离了出来,方便我们将控制台重定向到其它硬件上如以太网、USB以及本文的J-Link RTT 等。

三、RTT怎么用

IDE: Windows + MDK + LL Libraries for STM32

需要下载安装:J-Link / J-Trace
SEGGER官网

  1. 移植RTT到MDK工程中

    举例说明:
    ①找到JLink安装目录
    我的安装目录:安装目录

    ②将..\SEGGER\JLink\Samples\RTT目录中的SEGGER_RTT_Vxxxx.zip拷贝到工程目录中解压,创建相关文件夹管理,并加入工程,添加头文件目录。

    我的工程结构:Project头文件

  2. 修改代码与配置(LL库)

    ①修改SEGGER_RTT_Conf.h
    按需修改上、下行以及缓冲区大小

    //
    // Most common case:
    // Down-channel 0: RTT
    // Down-channel 1: SystemView
    //
    #ifndef   SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
      #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS           (3)     // Max. number of down-buffers (H->T) available on this target  (Default: 3)
    #endif
    
    #ifndef   BUFFER_SIZE_UP
      #define BUFFER_SIZE_UP                            (1024)  // Size of the buffer for terminal output of target, up to host (Default: 1k)
    #endif
    
    #ifndef   BUFFER_SIZE_DOWN
      #define BUFFER_SIZE_DOWN                          (16)    // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16)
    #endif
    
    #ifndef   SEGGER_RTT_PRINTF_BUFFER_SIZE
      #define SEGGER_RTT_PRINTF_BUFFER_SIZE             (64u)    // Size of buffer for RTT printf to bulk-send chars via RTT     (Default: 64)
    #endif
    
    #ifndef   SEGGER_RTT_MODE_DEFAULT
      #define SEGGER_RTT_MODE_DEFAULT                   SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0)
    #endif
    

    ②修改RT-Thread Nano -> board.c
    我使用了一个宏来管理该模块和串口的互斥,方便调试的时候相互切换:

    #define USART_SHELL     USART1
    #ifndef USART_SHELL
    #include "SEGGER_RTT.h"
    #endif
    

    使用如下代码来导出至RT-Thread Nano的自动初始化功能:

    #ifndef USART_SHELL
    int RTT_init()
    {
        SEGGER_RTT_ConfigUpBuffer(0, "RTTUP", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
        SEGGER_RTT_ConfigDownBuffer(0, "RTTDOWN", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
        SEGGER_RTT_SetTerminal(0);
        return RT_EOK;
    }
    INIT_COMPONENT_EXPORT(RTT_init);
    #endif
    

    使用如下代码来对接RT-Thread Nano的输入输出函数(LL库):

    void rt_hw_console_output(const char *str)
    {
    #ifdef USART_SHELL
        rt_size_t i = 0, size = 0;
        char a = '\r';
    
        size = rt_strlen(str);
        for (i = 0; i < size; i++)
        {
            while(!LL_USART_IsActiveFlag_TXE(USART_SHELL))
            {
            }
            if (*(str + i) == '\n')
            {
                LL_USART_TransmitData8(USART_SHELL, a);
                while(!LL_USART_IsActiveFlag_TXE(USART_SHELL))
                {
                }
            }
            LL_USART_TransmitData8(USART_SHELL, *(str + i));
        }
    #else
        SEGGER_RTT_printf(0, str);
    #endif
    }
    
    char rt_hw_console_getchar()
    {
    	int ch = -1;
    #ifdef USART_SHELL
        if(LL_USART_IsActiveFlag_RXNE(USART_SHELL))
        {
            ch = LL_USART_ReceiveData8(USART_SHELL);
        }
        else
        {
    		if(LL_USART_IsActiveFlag_ORE(USART_SHELL))
    		{
    			LL_USART_ClearFlag_ORE(USART_SHELL);
    		}
            rt_thread_mdelay(10);
        }
    #else
        if(SEGGER_RTT_HasKey())
            ch = SEGGER_RTT_GetKey();
        else
            rt_thread_mdelay(10);
    #endif
        return ch;
    }
    
  3. 使用J-Link RTT Viewer

    选择芯片型号并连接:
    选择型号连接成功

    输出功能:Output
    输入功能:Input

问题与总结

本文简述了如何将RTT对接到RT-Thread Nano中来代替常用的串口打印。RT-Thread(Nano)的模块化、接口抽象和面向对象设计能够让我们很轻松地做功能移植,灵活且方便。然而在使用过程中发现有如下问题有待解决,时间原因我暂时不去追根溯源,欢迎大家研究并留言:
在这里插入图片描述

参考资料:

  1. Real Time Transfer (RTT)
  2. 移植控制台/FinSH (rt-thread.org)
  3. SEGGER调试利器RTT(Real Time Transfer)组件下载
  4. 【专题教程第5期】工程调试利器RTT实时数据传输组件,替代串口调试,速度飞快,可以在中断和多任务中随意调用
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值