感芯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自带的串口绘图仪。

posted @ 2025-06-29 21:06  星如雨yu  阅读(60)  评论(1)    收藏  举报