This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSPM33C321A:MSPM33C321A:HSADC 无法达到最大频率

Guru**** 2901510 points

Other Parts Discussed in Thread: LP-MSPM33C321A, SYSCONFIG

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1640268/mspm33c321a-mspm33c321a-hsadc-unable-to-reach-max-frequency

器件型号: MSPM33C321A
主题: SysConfig 中讨论的其他器件

我正在使用 LP-MSPM33C321A、并使用示例工程 hsadc_max_freq_dma 作为开发的起点、并配置了与示例工程完全相同的时钟、示例工程对 SYSPLL 使用勘误权变措施 1、可能会锁定到错误的频率。 我使用的 DMA0 和 timerA 配置与 CCS 示例中使用的配置完全相同、只是我使用的传输模式为 DL_DMA_FULL_CH_REPEAT_SINGLE_TRANSFER_MODE

为了提供更多背景信息、我将 MCLK 设置为 160MHz、并使用 PA27 以 10kHz 的频率从信号发生器接收 1us 脉冲。 不过、我只能以~2.5MSPS 而不是广播的 9.43MSPS 进行采样、我知道这是通过使用 ISR 切换引脚 PA22 来实现的。 我正在使用乒乓缓冲器特性、因此我使用早期中断(缓冲器的一半已满时)和中断(缓冲器完成时)。 我的 ADC 样本数为每半个 2048 个样本、来自 PA22 的频率为 1.22kHz(或每秒 1、22y 的半部分数)、这使得我处于~2.51MSPS。 如果设置了 MCLK 160MHz、并且我使用 TIMERA0_0 来触发 SOC、且 TIMER_LOAD_VALUE 为 16、那么我是否应该在计算中看到 9.54MSPS? 就好像我的结果被 4 除以。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Eric、

    您能否详细介绍一下如何配置乒乓缓冲器? 我的问题是、如果 ADC IRQ 存在一定延迟、这可能会导致您的性能受到一定程度的限制。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我正在为在 DL_DMA_FULL_CH_REPEAT_SINGLE_TRANSFER_MOD 中配置的每个 ADC 使用一个 DMA 通道。
    我的目标缓冲区 uint16_t[2][2048], 布局为两个 2048 个样本的半部分、每个 ADC 总共 4096 个半字。
    我的源是 ADC 结果寄存器 (ADCRESULT0)、SrcIncrement = ADDR_UNDOWN、半字宽度。
    目标为[2][2048]缓冲区的开始、DESTIncrement = ADDR_INCREMENT、半字宽度。
    传输大小:2 x 2048 =每个周期 4096 个半字。

    我使用 DL_DMA_DMA\DMA0_setEarlyInterruptThreshold (Full_Ch_、0、DL_DMA_Eary_INTERRUPT_THRESHOLD_HALF);

    因此、当 2048 个传输完成时、DMA 会用早期 IRQ 触发(在 Half[0]已满时进行 I 标记)。

    然后我有一个完成/完整的 IRQ 当 4096 rransfers 完成(一半[1]满)。

    TIMA0_0 在 9.4MHz 的通道 1 上发布归零事件、两个 ADC 均订阅并触发 SOC0。 SOC0 完成触发 DMA_INT_1。

    //帮助调用两个配置的辅助函数
    //使用 DMA 一次对 ADC0/ADC1 执行
    静态 void init_hsadc (adc_module_e mod)

    hsadc_adc_lite_regs_Regs *adc = modules.ctrl;

    DL_HSADC_setClockDivideRatio (ADC、DL_HSADC_CLOCK_Divide_1_0);
    DL_HSADC_SOCChannelSelect (ADC、DL_HSADC_SOC_NUMBER0、DL_HSADC_ADCIN_0);
    DL_HSADC_setupSequencer (ADC、DL_HSADC_SEQ_number1、16、DL_HSADC_TRIGGER_GEN_SUB_0、
    DL_HSADC_SOC_NUMBER0);
    DL_HSADC_enableSequencer (ADC、DL_HSADC_SEQ_number1);
    DL_HSADC_setSampleCapReset (ADC、DL_HSADC_SEQ_number1、DL_HSADC_SAMPCAPRESET_HALF_VREFHI);
    DL_HSADC_setEndOfSequencer (ADC、DL_HSADC_SOC_NUMBER0);

    // ADC 侧的 DMA 触发器接线
    DL_HSADC_DMAInterruptStatusClear (ADC、DL_HSADC_DMA_INT_1);
    DL_HSADC_enableDMAContinuueToInterruptMode (ADC、DL_HSADC_DMA_INT_1);
    DL_HSADC_DMAInterruptSourceSelect (ADC、DL_HSADC_DMA_INT_1、DL_HSADC_SOC_NUMBER0);
    DL_HSADC_enableDMAInterrupt (ADC、DL_HSADC_DMA_INT_1);

    //订阅事件结构通道 1(timer 在此处发布)
    DL_HSADC_setSubscripberChanID (ADC、DL_HSADC_BUSPER_INDEX_0、1);

    DL_HSADC_POWERUP (ADC);

     

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

     FULL_CH_REPEAT_SINGLE_TRANSFER_MODE 预计会跟上 9.375MSPS 的速度、还是全通道模式的每次采样仲裁开销阻止了这种速度? 如果是、在此器件上以最大速率进行连续(乒乓)流式传输的建议模式是什么?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Eric、


    很抱歉耽误你的时间。 我使用 SDK 示例进行了类似的测试、遇到了一个类似的问题、获得大约 5MHz 的性能。 如果我对根本原因以及如何重新配置问题有更确切的答案、我将更新您。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    不用担心、感谢您的答复。 为了澄清一下、我的用例是连续流式传输、而不是 SDK 示例的一次性突发 2000 个样本 DMA 块 (DL_DMA_FULL_CH_REPEAT_SINGLE_TRANSFER_MODE)。  

    所以、我的目标架构是:

    - ADC0+ADC1 从同一 TIMA_0 零事件同时触发   

    -每个 ADC 一个 DMA 通道,在 DL_DMA_FULL_CH_REPEAT_SINGLE_TRANSFER_MODE 中

    - PING Pong 通过早期 IRQ 在半阈值和连续捕获

    谢谢!  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    嗨、Eric、

    使用随附的示例可获得最大频率。


    e2e.ti.com/.../hsadc_5F00_max_5F00_freq_5F00_dma.syscfge2e.ti.com/.../hsadc_5F00_max_5F00_freq_5F00_dma.c

    这并不是特定于您的用例、但您可以利用它进行改进、以获得出色性能。 之所以这样、是因为缓冲器为 32 位宽、但结果仅为 16 位、因此通过使用 9.4MHz 处的序列发生器、序列发生器在两个连接到同一 ADCIN0 引脚的 SOC 之间切换。 希望这可以帮助您开始设计。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢您、Erik。 ADCIN_0 上都有 2 个 SOC、序列发生器位于 SOC1 处、DMA 以 32 位宽度从 ADCRESULT0 读取、我看到在连续乒乓 DMA 模式下现在~2.84MSPS 略有增加。 您能否共享允许达到最大频率的特定 config/sysconfig 文件或设置? 我可以问您如何在您的终端验证最大频率 MSPS 吗? 您是否从 DMA 缓冲区内容中派生?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Eric、

    我相信以上文件显示了它在 9.4MSPS 下的工作原理。 需要一些时间才能将其从该配置转换为乒乓模式。 您能否发送波形或文件、以便我了解您看到的结果?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Eric、

    对不起,我错过了你上一条消息的下半部分,但我使用波形发生器以已知频率 (94 kHz ) 馈入正弦波。 在这个频率下、我期望两个峰值之间有 100 个样本。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您展示了每个周期 94kHz/100 样本的图。 我能够让 HSADC0/HSADC1 同时以~5.7MSPS 的速率进行采样、我相信这与您最初在上一次运行中看到的结果相匹配。 我正在使用 SOC0/SOC1、其中 SAMPLEWINDOW=16、ACQPS =15。
    我使用 TIMG4_0 触发这两个 ADC 的序列发生器、因为我找到了勘误表、其中说明 TIMA_0 不适用于多个事件 (TIMER_ERR_08)。  

    然后、我决定尝试以与使用 SOC0/SOC1 相同的方式在 CCS 中运行示例工程、并以 94kHz 正弦波馈送。 我在使用该示例时看到的采样率似乎很奇怪、但与我是否将半字宽度或字宽与 DMA 搭配使用是一致的。 我将用图表共享此示例工程的 ti_msp_dl_config.c 和 main.c。 我觉得缺少了您在 ti_msp_dl_config.c 中使用的一些配置 但可以确认可以同时使用 ADC。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Eric、

    本示例中有一个已知错误、其中 DMA 处于块模式、而不是单模式。 我相信、如果您进行此调整、它应该会修复它。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我已将.transferMode 切换为 DL_DMA_SINGLE_TRANSFER_MODE、当前使用的是 SOC0/SOC1。 我的序列发生器的配置方式与示例相同、但使用已知的 94kHz 正弦波馈送 PA27 后、我无法复制您的图。 这就是我的图当前外观、我还将展示我的 ti_msp_dl_config.c 通过此示例工程、我发现数据速率为~5.7MSPS。 我的项目还实现了 5.7MSPS 的采样率、涉及乒乓连续流式传输。 每个峰值为~61 个样本/周期、因此除非缺少另一个配置、否则我不知道配置与您的配置有何不同。

    #include "ti_msp_dl_config.h"
    
    DL_TimerA_backupConfig gTIMER_0Backup;
    
    /*
     *  ======== SYSCFG_DL_init ========
     *  Perform any initialization needed before using any board APIs
     */
    SYSCONFIG_WEAK void SYSCFG_DL_init(void)
    {
        SYSCFG_DL_initPower();
        SYSCFG_DL_GPIO_init();
        /* Module-Specific Initializations*/
        SYSCFG_DL_SYSCTL_init();
        SYSCFG_DL_TIMER_0_init();
        SYSCFG_DL_HSADC0_init();
        SYSCFG_DL_DMA0_init();
        /* Ensure backup structures have no valid state */
    	gTIMER_0Backup.backupRdy 	= false;
    
    }
    /*
     * User should take care to save and restore register configuration in application.
     * See Retention Configuration section for more details.
     */
    SYSCONFIG_WEAK bool SYSCFG_DL_saveConfiguration(void)
    {
        bool retStatus = true;
    
    	retStatus &= DL_TimerA_saveConfiguration(TIMER_0_INST, &gTIMER_0Backup);
    
        return retStatus;
    }
    
    
    SYSCONFIG_WEAK bool SYSCFG_DL_restoreConfiguration(void)
    {
        bool retStatus = true;
    
    	retStatus &= DL_TimerA_restoreConfiguration(TIMER_0_INST, &gTIMER_0Backup, false);
    
        return retStatus;
    }
    
    SYSCONFIG_WEAK void SYSCFG_DL_initPower(void)
    {
        DL_GPIO_reset(GPIOA);
        DL_TimerA_reset(TIMER_0_INST);
        DL_HSADC_reset(HSADC0_INST);
    
    
    
        DL_GPIO_enablePower(GPIOA);
        DL_TimerA_enablePower(TIMER_0_INST);
        DL_HSADC_enablePower(HSADC0_INST);
    
        delay_cycles(POWER_STARTUP_DELAY);
    }
    
    SYSCONFIG_WEAK void SYSCFG_DL_GPIO_init(void)
    {
    
    }
    
    
    static const DL_SYSCTL_SYSPLLConfig gSYSPLLConfig = {
        .inputFreq              = DL_SYSCTL_SYSPLL_INPUT_FREQ_32_48_MHZ,
    	.rDivClk2x              = 1,
    	.rDivClk1               = 0,
    	.rDivClk0               = 0,
    	.enableCLK2x            = DL_SYSCTL_SYSPLL_CLK2X_ENABLE,
    	.enableCLK1             = DL_SYSCTL_SYSPLL_CLK1_DISABLE,
    	.enableCLK0             = DL_SYSCTL_SYSPLL_CLK0_ENABLE,
    	.sysPLLMCLK             = DL_SYSCTL_SYSPLL_MCLK_CLK0,
    	.sysPLLRef              = DL_SYSCTL_SYSPLL_REF_SYSOSC,
    	.qDiv                   = 9,
    	.pDiv                   = DL_SYSCTL_SYSPLL_PDIV_1
    };
    
    SYSCONFIG_WEAK bool SYSCFG_DL_SYSCTL_SYSPLL_init(void)
    {
        bool fFCCRatioStatus = false;
        uint32_t fFCCSysoscCount;
        uint32_t fFCCPllCount;
        uint32_t fFCCRatio;
    
        DL_SYSCTL_setFCCPeriods( DL_SYSCTL_FCC_TRIG_CNT_01 );
    
        //Measuring PLL. Use ONLY this configuration. DO NOT EDIT
        DL_SYSCTL_configFCC(DL_SYSCTL_FCC_TRIG_TYPE_RISE_RISE,
                            DL_SYSCTL_FCC_TRIG_SOURCE_LFCLK,
                            DL_SYSCTL_FCC_CLOCK_SOURCE_SYSPLLCLK0);
        /* Get SYSPLL frequency using FCC */
        DL_SYSCTL_startFCC();
        while (DL_SYSCTL_isFCCDone() == 0);
    
        /* get measA= SYSPLL0 freq wrt LFOSC*/
        fFCCPllCount = DL_SYSCTL_readFCC();
    
        //Measuring SYSPLL Source
        DL_SYSCTL_configFCC(DL_SYSCTL_FCC_TRIG_TYPE_RISE_RISE,
                            DL_SYSCTL_FCC_TRIG_SOURCE_LFCLK,
                            DL_SYSCTL_FCC_CLOCK_SOURCE_SYSOSC);
        /* Get SYSPLL frequency using FCC */
        DL_SYSCTL_startFCC();
        while (DL_SYSCTL_isFCCDone() == 0 );//
    
        /* get measB= SYSOSC freq wrt LFOSC*/
        fFCCSysoscCount = DL_SYSCTL_readFCC();
    
        /* Get ratio of both measurements*/
        fFCCRatio = (fFCCPllCount * FLOAT_TO_INT_SCALE) / fFCCSysoscCount;
        /* Check ratio is within bounds*/
        if ((FCC_LOWER_BOUND <  fFCCRatio) && (fFCCRatio < FCC_UPPER_BOUND))
        {
            fFCCRatioStatus = true; //ratio is good for proceeding into application code.
        }
    
        return fFCCRatioStatus;
    }
    SYSCONFIG_WEAK void SYSCFG_DL_SYSCTL_init(void)
    {
    
    	//Low Power Mode is configured to be SLEEP
        DL_SYSCTL_setBORThreshold(DL_SYSCTL_BOR_THRESHOLD_LEVEL_0);
    
        
    	DL_SYSCTL_setSYSOSCFreq(DL_SYSCTL_SYSOSC_FREQ_BASE);
        DL_SYSCTL_configSYSPLL((DL_SYSCTL_SYSPLLConfig *) &gSYSPLLConfig);
    
        /*
         * PLL Incorrect locking WA start.
         * Insert after every PLL enable.
         * This can lead an infinite loop if the condition persists
         * and can block entry to the application code.
         */
    
        while (SYSCFG_DL_SYSCTL_SYSPLL_init() == false)
        {
            /* Toggle SYSPLL enable to re-enable SYSPLL and re-check incorrect locking */
            DL_SYSCTL_disableSYSPLL();
            DL_SYSCTL_enableSYSPLL();
    
            /* Wait until SYSPLL startup is stabilized*/
            while ((DL_SYSCTL_getClockStatus() & SYSCTL_CLKSTATUS_SYSPLLGOOD_MASK) != DL_SYSCTL_CLK_STATUS_SYSPLL_GOOD){}
        }
        DL_SYSCTL_disablePLLDivider( );
        DL_SYSCTL_setMCLKSource(SYSOSC, HSCLK, DL_SYSCTL_HSCLK_SOURCE_SYSPLL);
        DL_SYSCTL_setHSCLKSource(DL_SYSCTL_HSCLK_SOURCE_SYSPLL);
    
    
    }
    
    
    
    
    /*
     * Timer clock configuration to be sourced by BUSCLK (160000000 Hz)
     * timerClkFreq = (timerClkSrc / (timerClkDivRatio * (timerClkPrescale + 1)))
     *   160000000 Hz = 160000000 Hz / (1 * (0 + 1))
    */
    static const DL_TimerA_ClockConfig gTIMER_0ClockConfig = {
        .clockSel    = DL_TIMER_CLOCK_BUSCLK,
        .divideRatio = DL_TIMER_CLOCK_DIVIDE_1,
        .prescale    = 0U,
    };
    
    /*
     * Timer load value (where the counter starts from) is calculated as (timerPeriod * timerClockFreq) - 1
     * TIMER_0_INST_LOAD_VALUE = (106.25 ns * 160000000 Hz) - 1
     */
    static const DL_TimerA_TimerConfig gTIMER_0TimerConfig = {
        .period     = TIMER_0_INST_LOAD_VALUE,
        .timerMode  = DL_TIMER_TIMER_MODE_PERIODIC,
        .startTimer = DL_TIMER_STOP,
    };
    
    SYSCONFIG_WEAK void SYSCFG_DL_TIMER_0_init(void) {
    
        DL_TimerA_setClockConfig(TIMER_0_INST,
            (DL_TimerA_ClockConfig *) &gTIMER_0ClockConfig);
    
        DL_TimerA_initTimerMode(TIMER_0_INST,
            (DL_TimerA_TimerConfig *) &gTIMER_0TimerConfig);
        DL_TimerA_enableClock(TIMER_0_INST);
    
    
        DL_TimerA_enableEvent(TIMER_0_INST, DL_TIMERA_EVENT_ROUTE_1, (DL_TIMERA_EVENT_ZERO_EVENT));
    
        DL_TimerA_setPublisherChanID(TIMER_0_INST, DL_TIMERA_PUBLISHER_INDEX_0, TIMER_0_INST_PUB_0_CH);
    
    
    
    }
    
    
    
    SYSCONFIG_WEAK void SYSCFG_DL_HSADC0_init(void)
    {
        DL_HSADC_setClockDivideRatio(HSADC0_INST,DL_HSADC_CLOCK_DIVIDE_1_0);
    
        DL_HSADC_SOCChannelSelect(HSADC0_INST, DL_HSADC_SOC_NUMBER0, DL_HSADC_ADCIN_0);
        DL_HSADC_SOCChannelSelect(HSADC0_INST, DL_HSADC_SOC_NUMBER1, DL_HSADC_ADCIN_0);
    
        DL_HSADC_setupSequencer(HSADC0_INST, DL_HSADC_SEQ_NUMBER1, 16, DL_HSADC_TRIGGER_GEN_SUB_0, DL_HSADC_SOC_NUMBER0);
        DL_HSADC_enableSequencer(HSADC0_INST, DL_HSADC_SEQ_NUMBER1);
        DL_HSADC_setSampleCapReset(HSADC0_INST, DL_HSADC_SEQ_NUMBER1, DL_HSADC_SAMPCAPRESET_HALF_VREFHI);
        DL_HSADC_setEndOfSequencer(HSADC0_INST, DL_HSADC_SOC_NUMBER1);
    
    
        DL_HSADC_DMAInterruptStatusClear(HSADC0_INST, DL_HSADC_DMA_INT_1);
        DL_HSADC_enableDMAContinueToInterruptMode(HSADC0_INST, DL_HSADC_DMA_INT_1);
        DL_HSADC_DMAInterruptSourceSelect(HSADC0_INST, DL_HSADC_DMA_INT_1, DL_HSADC_SOC_NUMBER1);
        DL_HSADC_enableDMAInterrupt(HSADC0_INST, DL_HSADC_DMA_INT_1);
        DL_HSADC_SetInterruptPulsePosition(HSADC0_INST, DL_HSADC_INT_PULSE_POS_EOC);
    
    
        DL_HSADC_setSubscriberChanID(HSADC0_INST, DL_HSADC_SUBSCRIBER_INDEX_0, 1);
        DL_HSADC_PowerUp(HSADC0_INST);
    }
    
    
    static const DL_DMA_Config gDMA0_CH0Config = {
        .transferMode   = DL_DMA_SINGLE_TRANSFER_MODE,
        .extendedMode   = DL_DMA_NORMAL_MODE,
        .destIncrement  = DL_DMA_ADDR_INCREMENT,
        .srcIncrement   = DL_DMA_ADDR_UNCHANGED,
        .destWidth      = DL_DMA_WIDTH_WORD,
        .srcWidth       = DL_DMA_WIDTH_WORD,
        .trigger        = DMA0_CH0_TRIGGER_SEL_ADC0,
        .triggerType    = DL_DMA_TRIGGER_TYPE_EXTERNAL,
    };
    
    SYSCONFIG_WEAK void SYSCFG_DL_DMA0_CH0_init(void)
    {
    
        DL_DMA_setDestIncrement(DMA0, DMA0_CH0_CHAN_ID, DL_DMA_ADDR_INCREMENT);
        DL_DMA_initChannel(DMA0, DMA0_CH0_CHAN_ID , (DL_DMA_Config *) &gDMA0_CH0Config);
    }
    SYSCONFIG_WEAK void SYSCFG_DL_DMA0_init(void){
        SYSCFG_DL_DMA0_CH0_init();
    }
    
    
    
      

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Eric、

    很抱歉我是 OOO。 我想我在前一条消息中附加了 SysConfig 和.c 文件、它们提供了相同的结果。 如果使用这些文件无法重新创建波形、敬请告知。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    此外、在应用中调用 DMA 时、通过增加源大小或将 DMA 传输大小加倍来确保具有 32 位的 DMA 传输大小。 这样做的原因是为了获得 soc0 和 soc1 的结果。