MC3172 是厦门感芯科技的一款32 位 RISC并行多线程实时处理器。采用一种全新的CPU工作模式与软件开发模式,不同于单线程裸机编程,只能顺序执行,也不同于操作系统通过切换造成的多线程执行,并行多线程的各个线程是一直在并行运行的,彼此互不打扰,没有优先级的概念,也没有切换的随机性。

相关资料可在感芯官网下载:链接。
MC3172主要几个特点:

产品内置快速可编程线程控制器,支持全部64个线程运行频率设置,记内核时钟速度为 C Mhz,则每16个线程为一组共4个线程组,每个线程组固定分配四分之一主频资源,每个线程组内部的16个线程可按需配置,举例如下:
假设内核主频为128MHz,则每个线程组分配的主频为32Mhz,则线程组内的16个线程共享该32Mhz主频资源,可配置为如下几种典型设置(只是举例说明,不是必须配置为这些设置,可按实际需求灵活配置)。
这样一个具有特色的mcu,我当然想尝试一下,于是我第一时间申请了评估版,两天后,评估版到手:


在官网下载ide和MC3172资料合集包。
MC3172的开发环境使用的是国产软件MounRiver Studio,其官网地址:http://www.mounriver.com/,很多risc-v芯片都是用此开发工具,如沁恒的mcu。
MC3172资料合集位于http://www.gxchip.cn/down/show-70.html,点击资源下载,既可以下载到MC3172资料合集包。
点击下载后的软件->安装,安装后启动界面如下:

点击load project/solution,选择我们的项目工程,工程在官网下载的MC3172资料合集_V1.03文件里面MC3172资料合集_V1.03\MC3172_Template,打开后如下:

官网提供的所有的demo程序都位于GPIO_GPCOM_TIMER_Example.c这个文件内,我们的移植也将参考这部分内容。
在官网下载的MC3172资料合集_V1.03文件里面有一个芯片配置软件线程配置工具_V1.exe,位于MC3172资料合集_V1.03\MC3172_Template\MC3172目录,这个软件的相应代码已经开源,开源地址:https://gitee.com/gxchip。

到现在为止,MC3172还不支持直接从ide下载程序,其实也变相说明了也不支持调试。下载必须借助下载工具来实现。
在官网下载的MC3172资料合集_V1.03文件里面有一个芯片程序下载软件开发板程序下载_V1.exe,位于MC3172资料合集_V1.03\MC3172_Template\Release目录,这个软件的相应代码已经开源,开源地址:https://gitee.com/gxchip。

上面我们已经准备好了MC3172的开发环境,下面我们就设计一个demo程序,让它跑起来。
学单片机,第一个程序自然是点灯,下面我们就具体操作一下,来熟悉mcu的完整配置过程。
首先要注意,不要随意更改MC3172资料合集包里面文件的的位置。
打开线程配置工具_V1.exe软件,在里面配置如下:

点击生成代码,当你设置了SRAM的分配,工程的文件MC3172.lds就会自动更新,当你设置了线程分配thread_config.h就会自动更新。
注意:这个时钟源选择要注意了,系统时钟源内部RC 200Mhz默认开启,在没有配置时钟或者复位后,内部 200MHz 的 RC 振荡器作为默认的 CPU 时 钟,随后可以另外选择外部 4~40MHz 晶振(评估板挂的是48m无源晶振)驱动,8MhzRC振荡器或者外部直接输入时钟作为内核时钟。也就是这里的设置将来会直接作为内核时钟。
用ide打开工程,我们可以先参照一下GPIO_GPCOM_TIMER_Example.c这个文件内的程序代码:
//当main.c
GPIO_EXAMPLE(GPIOA_BASE_ADDR);
//GPIO_GPCOM_TIMER_Example.c
void GPIO_EXAMPLE(u32 gpio_sel)
{
//使能了GPIOA的时钟(运行|线程组别|外设时钟分频设置)
//这个外设时钟分频设置我想了好长时间,猜测是设置gpio_sel这个外设时钟的,而时钟来源应该是内核的主频,跟现在所处的线程时钟没有任何关系。不要和配置资源的时候那个时钟弄混。
INTDEV_SET_CLK_RST(gpio_sel,(INTDEV_RUN|INTDEV_IS_GROUP0|INTDEV_CLK_IS_CORECLK_DIV2));
//PA0-PA7配置为输出
GPIO_SET_OUTPUT_EN_VALUE(gpio_sel,(GPIO_PIN_7_0),GPIO_SET_ENABLE);
//PA8-PA15配置为输入
GPIO_SET_INPUT_EN_VALUE(gpio_sel,(GPIO_PIN_15_8),GPIO_SET_ENABLE);
//置输出高电平
GPIO_SET_OUTPUT_PIN_TO_1(gpio_sel,(GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3));
//置输出低电平
GPIO_SET_OUTPUT_PIN_TO_0(gpio_sel,(GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7));
while(1){
//引脚电平反转
GPIO_SET_OUTPUT_PIN_INV(gpio_sel,(GPIO_PIN0|GPIO_PIN2));
u16 rx_data;
//获取GPIOA的全部电平
rx_data=GPIO_GET_INPUT_VALUE_SAFE(gpio_sel);
//设置gpio的值
GPIO_SET_OUTPUT_PIN_VALUE(gpio_sel,(GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7),(rx_data>>4));
for (u32 var = 0; var < 5000; ++var) {
NOP();
}
}
}
按照上面的内容,在main.c的void thread0_main(void)里面编写程序如下:
void thread0_main(void)
{
//使能了GPIOA的时钟
INTDEV_SET_CLK_RST(GPIOA_BASE_ADDR,(INTDEV_RUN|INTDEV_IS_GROUP0|INTDEV_CLK_IS_CORECLK_DIV2));
//将PA0设置为输出模式
GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN0),GPIO_SET_ENABLE);
//配置默认输出为高电平
GPIO_SET_OUTPUT_PIN_TO_1(GPIOA_BASE_ADDR,GPIO_PIN0);
while(1) {
//引脚取反
GPIO_SET_OUTPUT_PIN_INV(GPIOA_BASE_ADDR,GPIO_PIN0);
//延时
for (u32 var = 0; var < 5000; ++var) {
NOP();
}
}
thread_end();
}
先将评估版接到电脑上面,打开开发板程序下载_V1.exe,这个时候将会识别出一个设备,点击连接设备,选择MC3172.hex固件,点击烧录固件,进度条走到100%,则下载完成

对照引脚图:

将PA0接到示波器上看到波形如下:

从图我们可以看到波形的周期为2.5ms,即对应周期为400hz,回看我们的程序设置。
首先我们在配置mcu的时候,选择了外部晶振,而评估版外部晶振默认是48M,这48兆将作为系统时钟.
然后我们配置线程的时候,选择了4分频,那么现在thread0只有12M了。
现在我们检测到引脚反转周期是400HZ,那么也就是说明我们程序里面while执行两个循环(引脚高一次,低一次)耗时2.5ms。
while里面的主要逻辑就是计数5000次,反转一次引脚电平,对于这款号称高速io的设备,我认为一次电平反转时间跟5000次循环相比微不足道,所以我们近似认为耗时就是5000次循环。
两次while耗时2.5ms,那么一次for循环就是2.5ms/(2*5000) = 250ns 。对应频率为4M.
因为for循环包括数值累加,比较,还有一个时钟的nop空耗,因此12M周期只能让for保持4M循环效果是合理的。
可能是对于一个刚开始推广的芯片,做的还是有很多不完美的地方: