业内首发!感芯MC3172硬实时RISC-V芯片,告别RTOS!

最近收到感芯科技寄来的一款开发板(https://mbb.eet-china.com/evaluating/product-99.html),非常感谢面包板社区感芯科技
其实本次评测活动我并没有申请,因为我和一位申请的朋友重名了,正好我又有小编的微信,所以也给我寄来一块,为了避免快递来回寄的麻烦,就没有退还,多一个用户评测总是好的。
这款开发板基于感芯科技MC3172芯片,业内首发并行多线程实时处理器,也就是可以完全硬件级实现多线程同时运行,最多支持64同步线程,不同于普通单片机运行RTOS,有点类似FPGA的并行执行方式,但它又是一颗MCU。
和普通的MCU相比,芯片本身特殊在哪里?开发方式又有什么区别呢?
21.jpg
本文将从硬件和软件两个方向来进行评测,硬件主要介绍芯片外设、开发板资源,软件介绍这颗芯片的开发环境搭建,应用开发和调试,以及对芯片的性能进行一个简单的测试。
因为我主要从事于FPGA开发工作,对于MCU接触不多,所以本次评测的广度和深度有限。欢迎和各位朋友一起交流学习。

1. MC3172开发板简介

MC3172开发板非常小巧迷你,大小只有46x31mm,连银行卡大小的一半都不到,尺寸小巧的代价就是资源非常有限。
板载如下硬件资源:
  • MC3172最小系统电路
  • CH554G下载器电路
  • 5v转3.3/1.8v稳压电路
  • 2.54mm扩展IO

USB接口为MicroUSB,只需要一根USB线即可完成程序的下载。目前安卓常用的是Type-C口,如果你没有这种老的MicroUSB线,可能会不太方便。为了降低成本和减小板子整体面积,3.3v和1.8v稳压芯片采用的是封装比较小的SOT-23封装的XC6206P182MR和XC6206P332MR。
22.jpg
遗憾的是没有板载电源LED、用户LED、用户按键等基本外设,不过都把所有的GPIO都通过标准的2.54mm间距排针引出来了,包括5v/3.3v/1.8v电源,也可以连接你想要扩展的外部模块,比如液晶屏,LED,温湿度传感器,WiFi等。
24.jpg
MC3172开发板PCB采用立创EDA进行绘制。如下:
09.jpg
3D效果
08.jpg
外扩的IO定义
07.jpg
这块板子目前在官方店铺售价39 RMB包邮。

00.jpg
2. MC3172芯片简介
MC3172是感芯科技研发的第一款32位RISC-V处理器,它是一款多线程实时处理器,可实现64线程同步并行运行,线程资源可按需配置,共享代码段空间与数据段空间,硬件级实时响应,无需中断服务程序,无需实时操作系统。
MC3172具有如下特性:
  • 基于RISC-V RV32IMC 指令集,100%单指令周期,最高200MHz主频,3.37coremark/MHz。
  • 片上128KB共享SRAM,可存放代码和数据,可按需配置为96+32/64+64/32+96,灵活应对各种应用场景。
  • 12个可配置通信接口,可配置为USART、SPI主从机、USB 2.0主机/设备(全速和低速)、CAN 2.0B。
  • 6个24位通用计数器,可提供高精度PWM与输入捕捉
  • 64个快速GPIO,可提供丰富的自定义控制接口。
  • 核心1.8v供电,GPIO 1.8-3.3v供电
  • 内嵌200MHz和8MHz RC振荡器
  • 外部支持最高133MHz输入时钟
  • 串行2线制TWDP调试接口,TWDIO 和 TWCLK,支持程序下载和调试。
  • LQFP100封装和QFN88封装可选。

202209041453418159.png
更多详解介绍,可以查看文末的MC3172数据手册。
MC3172的程序加载方式比较特殊,和FPGA的被动加载比较类似,MC3172内部只有RAM空间,通过CLK和DIO两根线连接到外部的CH554单片机,单片机外部连接了一颗SPI接口的Flash,当执行程序下载时,实际上是通过连接在单片机上的USB线,将程序文件下载到单片机外挂的Flash内部,上电启动时,单片机将Flash中的数据读出,通过CLK和DIO给MC3172加载。
论坛网友还自己设计了MC3172开发板2.0版本,开源了AD工程,下载地址在文末。
01.jpg
可以看出,2.0版本明显比官方的开发板大了一些,LED、按键、串口等硬件资源也多了。

03.jpg
3. 什么是并行多线程实时处理器

众所周知,目前的微控制器,除了FPGA是真正的并行运行,由时钟信号来驱动,在一个时钟周期内,多个模块可以同时执行很多操作。
MCU虽然也能通过RTOS任务调度器实现多线程,但其实是通过快速的切换来实现实时。
而MC3172为并行多线程实时处理器,是在芯片级实现的多线程同步并行运行,互不阻塞,各个线程共享数据段与代码段,无通信瓶颈。
20.jpg
各个线程按需分配主频,完成各自专项任务,无需中断与线程调度,故具有极强的实时性和可预测性,可以代替实时操作系统,实现程序的模块化与复用性。
  • 它有着操作系统的效率,但是它的线程调度没有任何抖动与等待。
  • 它有着裸机编程的直接,但是它的中断响应没有任何延迟与嵌套。

多线程的应用场景有哪些呢?可以类比FPGA中模块的概念,一个模块一个功能,每个模块独立运行。
比如采集温湿度,通过显示屏进行展示,并上传到云平台,可以分为3个线程:
  • 传感器驱动线程,完成初始化,定时获取传感器数据
  • 显示线程,定时刷新显示的数据值
  • 网络驱动模块,完成网络模块的初始化,定时将数据上传到云端。

两轮自平衡车PID控制可分为如下几个线程:
  • 电机驱动线程,用于设定电机的转速
  • 姿态反馈线程,用于监测当前运动状态
  • PID计算线程,用于根据姿态计算出电机的脉冲信号

多线程实时处理器的开发和应用,可以达到裸机编程的难度,RTOS的扩展性,FPGA的实时性与确定性
随着机器人,工业自动化,汽车等应用的进一步扩展,高实时多并发的多线程处理器必将大有作为。

4. 关于感芯科技

厦门感芯科技有限公司,2020年12月成立于福建厦门,是一家专注于高实时多并发应用领域微控制器研究的高科技企业。
从官网来看,目前芯片产品有MC3172,通过同步多线程的使用,可以达到裸机编程的难度,RTOS的扩展性,FPGA的实时性与确定性。
感芯科技官网:http://www.gxchip.cn/
gxchip.png
感芯科技目前还比较年轻,成立时间比较短,目前只有MC3172这款芯片产品,另辟蹊径,主打硬件级多线程实时处理器,和通用MCU市场做了区分。

5. 开发环境搭建

MC3172是一颗RISC-V内核处理器,使用完全国产化、通用化的MounRiver Studio开发环境,我相信对于从事RISC-V MCU开发的朋友来说,这款开发环境应该不陌生,目前有多款国产RISC-V芯片都是使用的这个开发环境,支持常见的Windows、Linux、MacOS三大主流平台。
04.jpg
我第一次接触这个开发环境,是使用沁恒的CH32V芯片,这款开发环境还支持通用的RISC-V内核芯片开发,比如RV32E,RV32I,RV64I等,MC3172是基于RV32IMC指令集。可以到文末的资料汇总获取软件的下载链接。
除了开发环境,我们还需要获取两个工具。
  • 程序下载工具,用于将hex文件通过CH554G下载到SPI Flash。
  • 配置代码生成工具,用于配置各个线程的频率,堆栈空间大小等等。

这两个工具都是基于Qt开发,而且开源在感芯官方Gitee上,地址在文末资料汇总。
可以根据自己的需要,丰富软件的功能,或者进行一些个性化定制。
%E5%85%AC%E4%BC%97%E5%8F%B7.jpg
12.jpg
板载的下载器使用是USB-HID协议,所以无需安装驱动即可使用。
05.jpg
用于配置线程运行空间的组合方式,线程的个数,每个线程空间的大小,时钟源的选择等等。
06.jpg
自动生成两个配置文件MC3172.lds链接脚本和thread_config.h线程配置文件,直接放在我们的工程下即可调用。

6. Hello World

开发环境搭建完成后,下载感芯MC3172 V1.21资料包,在模板例程的基础上,我们来实现一个Hello World工程,用到了GPIO和UART外设。
使用线程配置工具,分别使能3个线程,线程频率配置为主时钟频率的1/4,即48/4=12MHz,线程栈空间大小为128字节。
14.jpg

线程0

实现5个LED流水灯,PB1/3/5/7/9:
void thread0_main(void)
{
    uint8_t cnt = 0;
    uint32_t status = 0x02;
    uint32_t gpiob = GPIOB_BASE_ADDR;

    INTDEV_SET_CLK_RST(gpiob, INTDEV_RUN | INTDEV_IS_GROUP0 | INTDEV_CLK_IS_CORECLK_DIV4);
    GPIO_SET_OUTPUT_EN_VALUE(gpiob, GPIO_PIN1 | GPIO_PIN3 | GPIO_PIN5 | GPIO_PIN7 | GPIO_PIN9, GPIO_SET_ENABLE);
    GPIO_SET_OUTPUT_PIN_TO_1(gpiob, GPIO_PIN1 | GPIO_PIN3 | GPIO_PIN5 | GPIO_PIN7 | GPIO_PIN9);

    while(1)
    {
        status <<= 2;
        if(status == 0x800)
            status = 2;
        GPIO_SET_OUTPUT_PIN_VALUE(gpiob, GPIO_PIN1 | GPIO_PIN3 | GPIO_PIN5 | GPIO_PIN7 | GPIO_PIN9, status);
        delay_ms(500);
    }
    thread_end();
}

线程1

实现串口回环测试,TXD=PA15,RXD=PA14:
void thread1_main(void)
{
    u8 rx_data_rp=0;
    u8 rx_data=0;

    //TXD=GPCOM_P3=PA15, RXD=GPCOM_P2=PA14
    INTDEV_SET_CLK_RST(GPCOM3_BASE_ADDR,(INTDEV_RUN|INTDEV_IS_GROUP0|INTDEV_CLK_IS_CORECLK_DIV4));
    GPCOM_SET_IN_PORT(GPCOM3_BASE_ADDR,(GPCOM_RXD_IS_P2));
    GPCOM_SET_OUT_PORT(GPCOM3_BASE_ADDR,( \
          GPCOM_P0_OUTPUT_DISABLE|GPCOM_P3_OUTPUT_ENABLE|GPCOM_P2_OUTPUT_DISABLE|GPCOM_P1_OUTPUT_DISABLE| \
          GPCOM_P0_IS_HIGH       |GPCOM_P3_IS_TXD       |GPCOM_P2_IS_HIGH       |GPCOM_P1_IS_HIGH \
                    ));
    GPCOM_SET_COM_MODE(GPCOM3_BASE_ADDR,GPCOM_UART_MODE);

    GPCOM_SET_COM_SPEED(GPCOM3_BASE_ADDR,12000000,115200);      //48/4=12

    GPCOM_SET_OVERRIDE_GPIO(GPCOM3_BASE_ADDR, ( \
          GPCOM_P2_OVERRIDE_GPIO|GPCOM_P2_INPUT_ENABLE | \
          GPCOM_P3_OVERRIDE_GPIO \
                                            ));
    rx_data_rp=GPCOM_GET_RX_WP(GPCOM3_BASE_ADDR);
    while(1)
    {
       if(rx_data_rp != (GPCOM_GET_RX_WP(GPCOM3_BASE_ADDR)))
       {
            rx_data=GPCOM_GET_RX_DATA(GPCOM3_BASE_ADDR,rx_data_rp);
            GPCOM_PUSH_TX_DATA(GPCOM3_BASE_ADDR,rx_data);
            rx_data_rp++;
            rx_data_rp &= 0x0f;
       }
    }

    thread_end();
}

线程2

实现串口500ms输出Hello World by MC3172! mbb.eet-china.com字符串:
void thread2_main(void)
{
    while(1)
    {
        my_printf(GPCOM3_BASE_ADDR, "Hello World by MC3172! mbb.eet-china.com\r\n");
        delay_ms(300);
    }
    thread_end();
}
我们自己写一个简单的串口输出字符串:
void my_printf(uint32_t comx, char *pStr)
{
    while(*pStr != 0)
    {
        while(GPCOM_TX_FIFO_FULL(comx));
        GPCOM_PUSH_TX_DATA(comx, *pStr++);
    }
}
再写一个毫秒级延时函数:
void delay_ms(uint32_t ms)
{
    uint32_t now = CORE_CNT;
    uint32_t CNT_MS = ms * (CORE_CLK/1000);
    while(CORE_CNT - now < CNT_MS);
    return;
}
延时函数实现的原理是MC3172内部有一个全局的计数器,计数时钟源是内核时钟,32位递增计数,可以通过CORE_CNT地址读取。
15.jpg
从串口输出记录的时间戳,看出延时时间还比较准确,各线程也都正常运行。
3M波特率波形:
13.jpg
2M波特率波形:
10.jpg
7. 资料下载
  • 感芯MC3172资料包MC3172资料合集_v1.21

http://www.gxchip.cn/upload/202210/08/202210082332589333.zip
  • 开发环境MounRiver Studio

http://file.mounriver.com/upgrade/MounRiver_Studio_Setup_V182.zip
  • 感芯科技官方GitHub仓库

https://gitee.com/gxchip
(包括代码生成工具、ISP下载工具源码、CH554G下载器固件源码、MC3172工程模板等)
  • 感芯科技官方技术论坛

https://whycan.com/f_57.html
  • 论坛游总封装的HAL库

https://gitee.com/ylc0919/mc3172.git
  • MC3172民间参考手册

https://docs.qq.com/doc/DREJmcnpDQWVFcnhw
  • MC3172开发板入门体验

https://blog.csdn.net/panda5_csdn/article/details/125732906
  • 论坛网友画的2.0版本的开发板AD工程

链接: https://pan.baidu.com/s/1VPL9Jm-Jvb1YHvXvZCYHGw
提取码:y3qc
  • 使用Visual Studio来开发MC3172

https://whycan.com/t_8577.html
  • MC3172上移植文件系统

https://gitee.com/yanhui5329/mc3172_-fat-fs

8. 总结

总的来说,MC3172硬件实时多线程处理器,算是众多MCU产品中的一朵奇葩,可以不用RTOS,就可以实现芯片级的多线程,降低了用户开发的难度,当然,客观的说,芯片的生态环境还有待完善,芯片的配套文档,比如寄存器手册,用户手册,固件函数驱动库等都还不够成熟,如果想要在通用MCU市场瓜分一点市场的话,理想的做法还是尽量去兼容比较主流的函数库,这样可以用最短的时间适配现有项目工程。MC3172首款开发板的配置也比较简单,没有用户外设,比如LED,按键,USB接口也没有串口功能,不方便调试等等,不能够对芯片本身的资源做一个完整的评估,软件开发环境还不支持程序下载和调试工具,多线程配置工具,没有加载当前已有配置的功能,如果需要对已经配置的线程进行修改,打开配置工具后,需要再一个一个单独的配置。
整体来说,对于百花齐放的国产MCU市场来说,是一朵奇葩(褒义),如果进一步完善生态环境,并且有不错的价格优势的话,将会有很大的市场。
本文对MC3172的评测比较浅薄,我也并没有深入测试MC3172这款独特的芯片,文中有描述不准确的地方,欢迎在评论区留言交流。