工具/软件:
我正在使用 BeagleBone Black。
我想 使用 BB Black 内置的 ADC 以10kHz 的采样率采集数据。 我想使用 BB Black 的 PRU 和 DMA。 我不知道如何使用 DMA。
如何使用 PRU_edmaConfig.c? DMA 传输是否需要任何其他要求?
是否有任何其他快速数据传输方法?
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.
您好、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
您好、Nagesh、
这是用于大学项目吗?
zerocopy 示例展示了如何从 Linux 分配存储器区域。 从该存储器区域读取数据并将数据写入.csv 文件超出了我们在此处可以支持的范围(即、这是一般 Linux 问题、而不是 TI 特定问题)。
有多种不同的缓冲方案、可以在不损坏数据的情况下同时读取和写入。 ping-ping 缓冲区只是一种可能的选项。
此致、
Nick
您好、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);
您好、Nagesh、
我的最后一个答复是我将提供的指导。
您有一个"已知良好"的起点。 根据您上面的响应、情况1: PRU_ADC_onChip、该示例按预期工作。
然后你一次改变了一堆东西、代码不再按预期工作。
当您一次更改多个项目时、很难准确确定哪些更改导致了问题。 请返回、尝试一次只更改一个 ADC 设置。 每次更改后进行测试。 我希望您很快就会发现哪个变化导致了奇怪的行为。
此致、
Nick