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.

[参考译文] MSPM0G3507:ADC 乒乓示例提供了 MEMRESx 开箱即用的溢出

Guru**** 2460850 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1477834/mspm0g3507-adc-ping-pong-example-gives-memresx-overflow-out-of-the-box

器件型号:MSPM0G3507

工具与软件:

您好!
我有一个 Launchpad 3507。 当加载 ADC 乒乓示例并添加检查 MEMRESx 溢出时、会直接将其设置。

为什么会发生这种情况?

这是修改后的示例、添加了全局标志并删除了断点(我知道断点会导致溢出)。 运行它并将 gOverflow 添加到手表中

/*
 * Copyright (c) 2021, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "ti_msp_dl_config.h"

#define ADC_SAMPLE_SIZE (64)

/* When FIFO is enabled 2 samples are compacted in a single word */
#define ADC_FIFO_SAMPLES (ADC_SAMPLE_SIZE / 2)

uint16_t gADCSamplesPing[ADC_SAMPLE_SIZE];
uint16_t gADCSamplesPong[ADC_SAMPLE_SIZE];

volatile bool gCheckADC;
volatile bool gPing;
volatile bool gOverflow;
volatile bool gUnderflow;


int main(void) {
  gOverflow = false;
  gUnderflow = false;
  gPing = true;

  SYSCFG_DL_init();

  /* Configure DMA source, destination and size */
  DL_DMA_setSrcAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)DL_ADC12_getFIFOAddress(ADC12_0_INST));
  DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)&gADCSamplesPing[0]);
  DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, ADC_FIFO_SAMPLES);
  DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);

  /* Setup interrupts on device */
  NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);

  gCheckADC = false;

  /* The ADC is configured for Repeat Single Conversion,
   * so the ADC will continue until DL_ADC12_disableConversions() is called */
  DL_ADC12_startConversion(ADC12_0_INST);

  while (1) {

    while (false == gCheckADC) {
      __WFE();
    }
    /* Breakpoint to check the buffers and watch the Ping Pong operation.
     * The data will be alternating between each buffer.
     */
    //__BKPT(0);

    /* Switch to send ADC Results to Pong Buffer */
    if (gPing) {

      DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)&gADCSamplesPong[0]);
      DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, ADC_FIFO_SAMPLES);
      DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);
      DL_ADC12_enableDMA(ADC12_0_INST);

      gPing = false;
    }
    /* Switch to send ADC Results to Ping Buffer */
    else {

      DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)&gADCSamplesPing[0]);
      DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, ADC_FIFO_SAMPLES);
      DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);
      DL_ADC12_enableDMA(ADC12_0_INST);

      gPing = true;
    }
  }

  gCheckADC = false;
}

void ADC12_0_INST_IRQHandler(void) {
  gOverflow = gOverflow || DL_ADC12_getRawInterruptStatus(ADC12_0_INST,DL_ADC12_INTERRUPT_OVERFLOW);
  gUnderflow = gUnderflow || DL_ADC12_getRawInterruptStatus(ADC12_0_INST,DL_ADC12_INTERRUPT_UNDERFLOW);
  switch (DL_ADC12_getPendingInterrupt(ADC12_0_INST)) {
  case DL_ADC12_IIDX_DMA_DONE:
    gCheckADC = true;
    break;
  default:
    break;
  }
}

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

    尊敬的 Kai:

    您可以将 DMA 触发器更改为之前的值吗? 尝试加载 MEMRES6、而不是 MEMRES11。 由于 ADC 处于重复模式、它将继续进行永久采样、而借助 FIFO、它将使用所有 MEMRES 寄存器并写入下一个数据、如果 DMA 未读取数据、这可能会覆盖之前的值、从而导致溢出中断。

    我将介绍一个代码示例、以便在 ADC 输入中实现均衡  

    此致、
    Luke

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

    将 DMA 触发器设置为 mem10已经导致下溢。 采样时间是10us、这对我来说很有意义。 此外还设置了一个溢出、这使我质疑溢出的可信度。

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

    尊敬的 Kai:

    您能否检查下溢和溢出何时被触发。 例如、第一个 DMA 上的上溢是否触发第二个 DMA 上的下溢?

    此致、
    Luke

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

    您好!
    1)在 mem10上使用 DMA 触发时:
    发生第一个 DMA 中断时设置下溢
    当第二个 DMA 中断发生时、设置溢出

    2)在 mem11上使用 DMA 触发

    当第二个 DMA 中断发生时、设置溢出

    代码  

    /*
     * Copyright (c) 2021, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    #include "ti_msp_dl_config.h"
    
    #define ADC_SAMPLE_SIZE (64)
    
    /* When FIFO is enabled 2 samples are compacted in a single word */
    #define ADC_FIFO_SAMPLES (ADC_SAMPLE_SIZE / 2)
    
    uint16_t gADCSamplesPing[ADC_SAMPLE_SIZE];
    uint16_t gADCSamplesPong[ADC_SAMPLE_SIZE];
    
    volatile bool gCheckADC;
    volatile bool gPing;
    volatile bool gOverflow;
    volatile bool gUnderflow;
    volatile uint32_t gOverflowCounter;
    volatile uint32_t gUnderflowCounter;
    
    
    int main(void) {
      gOverflow = false;
      gUnderflow = false;
      gOverflowCounter = 0U;
      gUnderflowCounter = 0U;
      gPing = true;
    
      SYSCFG_DL_init();
    
      /* Configure DMA source, destination and size */
      DL_DMA_setSrcAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)DL_ADC12_getFIFOAddress(ADC12_0_INST));
      DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)&gADCSamplesPing[0]);
      DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, ADC_FIFO_SAMPLES);
      DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);
    
      /* Setup interrupts on device */
      NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);
    
      gCheckADC = false;
    
      /* The ADC is configured for Repeat Single Conversion,
       * so the ADC will continue until DL_ADC12_disableConversions() is called */
      DL_ADC12_startConversion(ADC12_0_INST);
    
      while (1) {
    
        while (false == gCheckADC) {
          __WFE();
        }
        /* Breakpoint to check the buffers and watch the Ping Pong operation.
         * The data will be alternating between each buffer.
         */
        //__BKPT(0);
    
        /* Switch to send ADC Results to Pong Buffer */
        if (gPing) {
    
          DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)&gADCSamplesPong[0]);
          DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, ADC_FIFO_SAMPLES);
          DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);
          DL_ADC12_enableDMA(ADC12_0_INST);
    
          gPing = false;
        }
        /* Switch to send ADC Results to Ping Buffer */
        else {
    
          DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)&gADCSamplesPing[0]);
          DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, ADC_FIFO_SAMPLES);
          DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);
          DL_ADC12_enableDMA(ADC12_0_INST);
    
          gPing = true;
        }
      }
    
      gCheckADC = false;
    }
    
    void ADC12_0_INST_IRQHandler(void) {
      gOverflow = gOverflow || DL_ADC12_getRawInterruptStatus(ADC12_0_INST,DL_ADC12_INTERRUPT_OVERFLOW);
      gUnderflow = gUnderflow || DL_ADC12_getRawInterruptStatus(ADC12_0_INST,DL_ADC12_INTERRUPT_UNDERFLOW);
      if(!gOverflow){
        gOverflowCounter++;
      }
      if(!gUnderflow){
        gUnderflowCounter++;
      }
      switch (DL_ADC12_getPendingInterrupt(ADC12_0_INST)) {
      case DL_ADC12_IIDX_DMA_DONE:
        gCheckADC = true;
        break;
      default:
        break;
      }
    }

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

    谢谢 Kai、我会看看我是否可以在我的最后重复这个、并进一步调查条件。  

    是否需要在连续重复模式下使用 ADC 样本以及是否需要验证未错过任何样本?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您是否需要在连续重复模式下使用 ADC 样片以及是否希望验证未遗漏任何样片?

    完全正确、我基本上都想在示例中完成所有操作、但是我已经注意到已为我的设置设置了溢出标志。 因此、我查看了示例并发现了相同的行为。

    谢谢!

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

    尊敬的 Kai:

    您是否有目标采样率?

    我能够与当前10us 复制相同的内容、并调整采样速度、DMA 触发源(载入了 MEMRES)的参数、以及 早期中断阈值会改变 上溢和下溢条件的行为。

    目前、我正在研究避免溢出情况的配置。

    此致、
    Luke

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

    您好!
    这是我在实际项目中具有的值(4个通道上为250ns、但硬件均值计算后、因此125ns):
    硬件均值计算不是必需的。


    如果您可以找到溢出的根本原因、最好了解导致溢出的原因。

    谢谢

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

    尊敬的 Kai:

    我将缓冲区大小从64调整为12以与存储器寄存器相同、这样就停止了示例中的溢出情况。

    这种调整修复溢出的原因- DMA 完成中断不会触发、直到 DMA 事务完成、在示例中列出的值总共32个事务。 因此、在 DMA 将完成整个缓冲区大小的同时、ADC 也将继续运行并覆盖之前的事务。 通过将 DMA 事务与相同数量的 ADC MEMRES 寄存器进行匹配、DMA done 将触发、ADC 将在不写入旧值的情况下启动其事务。

    不过我无法清除溢出以反映您的采样速度、因此我认为采样速度对于重新配置来说太快。 您可以做的是重复您的通道以使用所有12个 MEMCTL 寄存器、然后最后一个 MEMCTL 将触发模式设置为"有效触发将步进到下一个存储器转换寄存器"。 然后、在重新配置 DMA 之后、再次启动 ADC 事务。 您应该能够将 ADC 保持在重复模式、但会调用 startConversions 函数。

    此致、
    Luke

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

    您好!
    我看到、演示中的问题是32不是12的倍数。

    另外两个问题:

    对于我的问题,我找不到任何文件的区别"有效的触发器"和"触发器"。
    1) 1)你知道我可以在哪里找到它吗?

    对于我的实际代码、我会注意到一旦我开始编译器优化、在连续采样期间便不会设置溢出标志。 但是、当我开始并行发送数据(通过 DMA 和 SPI)时、该位会被置位。
    2)是否有最佳实践可以处理此类负载变化。 例如、更改 ADC DMA 的 memresX 中断、或者触发更早重新启用 DMA?

    谢谢!

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

    尊敬的 Kai:

    有效触发是触发源的实例、例如、如果您通过事件或软件触发、则另一个软件调用或事件将是"有效"触发、否则它将在完成前一个触发后立即移动到下一个通道。

    有早期中断可以让 DMA 进行设置、因此中断将在所有传输完成之前触发。 在比赛条件下、如果您保证其中一个不会跑过另一个、通常会更容易处理。 因此、如果最后一个 ADC 通道等待 DMA 完成、然后重新启动 ADC 采样、您就知道 ADC 不会溢出。 问题在于将会限制您的总吞吐量、因为您将受到 DMA 完成的限制。

    您的 SPI 事务是否可预测、即:我们是控制器、还是 SPI 请求将每 X 段时间发生一次?

    如果 SPI 是可预测的、则您可以调整设置以补偿额外的处理能力。

    此致、
    Luke