RT-Thread中使用RTT调试

RT-Thread中使用Jlink的RTT调试

RT-Thread中的finsh命令非常实用,但是一般都会占用掉了一个串口。或者有时候手边没有串口线时,就不方便调试了。

由于我用的时jlink烧录器,之前使用调试工具-RTT来代替串口进行信息的交互和调试。所以我就想,能否用RTT来替代串口,运行finsh命令。

RTT( Real Time Terminal)是SEGGER公司新出的可以在嵌入式应用中与用户进行交互的实时终端。J-Link驱动4.90之后的版本都支持RTT。具体详情自选查找。

下面说一下步骤。

首先,新建一个项目时,就要选控制台串口,以及对应的管脚,我们按照默认的选就可以了。
创建RT-Thread项目
输入项目名,完成各个配置后,打开rtconfig.h文件,会看到:
rtconfig.h文件
这里关键的是:RT_USING_DEVICE,RT_USING_CONSOLE和RT_CONSOLE_DEVICE_NAME
很明显,使用了uart1这个串口去给控制台。具体如何控制的,我们看一下关键代码:
kservice.c中的rt_kprintf()打印函数,实际输出函数。

/**
 * This function will print a formatted string on system console
 *
 * @param fmt the format
 */
void rt_kprintf(const char *fmt, ...)
{
    va_list args;
    rt_size_t length;
    static char rt_log_buf[RT_CONSOLEBUF_SIZE];

    va_start(args, fmt);
    /* the return value of vsnprintf is the number of bytes that would be
     * written to buffer had if the size of the buffer been sufficiently
     * large excluding the terminating null byte. If the output string
     * would be larger than the rt_log_buf, we have to adjust the output
     * length. */
    length = rt_vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, fmt, args);
    if (length > RT_CONSOLEBUF_SIZE - 1)
        length = RT_CONSOLEBUF_SIZE - 1;
#ifdef RT_USING_DEVICE
    if (_console_device == RT_NULL)
    {
        rt_hw_console_output(rt_log_buf);
    }
    else
    {
        rt_uint16_t old_flag = _console_device->open_flag;

        _console_device->open_flag |= RT_DEVICE_FLAG_STREAM;
        rt_device_write(_console_device, 0, rt_log_buf, length);
        _console_device->open_flag = old_flag;
    }
#else
    rt_hw_console_output(rt_log_buf);
#endif
    va_end(args);
}

简单理解就是:
如果用了有效的device,就用device输出。如果不用device就用rt_hw_console_output()这个函数输出。
device还是要用的,那么我们就把命令台的device改成无效的就行。
所以我们可以简单的修改:

#define RT_CONSOLE_DEVICE_NAME ""

把uart1去掉。这样就可以让程序用device但是命令台device却无效了。

然后去board.c中,实现rt_hw_console_output()这个函数。记得要添加RTT的头文件。(RTT相关文件自己找,然后添加进项目。)

#include "SEGGER_RTT.h"
void rt_hw_console_output(const char *str)
{
    rt_size_t i = 0, size = 0;

    size = rt_strlen(str);
    for (i = 0; i < size; i++)
    {
        if (*(str + i) == '\n')
        {
           break;
        }
    }
    SEGGER_RTT_printf(0,"%s",str);
}

然后,编译,运行,打开J-Link RTT Viewer,就能看到
(J-Link RTT Viewer使用说明自己查找,强调一下,input–sending中选send on enter)
J-Link RTT Viewer界面
输出就这么简单就完成了,但是我们会发现,输入什么命令都没有效果,接着我们来解决输入问题。

输入关键点在shell.c文件,中的finsh_getchar()函数。

static int finsh_getchar(void)
{
#ifdef RT_USING_DEVICE
#ifdef RT_USING_POSIX
    return getchar();
#else
    char ch = 0;

    RT_ASSERT(shell != RT_NULL);
    while (rt_device_read(shell->device, -1, &ch, 1) != 1)
        rt_sem_take(&shell->rx_sem, RT_WAITING_FOREVER);

    return (int)ch;
#endif
#else
    extern char rt_hw_console_getchar(void);
    return rt_hw_console_getchar();
#endif
}

一样的,用了用了device就从device中读取,否则用rt_hw_console_getchar()这个函数。
现在问题来了,这边没有无效的命令台device的判断条件了,所以我们只好自己修改这部分代码

static int finsh_getchar(void)
{
#ifdef RT_USING_DEVICE
#ifdef RT_USING_POSIX
    return getchar();
#else
    char ch = 0;

    RT_ASSERT(shell != RT_NULL);
    if(shell->device!=RT_NULL)
    {
        while (rt_device_read(shell->device, -1, &ch, 1) != 1)
            rt_sem_take(&shell->rx_sem, RT_WAITING_FOREVER);

        return (int)ch;
    }
    else
    {
        extern char rt_hw_console_getchar(void);
        return rt_hw_console_getchar();
    }
#endif
#else
    extern char rt_hw_console_getchar(void);
    return rt_hw_console_getchar();
#endif
}

然后,去board.c中实现rt_hw_console_getchar()这个函数。

char rt_hw_console_getchar(void)
{
    int ch = -1;
    char tempbuffer[2];
    uint8_t NumBytes=0;

    NumBytes = SEGGER_RTT_Read(0, &tempbuffer[0], 1);
    if(NumBytes==1)
    {
        ch=tempbuffer[0];
    }
    return ch;
}

一个字符一个字符的读取,那么也就只能这样了。
接着试试效果:
在这里插入图片描述
输入help命令,成功了!

到此为止,RTT实际已经添加完毕了。

然后,我们追求更加实用的话,我们会希望拥有我们自己的命令,比如上图里的log就是我自己添加的。
方法很简单,添加代码

int msh_log(int argc, char **argv)
{
    rt_kprintf("my log run!:");
    if (argc==2)
    {
        rt_kprintf("arg is %s\n",argv[1]);
    }
    rt_kprintf("\n");

    return 0;
}
FINSH_FUNCTION_EXPORT_ALIAS(msh_log, __cmd_log, RT-Thread shell log.);

在这里插入图片描述
执行效果就是这样的了。

还可以参考这样的用法:

void myhello(void)
{
    rt_kprintf("hello RT-Thread!\n");
}
MSH_CMD_EXPORT(myhello , my hello to RT-Thread);

(使用的工具:RT-Thread studio 2.0 内核rt-thread 4.0.2)

  • 7
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值