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.

[参考译文] AM3358:使用 PRU ADC DMA 进行数据采集

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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1476699/am3358-data-acquisition-using-pru-adc-dma

部件号:AM3358

工具/软件:

我正在使用 BeagleBone Black。
我想 使用 BB Black 内置的 ADC 以10kHz 的采样率采集数据。 我想使用 BB Black 的 PRU 和 DMA。 我不知道如何使用 DMA。

如何使用 PRU_edmaConfig.c? DMA 传输是否需要任何其他要求?

是否有任何其他快速数据传输方法?

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

    您好、Nagesh、

    我将在此处查看另一个线程上的 EDMA 示例:
    https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1478438/am3358-edma-data-transfer-using-example-code-in-pru_software_support_package

    在使用板载 ADC (不带 DMA)方面、您是否有任何问题?

    这是我编写的用于配置 ADC 并从 PRU 读取 ADC 的初始示例:
    https://git.ti.com/cgit/pru-software-support-package/pru-software-support-package/tree/examples/am335x/PRU_ADC_onChip

    此致、

    Nick

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

    感谢您发送编修。

    如上所述、我要从内置 ADC 以10kHz 的频率采集数据。 这在 RPM 中无法实现。 于是我搬到了 DMA。

    如何在 PRU_ADC_onChip 中进行更改以10kHz 频率进行10秒采集? 我已经测试了这个例子。 运行良好。 所以、我确实更改了代码、以添加 PRU 时钟速度并从 ADC 采集数据。 在不将数据存储在内存中的情况下运行代码时也可以。 但 BB Black 在将数据存储在样本[i]中时挂起。 那么、如何在此处添加 DMA、以便使用 PRU 从 ADC 传输数据?

    如何在 PRU_edmaConfig 中进行更改、以发送从内置 ADC 获取的数据并实现 PRU?

    我尝试了 EDMA 使用此处提供的设置将相同的数据从源(0x4A310000)发送到目标(0x80000000)。 在图中、其中 ACNT = 2、BCNT = 100、CCNT = 1。 Total = ACNT*BCNT*CCNT = 200。 但我得到了1028个转移计数。 您能告诉我哪里出了问题吗?

    如何处理这些类型的转账?

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

    您好、Nagesh、

    帮助我了解您的用例

    好的、我知道您要以10kHz 的速率从 ADC 进行采样(每100 μ s 1个样本)。

    您希望将数据发送到何处? 然后发送到 PRU 进行处理? Linux? 其他地方?

    如果您将数据直接从 PRU 发送到 Linux、PRU 内核在这里执行什么操作? 例如、PRU 是否会预处理 ADC 数据、或者执行其他操作?

    您的测试结果如何?  

    您如何衡量转移的计数? 如果您正在获得终端输出等、请附加该输出、以便我可以直接查看它、而不是仅描述它。

    此致、

    Nick

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

    您希望将数据发送到何处? 然后发送到 PRU 进行处理? Linux? 其他地方?  如果您将数据直接从 PRU 发送到 Linux、PRU 内核在这里执行什么操作? 例如、PRU 是否会预处理 ADC 数据、或者执行其他操作?

    >我正在将数据发送到 Linux 存储器。  我使用 PRU 以10kHz 的频率从内置 ADC 对数据进行采样。 就这样。 然后、我想 使用 EDMA 将该数据从 PRU 存储器(0x4A310000)发送到 ARM 存储器(0x80000000)。 然后、我想将所有采集的数据保存在 CSV 文件中。 这是我的想法。 如果你能告诉我更好的选择,请告诉.

    您如何衡量转移的计数? 如果您正在获得终端输出等、请附加该输出、以便我可以直接查看它、而不是仅描述它。

    >我测试了数据中给出的内容。 我发现 CCNT =(2、3、4、5等)不工作。 我只得到 ACNT*BCNT 值。

    >这是我设置的。

    #define PARAM_OFFSET (0x4000/4)
    #define OPT 0x00
    #define SRC 0x04
    #define ACNT 0x2
    #define BCNT 0xA
    #define dst 0x0C
    #define SRC_DST_BIDX 0x10
    #define LINK_BCNTRLD 0x14
    #define SRC_DST_CIDX 0x18
    #define CCNT 0x2

    params.opt.Sam = 0;
    params.opt.dam = 0;
    params.opt.syncdim = 1;
    params.opt.static_set = 0;
    params.opt.fwid = 0;
    params.optccmode = 0;
    Params.OPT.TCC = hostData.chan;
    params.optcinten = 0;
    params.optcchen = 0;
    params.opt.itcchen = 0;
    params.opt.privid = 0;
    params.opt.priv = 1;

    params.ccnt.ccnt = CCNT;
    params.abcnt.acnt = ACNT;
    params.abcnt.bcnt = BCNT;
    params.bidix.srcbidx = 0x0;
    params.bidx.dstbidx = ACNT;
    params.cidx.srccidx = 0x0;
    params.cidx.dstcidx = 0x14;
    Params.data src = src;
    params.dst = hostData.dst;

    >这是使用"sudo devmem2 0xXXXXXXXX 计数"得到的结果

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

    注1:Linux 如何访问 DDR 存储器?  

    如何将 DDR 数据暴露在 Linux 用户空间中? (我假设这是数据的使用者)。

    请注意、您需要在 Linux 器件树文件中保留要写入的存储器区域。 否则、Linux 可能随时覆盖您的数据。

    zerocopy 示例适用于其内核多于 AM335x 的处理器、但相同的概念也适用于保留一个存储器区域、该区域可用于在 Linux 和 PRU 内核之间来回传递数据:
    https://git.ti.com/cgit/rpmsg/rpmsg_char_zerocopy/log/?h=ti-linux-6.1

    (请注意、分支 ti-linux-6.1应用于 Linux 内核6.1或5.10)

    注2:我认为你是高超的  

    如果您已经必须在 DDR 中定义共享存储器区域、并且已经在编写 PRU 代码、则无需涉及 DMA。 只需使用 PRU 读取数据、根据需要进行任何次要数据滤波、并通过 PRU 内核将数据直接写入 DDR。 PRU 可以直接读取和写入 DDR 地址、就像它能够读取和写入内部 PRU DRAM 地址一样。

    如果您想允许 PRU 在 Linux 消耗另一个缓冲区中的数据的同时继续写入一个缓冲区、您甚至可以设置乒乓缓冲区等结构。

    此致、

    Nick

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

    讲述如何在 DDR 中写入数据并保留存储器区域吗?

    我只想在 DDR (0x80000000)中写入数据并将数据保存在 CSV 文件中。 我是否确实需要乒乓缓冲器来持续写入数据?

    您能否指示乒乓缓冲器在 DDR 中写入5-10秒的连续数据?  

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

    您好、Nagesh、

    这是用于大学项目吗?

    zerocopy 示例展示了如何从 Linux 分配存储器区域。 从该存储器区域读取数据并将数据写入.csv 文件超出了我们在此处可以支持的范围(即、这是一般 Linux 问题、而不是 TI 特定问题)。

    有多种不同的缓冲方案、可以在不损坏数据的情况下同时读取和写入。 ping-ping 缓冲区只是一种可能的选项。

    此致、

    Nick

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

    感谢您的答复。

    我更怀疑...

    每当我尝试 通过 PRU 存储多个样本(100000个样本)的数据从 ADC 存储到 DDR (0x80000000)时、AM335x 会崩溃、需要按电源按钮来关闭。 如何解决这个问题?

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

    您好、Nagesh、

    您是否保留了要在 Linux 器件树文件中使用的存储器区域? 如果 DDR 区域未明确保留、则 Linux 可能已经在使用该存储器区域、并且您将覆盖 Linux 数据。

    您可以 在此 AM57x 器件树文件中看到保留存储器区域的示例:
    https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/arch/arm/boot/dts/am571x-idk.dts?h=ti-linux-6.1.y-cicd

    此致、

    Nick

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

    谢谢 Nick。

    我在0x90000000处保留了40MB 的存储器区域、并且能够将数据存储在该区域中。  

    当我尝试从 PSSP (PRU_ADC_onChip)示例获取数据时、我将其更改为以10kHz 采样率获取10秒的数据。 我没有得到想要的(纯音信号)。 您能给我提供任何使用 PRU 的 ADC 示例代码吗? 此外、我还在尝试设置差模。

    图中显示了采集的数据、该数据不是纯音信号。 为了获得纯音信号或实际测量、必须进行哪些所需设置。

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

    您好、Nagesh、

    您尝试捕获的信号频率是多少? 在信号上放置示波器时、您是否看到了预期看到的信号?

    我不知道您尝试如何处理所有复杂设置(DMA、将存储器传输到 Linux、自定义 ADC 配置等)。 我们稍等片刻。

    如果您只是从 PRU_ADC_onChip 示例中复制-粘贴 ADC 设置、并从 PRU_ADC_onChip 示例中复制-粘贴 READ_ADC 函数、您会看到什么? 保持纯音信号运行。 引导 PRU、运行它、直到存储器中的 X 个数据条目填满、并使代码停止。 该数据是什么样子的?

    此致、

    Nick

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

    您好、Nick、  

            我希望捕获~0Hz 至4000Hz 的频率范围。 我 现在无法访问示波器。 但我测试了 GND_ADC 和 VDD_ADC、以查看 am3358 ADC 的响应是什么 、并正如您提到的那样进行了测试。

    情形1: 我使用了 PRU_ADC_onChip 示例。 我从代码中得到了万用表中所示的确切电压值。 这对于多次测试是如此。

    情形2: 当尝试使用 ADC 设置(ADC_CLKDIV、开路延迟和采样延迟)或 PRU 设置(DELAYCYCLES)以不同的采样率采集多个样本时、场景会发生变化。  

    ADC 设置:

    __________________

    #define ADC_CLOCK_DIV 0x17
    #define OPEN_DELAY 0x28
    #define SAMPLE_DELAY 0x2D

    ADC_TSC.STEPCONFIG4_BIT.MODE = 0;
    ADC_TSC.STEPCONFIG4_BITS.AVERAGE = 0;
    ADC_TSC.STEPCONFIG4_BIT.SEL_INP_SWC_3_0 = 7;
    ADC_TSC.STEPCONFIG4_BIT.SEL_INM_SWC_3_0 = 8;
    ADC_TSC.STEPCONFIG4_BIT.FIFO_SELECT = 0;
    ADC_TSC.STEPCONFIG4_BIT.DIFF_CNTRL = 0;
    ADC_TSC.STEPDELAY4_BIT.OPENDELAY = OPEN_DELAY;
    ADC_TSC.STEPDELAY4_BIT.SAMPLEDELAY = SAMPLE_DELAY;

    ADC_TSC.ADC_CLKDIV_BIT.ADC_CLKDIV = ADC_CLOCK_DIV;

    ____________________

    我添加了这些代码以获得10kHz 的采样率。

    图1显示了通过将 GND 连接到 ADC 通道来从 ADC 接地引脚(GND_ADC =0V)读取的数据

    图2显示了  通过将 VDD 连接到 ADC 通道从 ADC 电压引脚(VDD_ADC = 1.8V)读取的数据

    从图中可以清楚地看出、 VDD_ADC (~1.8V)和 GND_ADC (~0V)无法获得所需的内容。 如图所示、ADC 通过读取非相关样本来丢失多个样本。 即便如此、每三个读数(图1)和两个读数(图2)都是错误的。 ADC 应读取所有样本的确切值(~1.8V 或0.0V)。  因此、您能否为我提供相关设置来获取采样率的精确读数。

    注意: 我不使用 DMA;使用您建议的唯一方法... memory[i]= READ_ADC (message.channel);

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

    您好、Nick、

             正在等待您的回答!

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

    您好、Nagesh、

    感谢您的 ping。 是的、该波形看起来根本不正确。

    好的、您有一个"已知良好"的起点、并且您的当前设置看起来不正确。 您是否尝试一次只更改一个设置以找出导致不良行为的设置?

    此致、

    Nick

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

     TI 是否提供了任何 可以帮助我的方法?

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

    您好、Nagesh、

    我的最后一个答复是我将提供的指导。

    您有一个"已知良好"的起点。 根据您上面的响应、情况1: PRU_ADC_onChip、该示例按预期工作。

    然后你一次改变了一堆东西、代码不再按预期工作。

    当您一次更改多个项目时、很难准确确定哪些更改导致了问题。 请返回、尝试一次只更改一个 ADC 设置。 每次更改后进行测试。 我希望您很快就会发现哪个变化导致了奇怪的行为。

    此致、

    Nick