感芯MC3172开发笔记之读取AD模块
手头有一块某原子的ad板,板载3pa1030 * 2pcs,最大采样率50MSPS,但是fpga(见上篇AntMiner S9)坏了,因此找不到一个合适的下位机。
社长塞给了我一块MC3172(二代评估板),翻了一下手册,RISC-V+硬64线程!适合实时性高的场合 资料传送门

可以试试用它读取ad模块的并行数据,再通过高速UART发送到上位机进行处理。
开发IDE使用国产MounRiver Studio 传送门,我下载的是MRS2(基于VSCode)
[deprecated] 截止目前,MRS已更新新版本,更新后此问题可能被解决。权当记录
在MRS打开MC3172_Template_v1.23目录,尝试先build一下,结果竟然出现了这个:

make -jundefined all...一眼javascript,翻了一下编译设置,没有多线程相关选项。js代码被混淆了,下断点调试无果,果断放弃。只能选择patch make.exe了...
不想看?这里有patch好的make.exe,提取码:5Yvq
打开IDA,分析"E:\MounRiver\MounRiver_Studio2\resources\app\resources\win32\others\Build_Tools\Make\bin\make.exe"这个文件,定位"option requires a positive integer argument",对数值判断的分支做如下修改


修改后就可以成功编译了(ps: 此修改会导致提供给make的数值选项变为1,但对MRS无影响。)
打开MC3172\线程配置工具_V1.exe,配置线程

接下来贴代码吧
// MC3172 main.c
// author: xry1029, date: 2025/6/29
#include "../MC3172/MC3172.h"
#include <string.h>
//#include "./GPIO_GPCOM_TIMER_Example.c"
#define SYS_CORE_CLK_MHZ 192 // Internal RC Clock
// #define SYS_CORE_CLK_MHZ 48 // Internal XTAL Clock
u16 ad_data = 0;
/*
ad_data thread0 GPIO_GET_INPUT_VALUE_SAFE(GPIOA_BASE_ADDR) 一次性获取所有值
ad_clk thread1 GPIO_SET_OUTPUT_PIN_TO_1 注意一次循环三条指令
uart thread2 GPCOM_PUSH_TX_DATA 注意调节速率
led thread3 GPIO_SET_OUTPUT_PIN_TO_1 一闪一闪亮晶晶
*/
/*
PB0 - PB9 ad_data [0:9]
PB10 ad_otr
PC0 ad_clk
PC1 ad_oe
*/
////////////////////////////////////////////////////////////
void thread_end(void)
{
while(1);
}
// 来自社区大佬的延时函数
void delay_us(u32 nus, int div){
// 1000us = 1ms, 1000ms = 1s
u32 ticks;
u32 told, tnow, tcnt = 0;
GET_CORE_CNT(told); //读取内核定时器数值
ticks = nus * SYS_CORE_CLK_MHZ/div; //目标延时节拍数=需要延时时间(us)*CORE_CLK(MHz)/分频数
while (1)
{
GET_CORE_CNT(tnow);
if (tnow != told)
{
if (tnow < told)tcnt = 0xFFFFFFFF - told + tnow; //CORE_CNT递增32位,计算已延时节拍数
else tcnt = tnow - told;
if (tcnt >= ticks)break; //延时完成
}
};
}
////////////////////////////////////////////////////////////
#define GPIO_AD_PORT GPIOB_BASE_ADDR
void thread0_main(void)
{
// 1/4分频
// 读取ad数据
INTDEV_SET_CLK_RST(GPIO_AD_PORT, (INTDEV_RUN | INTDEV_IS_GROUP0 | INTDEV_CLK_IS_CORECLK_DIV4));
// 前10位为ad数值,后一位为otr,其余五位填0
GPIO_SET_INPUT_EN_VALUE(GPIO_AD_PORT,(GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7|GPIO_PIN8|GPIO_PIN9|GPIO_PIN10),GPIO_SET_ENABLE);
while(1){
//user code section
ad_data = GPIO_GET_INPUT_VALUE_SAFE(GPIO_AD_PORT);
// 这句其实有三条指令 读取寄存器 赋值 jmp
// 因此实际的ad速率为16mhz 刚好和gpio反转的速率一样...
}
thread_end();
}
////////////////////////////////////////////////////////////
#define GPIO_PC_PORT GPIOC_BASE_ADDR
void thread1_main(void)
{
// 1/4分频
// 翻转gpio实现时钟
#define PC0_INDEX GPIO_PIN0
INTDEV_SET_CLK_RST(GPIO_PC_PORT, (INTDEV_RUN | INTDEV_IS_GROUP0 | INTDEV_CLK_IS_CORECLK_DIV4));
GPIO_SET_OUTPUT_EN_VALUE(GPIO_PC_PORT, PC0_INDEX,GPIO_SET_ENABLE);
while(1){
//user code section
//GPCOM_UART_EXAMPLE(GPCOM8_BASE_ADDR);
GPIO_SET_OUTPUT_PIN_TO_1(GPIO_PC_PORT, PC0_INDEX);
GPIO_SET_OUTPUT_PIN_TO_0(GPIO_PC_PORT, PC0_INDEX);
// jmp;
}
thread_end();
}
////////////////////////////////////////////////////////////
#define GPIO_UART_PORT GPCOM0_BASE_ADDR
void _putchar(char character){
GPCOM_PUSH_TX_DATA(GPIO_UART_PORT,character);
while(GPCOM_TX_FIFO_FULL(GPIO_UART_PORT)); // 等一等
}
void send_u16_decimal_fast(u16 value) {
// 快速将读取到的u16数据转为ASCII并加上前/后缀
// 输入范围: 0-1023
// 只取低10位
value &= 0x03FF;
// 十进制位权表(用于快速定位最高位)
static const u16 powers_of_ten[] = {
1000, 100, 10, 1
};
// 是否已经发送过任何数字(处理前导 0)
int sent = 0;
// 前缀(for plotter)
// _putchar('$');
for (int i = 0; i < 4; ++i) {
u16 divisor = powers_of_ten[i];
if (value >= divisor || sent || divisor == 1) {
u8 digit = 0;
// 使用减法代替除法(在小范围内更快)
while (value >= divisor) {
value -= divisor;
digit++;
}
_putchar('0' + digit);
sent = 1;
}
}
// 后缀(for plotter)
// _putchar(';');
_putchar('\n');
}
void thread2_main(void)
{
// 1/4分频
// UART发送函数
// PA3: TXD, PA2: RXD
u16 ad_data_bak = 0; // 防幻读
INTDEV_SET_CLK_RST(GPIO_UART_PORT,(INTDEV_RUN|INTDEV_IS_GROUP0|INTDEV_CLK_IS_CORECLK_DIV4));
GPCOM_SET_IN_PORT(GPIO_UART_PORT,(GPCOM_RXD_IS_P2));
GPCOM_SET_OUT_PORT(GPIO_UART_PORT,( \
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(GPIO_UART_PORT,GPCOM_UART_MODE);
// ch340最大baud 2000000
GPCOM_SET_COM_SPEED(GPIO_UART_PORT,50000000,2000000); // 已经是ch340的极限了 比率24有点低 希望别出问题哇 出问题了就降时钟
GPCOM_SET_OVERRIDE_GPIO(GPIO_UART_PORT, ( \
GPCOM_P2_OVERRIDE_GPIO|GPCOM_P2_INPUT_ENABLE | \
GPCOM_P3_OVERRIDE_GPIO \
));
while(1) {
memcpy(&ad_data_bak, &ad_data, sizeof(u16));
if (ad_data_bak & (1 << 10)) {
// 如果otr为高,超量程,输出0
send_u16_decimal_fast((u16)0);
}else {
send_u16_decimal_fast(ad_data_bak);
}
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread3_main(void)
{
// 1/4分频
// blink 板载LED
#define GPIO_LED_PORT GPIOD_BASE_ADDR
#define LED_INDEX GPIO_PIN8
INTDEV_SET_CLK_RST(GPIO_LED_PORT, (INTDEV_RUN | INTDEV_IS_GROUP0 | INTDEV_CLK_IS_CORECLK_DIV4));
// OE PC1 -> LOW 很奇怪,oe为低才开始采样,怎么回事
GPIO_SET_OUTPUT_EN_VALUE(GPIO_PC_PORT, GPIO_PIN1,GPIO_SET_ENABLE);
GPIO_SET_OUTPUT_PIN_TO_0(GPIO_PC_PORT, GPIO_PIN1);
GPIO_SET_OUTPUT_EN_VALUE(GPIO_LED_PORT, LED_INDEX,GPIO_SET_ENABLE);
while(1){
//user code section
//GPIO_EXAMPLE(GPIOA_BASE_ADDR);
GPIO_SET_OUTPUT_PIN_TO_1(GPIO_LED_PORT, LED_INDEX);
delay_us(1000*500,4);
GPIO_SET_OUTPUT_PIN_TO_0(GPIO_LED_PORT, LED_INDEX);
delay_us(1000*500, 4);
// 此处指令共9条
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread4_main(void)
{
while(1){
//TIMER_CAPTURER_EXAMPLE(TIMER3_BASE_ADDR);
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread5_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread6_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread7_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread8_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread9_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread10_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread11_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread12_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread13_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread14_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread15_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread16_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread17_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread18_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread19_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread20_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread21_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread22_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread23_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread24_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread25_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread26_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread27_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread28_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread29_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread30_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread31_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread32_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread33_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread34_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread35_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread36_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread37_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread38_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread39_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread40_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread41_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread42_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread43_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread44_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread45_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread46_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread47_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread48_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread49_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread50_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread51_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread52_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread53_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread54_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread55_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread56_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread57_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread58_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread59_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread60_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread61_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread62_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
void thread63_main(void)
{
while(1){
//user code section
}
thread_end();
}
////////////////////////////////////////////////////////////
编译完成后通过Release\GX-ISPTool_v1.23.exe下载进板,看到板载LED闪烁后通过ch340连接uart,我使用的上位机是serialplot,也可以用Arduino自带的串口绘图仪。
--------------
你已经看完这篇博文了!
本文来自博客园,作者:星如雨yu,转载请注明原文链接:https://www.cnblogs.com/tianpanyu/p/18956759
另,建议转载手动看一眼,把代码块转过去呗(超小声嘀咕)

浙公网安备 33010602011771号