WCH RISC CH32V303RCT6 单片机的SDI Printf 虚拟串口功能 类似SEGGER RTT打印功能 简单分析

3 篇文章 0 订阅

参考:
有关于 SDI printf 更多的信息和资料吗?
关于 CH32 系列 MCU SDI 虚拟串口功能的使用
【CH32X035 评估板测评】+ 教你使用 SDI 接口重定向 printf
SDI (Serial Data Interface) 是沁恒微电子 RISC-V 内核的私有外设接口,CH32 RISC-V 系列目前提供了 SDI 的 printf 打印功能
(有点类似RTT Viewer,但是是由WCH-LinkE调试器虚拟出来的一个串口,可以使用各种串口上位机查看打印的调试信息)

0.前言

有段时间没有看CH32V单片机的开发了,今天帮新来的同事调试时候看到debug.c里面有新的函数SDI_Printf_Enable
在这里插入图片描述
大概看了下,感觉有点像RTT,去wch官方那个技术社区搜了下果然有相关内容。
在这里插入图片描述
主要看了这篇:关于 CH32 系列 MCU SDI 虚拟串口功能的使用写的很详细了。

在此下载最新的WCH-LinkUtility,解压后Doc文件夹中有WCH-Link使用说明,看来通用MCU的支持的多点,CH582、CH592还没有支持。
在这里插入图片描述

1.试验

1.1 打开SDI_PRINT

这里我使用的是CH32V303RCT6单片机,打开官方EVT中的例程
在这里插入图片描述
默认的Printf是关闭SDI功能、打开串口1的
在这里插入图片描述debug.h中将SDI_PRINT改为SDI_PR_OPEN即可编译。
在这里插入图片描述

1.2 打开串口助手

打开 WCH-LinkE 对应的串口,115200、8N1
在这里插入图片描述

1.3.使用WCH-LinkUtility下载固件并打开SDI 功能

在这里插入图片描述

1.4.下载查看串口信息

wch-linke只连接了SWCLK、SWDIO,没有连接自身的TX、RX,但还是可以看到有数据打印出来。
在这里插入图片描述

2.SDI Printf 虚拟串口功能原理简单推测分析

感谢**【CH32X035 评估板测评】+ 教你使用 SDI 接口重定向 printf**的分享

debug.c中的_write函数可以大概推测下SDI实现的原理:

#define DEBUG_DATA0_ADDRESS  ((volatile uint32_t*)0xE0000380)
#define DEBUG_DATA1_ADDRESS  ((volatile uint32_t*)0xE0000384)

__attribute__((used)) int _write(int fd, char *buf, int size)
{
    int i = 0;

#if (SDI_PRINT == SDI_PR_OPEN)
    int writeSize = size;

    do
    {

        /**
         * data0  data1 8 bytes
         * data0 The lowest byte storage length, the maximum is 7
         *
         */

        while( (*(DEBUG_DATA0_ADDRESS) != 0u))
        {

        }

        if(writeSize>7)
        {
            *(DEBUG_DATA1_ADDRESS) = (*(buf+i+3)) | (*(buf+i+4)<<8) | (*(buf+i+5)<<16) | (*(buf+i+6)<<24);
            *(DEBUG_DATA0_ADDRESS) = (7u) | (*(buf+i)<<8) | (*(buf+i+1)<<16) | (*(buf+i+2)<<24);

            i += 7;
            writeSize -= 7;
        }
        else
        {
            *(DEBUG_DATA1_ADDRESS) = (*(buf+i+3)) | (*(buf+i+4)<<8) | (*(buf+i+5)<<16) | (*(buf+i+6)<<24);
            *(DEBUG_DATA0_ADDRESS) = (writeSize) | (*(buf+i)<<8) | (*(buf+i+1)<<16) | (*(buf+i+2)<<24);

            writeSize = 0;
        }

    } while (writeSize);


#else
    for(i = 0; i < size; i++)
    {
#if(DEBUG == DEBUG_UART1)
        while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
        USART_SendData(USART1, *buf++);
#elif(DEBUG == DEBUG_UART2)
        while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
        USART_SendData(USART2, *buf++);
#elif(DEBUG == DEBUG_UART3)
        while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);
        USART_SendData(USART3, *buf++);
#endif
    }
#endif
    return size;
}

SDI (Serial Data Interface) 是沁恒微电子 RISC-V 内核的私有外设接口
在这里插入图片描述

#define DEBUG_DATA0_ADDRESS  ((volatile uint32_t*)0xE0000380)
#define DEBUG_DATA1_ADDRESS  ((volatile uint32_t*)0xE0000384)

可以看到_write函数写的数据地址正是在其MCU内核的Core Private Peripherals范围中

这段代码来看,SDI 接口发送的数据存放于 DATA0 和 DATA1 地址的寄存器,每个寄存器可以存放 32 位数据也就是 4 个字节,两个寄存器可以存储 8 个字节数据,因为 DATA0 的低位第一个字节存放发送数据的个数,那么得知 SDI 接口一次性一包数据可以发送 7 个字节。
综上分析,SDI 接口还可以做其他用途的数据传输,目前来看,貌似给出的资料目前只能发送不能接收。

在这里插入图片描述

  1. WCH-LinkE调试器在Enable SDI Printf后,会虚拟出来一个串口供上位机串口助手使用,默认波特率115200、8N1
  2. MCU 开启SDI,#define SDI_PRINT SDI_PR_OPEN
  3. MCU程序运行中调用Printf函数,要打印的数据最终通过_write函数不断地写在内核中的DEBUG_DATA0_ADDRESSDEBUG_DATA1_ADDRESS 地址上,而不是通过硬件串口外设调用USART_SendData发送
  4. WCH-LinkE调试器会不断地查询位于MCU的内核中上述DEBUG_DATA0/1_ADDRESS两地址的数据,并将该数据打包通过虚拟出来的串口发送给串口上位机
    比较类似于RTT Viewer功能,通过调试器不断快速地访问RAM/内核中的指定地址范围的数据来实现MCU和调试器到上位机的数据传输。
    只不过WCH的SDI功能目前仅有Printf 打印,对用户RAM区占用很小,但还没支持双向的数据传输,但也算是很好的提升了,WCH加油啊!

3.WCH-LinkUtility的问题

WCH-LinkUtility在菜单栏 Target下拉可以随时控制SDI的开关,但是下图这里的开关不是即时发生的,实测只有在下载程序时会生效。(2024-04-25)
在这里插入图片描述
请添加图片描述

  • 20
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值