目录

利用DMA实现乒乓操作

设计步骤与注意事项

软件流程图与代码

瓶颈优化策略


利用DMA实现乒乓操作

“乒乓操作”是一种典型的用空间换时间操作,它本身并不能弥补高速数据流与低速计算单元之间的矛盾,高速数据流还是要“等待”低速运算完成,但是“乒乓操作”给高速数据流提供了两条独立的数据存储的链路,使得运算单元能够提前起跑,降低了整个链路的时间。

在雷达编程中这种乒乓操作实现在高速ADC采样和FFT运算之间,这里读者可以把DMA想象成一个专用的核心,它的功能仅仅是对数据进行搬运。DMA通常用于将数据传输到一个缓冲器,同时 CPU使用另一个缓冲器进行FFT运算。如下图所示,蓝色路径显示 DMA 将数据传输到缓冲区 1,CPU 从缓冲区 2 获取数据。当路径切换时,DMA 将数据传输到缓冲区 2,CPU 从 缓冲区 1 获取数据。这种技术的好处是整个应用程序的运行时更短,因为 CPU 在任何时候都可以自由地对一部分 数据进行操作。在该示例中,ADC 配置为单次转换模式,DMA 和 CPU 将在每次转换后在缓冲区之间切换。

雷达编程实战之提高探测速度-LMLPHP


设计步骤与注意事项

设计步骤如下:

  1. 根据给定的模拟输入和设计要求确定 ADC 的配置,包括基准源、基准值、分辨率和采样率。
  2. 生成 2 个数组缓冲区来存储 ADC 数据并将缓冲区大小和 DMA 传输大小设置为相同,以便 DMA 填充整个缓 冲区。
  3. 根据步骤 1 中的工程要求在 SysConfig 中配置 ADC。
  4. 在 SysConfig 中,在 ADC 部分中配置 DMA。
  5. 编写应用程序代码以动态更改 DMA 的目标地址,从而在两个缓冲区之间交替。

设计要注意的事项如下:

  1. 最大采样速度:ADC 的采样速度基于输入信号频率、模拟前端、滤波器或任何其他影响采样的设计参数。
  2. ADC 基准:选择与预期最大输入保持一致的基准,以利用 ADC 的满量程范围。
  3. 点击“Settings”:时钟源决定了转换的总时间。时钟分频器与 SCOMP 设置一起决定总采样时间。 SysConfig 根据采样时间设置来设置相应的 SCOMP。

软件流程图与代码

软件流程图如下:

雷达编程实战之提高探测速度-LMLPHP

Ti实现代码如下,用户可以根据注释获得这种“乒乓操作”更直观的认识。 

/*
 * 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;

int main(void) {

  uint16_t maxReading;
  bool ping = true;
  uint16_t *ADCSamplesCurrDataPtr;

  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_Full_Ch_setEarlyInterruptThreshold(
      DMA, DMA_CH0_CHAN_ID, DL_DMA_EARLY_INTERRUPT_THRESHOLD_HALF);
  DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);

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

  gCheckADC = false;

  DL_ADC12_enableConversions(ADC12_0_INST);
  DL_ADC12_startConversion(ADC12_0_INST);

  while (1) {

    while (false == gCheckADC) {
      __WFE();
    }
    // Breakpoint here to check the buffers and watch the ping pong operation.
    // The data should be alternating between each buffer.
    __BKPT(0);

    if (ping) { // Switch to pong

      ADCSamplesCurrDataPtr = gADCSamplesPing;

      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_Full_Ch_setEarlyInterruptThreshold(
          DMA, DMA_CH0_CHAN_ID, DL_DMA_EARLY_INTERRUPT_THRESHOLD_HALF);
      DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);

      gCheckADC = false;
      ping = false;

      DL_ADC12_enableDMA(ADC12_0_INST);
      DL_ADC12_enableConversions(ADC12_0_INST);
      DL_ADC12_startConversion(ADC12_0_INST);

    } else { // Switch to Ping

      ADCSamplesCurrDataPtr = gADCSamplesPong;

      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_Full_Ch_setEarlyInterruptThreshold(
          DMA, DMA_CH0_CHAN_ID, DL_DMA_EARLY_INTERRUPT_THRESHOLD_HALF);
      DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);

      gCheckADC = false;
      ping = true;

      DL_ADC12_enableDMA(ADC12_0_INST);
      DL_ADC12_enableConversions(ADC12_0_INST);
      DL_ADC12_startConversion(ADC12_0_INST);
    }
  }
}

void ADC12_0_INST_IRQHandler(void) {
  switch (DL_ADC12_getPendingInterrupt(ADC12_0_INST)) {
  case DL_ADC12_IIDX_DMA_DONE:
    gCheckADC = true;
    break;
  default:
    break;
  }
}

瓶颈优化策略

整个雷达工作周期的瓶颈,来自一头一尾:头调频连续波到ADC回波采样的射频模拟部分,尾是从点云到航迹目标的数据处理部分。针对这个头,可以针对产品情景进行一些包括调频时长等相关参数的调整来达到帧周期的缩短,这部分我就不赘述了,感兴趣的朋友可以从《雷达编程实战之功耗优化技术(低功耗)》文章中寻求到方法,而这篇文章主要针对这个数据处理的尾巴来讲一下两个优化的策略,而这两个优化策略主要针对两种不同平台资源的情况进行选择。

首先如果我们的芯片平台存在多个DSP核心以及ARM核心,那么我们完全可以合理分配计算资源,达到理论上最快的帧频率,下面是几点分配的原则。

  • 有一个DSP核心很可能承担了信号处理流程的计算工作,然而另一个DSP核心可以与此核心配合,完成多条信号处理链路同时进行,进一步提高点云信息的丰富/置信度,数据处理也可以单独拎出一个DSP核来处理,核间可以通过操作系统提供的Message实现同步,共享RAM进行合理分区,利用标志位标识RAM区当前状态,设计时应尽可能压榨核心等待时间。
  • ARM处理大部分外设控制以及基础软件涉及的业务逻辑与协议栈实现,保证系统正常运行。

如果我们芯片平台仅仅存在一个DSP核心和一个ARM核心,那么我们就需要为整体的产品性能来考虑一些事情了。依然有一个DSP核心承担了信号处理流程的计算工作,而且很有可能它已经没有多余的RAM空间来进行别的计算了,芯片本身很可能在设计之初就没有考虑要进行数据处理(直接出点云给域控制器),而如果我们要硬上(毕竟要做一些数据处理算法来当作研发亮点),那就只可能放在ARM来跑,不过很可惜,这个方案是个陷阱,下面我来介绍一种在这种平台跑算法的方案。

  • 信号处理链路有很多涉及到了硬核的运算,我们可以合理利用硬核的中断,来动态分配任务的优先级。首先我们预存一帧A的点云数据,然后继续进行下一帧B的信号处理流程,在DSP等待硬核处理的间隙,动态提高数据处理任务优先级,并启动调度,数据处理任务拿到DSP资源之后进行A点云数据进行处理,当硬核处理完成之后,进入硬核中断函数,降低数据处理任务优先级,执行上下文切换之后,将DSP核心重新交回信号处理流程。当最终DSP核完成信号处理流程之后,通过Mailbox将当前信号处理以及数据处理流程信息传递给ARM核心。
  • ARM核心做策略判断,如果数据处理没有做完,根据传递过来的信息来综合判断是否由ARM核继续执行剩余算法,如果不执行则Mailbox回传信息暂停信号处理流程,进行数据处理直至完成。

10-05 05:32