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.

[参考译文] Linux/BEAGLEBN:从 PRU 读取 ADC

Guru**** 2538930 points


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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/624709/linux-beaglebn-adc-read-from-pru

器件型号:BEAGLEBN

工具/软件:Linux

大家好、

我们有一个项目、除了 Sitara / Linux 之外、我们还想使用 AM335x 通过其 PRU 子系统(HW 为 BeagleBone Green)提供的功能。

我们已经知道、PRU 似乎工作正常、Linux 用户模式应用程序工作正常、到达 PRU 的设备驱动程序似乎正常。

但是、我们似乎无法正确使用 ADC。 如果我们定期读取 ADC、我们会在有效载荷数组中获得以下内容(请参阅下面的 PRU 代码):

c909 c909 c909 c909 c909 c909 c909 c909 c909 c909 c909 c909 c909

2a0a 0000 f709 0000 CC09 0000 c109 0000

 

c909 c909 c909 c909 c909 c909 c909 c909 c909 c909 c909 c909 c909

2a0a 0000 f709 0000 CC09 0000 c109 0000

…μ A

 

这种情况会持续发生、与 ADC 输入引脚上的电压无关。 正如我所描述的、如果我们用常量值填充有效负载数组、我们所有其他软件组件都能很好地工作、并且我们可以在应用级别获得填充值。

我们在代码片段下面提供了一些内容、我们从开始、并对其进行了一些修改、以达到最佳目的。 (我们从以下网站获得了原始版本: https://raw.githubusercontent.com/rvega/bbb-pru/master/apps/adc/pru.c)

如果我们在处理 ADC 时遗漏了一些内容、是否有人会查看此代码?

或者、如果我们可以参考一个实际工作示例、我们也可以将其用于 PRU 处理 ADC。

使用 ADC 时、是否需要设置和/或复位任何其他系统组件? 其他系统部件(TSC)可能会发生碰撞?

提前感谢您、

BR、

 

代码如下:

 

#include
#include
#include "resource_table_1.h"

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define HWREG (x)(*(volatile unsigned int *)(x)))
define min <b ? (a、b)(定义最小值(a、b) a:b)

#define BLOCK_SIZE 128
#define CHANNELS 6.

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
uint16_t 有效载荷[8];

void init_adc (void){
  unsigned int data、i;

  //启用 OCP 以便我们可以访问的整个存储器映射
  来自 PRU 的//器件。 将 SYSCFG 寄存器的位4清零
  HWREG (0x26004)&= 0xFFFFFFEF;

  //启用 ADC 模块的时钟。 CM_WKUP_ADC_TSK_CLKCTL 寄存器
  HWREG (0x44e004bc)= 0x02;

  //暂时禁用 ADC 模块。 ADC_CTRL 寄存器
  HWREG (0x44e0d040)&=~(0x01);

  //计算采样率:
  // fs = 24MHz /(CLK_DIV*2 *通道*(OpenDly+Average *(14+SampleDly)))
  //我们需要48kHz。 (影响到50kHz)
  unsigned int clock_divider = 4;
  unsigned int open_delay = 4;
  unsigned int average = 1;      //可以是0 (无平均值)、1 (2个样本)、
                                  // 2 (4个样本)、 3 (8个样本)
                                  //或4 (16个样本)
  unsigned int sample_delay = 4;

  //设置时钟分频器(将寄存器设置为所需的值减1)。
  // ADC_CLKDIV 寄存器
  HWREG (0x44e0d04c)=时钟分频器- 1;

  //设置从0到 FFF 的值范围。 ADCRANGE 寄存器
  HWREG (0x44e0d048)=(0xffffff<< 16)&(0x000);

  //禁用所有步骤。 STEPENABLE 寄存器
  HWREG (0x44e0d054)&=~(0xff);

  //解锁步进配置寄存器。 ACD_CTRL 寄存器
  HWREG (0x44e0d040)|=(0x01 <<2);

  //为步骤1设置配置。 SW 模式、连续模式、
  //使用 FIFO 0,使用通道0。 STEPCONFIG1寄存器
  HWREG (0x44e0d064)= 0x0000 |(0x0<26)|(0x00<<19)|(0x00<15)|(平均值<2)|(0x01);

  //设置步骤1的延迟。 STEPDELAY1寄存器
  HWREG (0x44e0d068)= 0x0000 |(SAMPLE_DELAY - 1)<<24 | OPEN_DELAY;

  //为步骤2设置配置。 SW 模式、连续模式、
  //使用 FIFO 0,使用通道1。 STEPCONFIG2寄存器
  HWREG (0x44e0d06c)= 0x0000 |(0x0<<26)|(0x01<<19)|(0x01<15)|(平均值<2)|(0x01);

  //设置步骤2的延迟。 STEPDELAY2寄存器
  HWREG (0x44e0d070)= 0x0000 |(SAMPLE_DELAY - 1)<<24 | OPEN_DELAY;

  //为步骤3设置配置。 SW 模式、连续模式、
  //使用 FIFO 0,使用通道2。 STEPCONFIG3寄存器
  HWREG (0x44e0d074)= 0x0000 |(0x0<<26)|(0x02<<19)|(0x02<15)|(平均值<2)|(0x01);

  //设置步骤3的延迟。 STEPDELAY3寄存器
  HWREG (0x44e0d078)= 0x0000 |((SAMPLE_DELAY - 1)<<24)| OPEN_DELAY;

  //锁定步骤配置寄存器。 ACD_CTRL 寄存器
  HWREG (0x44e0d040)&=~Ω(0x01 <<2);

  //通过读取 FIFO0来清除它。 FIFO0COUNT、FIFO0DATA 寄存器
  unsigned int count = HWREG (0x44e0d0e4);
  for (i=0;<count; i++)
  {
     数据= HWREG (0x44e0d100);
  }

  //通过读取 FIFO1来清除它。 FIFO1COUNT、FIFO1DATA 寄存器
  计数= HWREG (0x44e0d0f0);
  (i=0;<count; i++)
  {
     数据= HWREG (0x44e0d200);
  }

  //启用标记通道 ID。 ADC_CTRL 寄存器
  HWREG (0x44e0d040)|= 0x02;

  //启用步骤1-4。 STEPENABLE 寄存器
  HWREG (0x44e0d054)|= 0xFE;

  //启用模块(开始采样)。 ADC_CTRL 寄存器
  HWREG (0x44e0d040)|= 0x01;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void main (void){
  unsigned int i;
  unsigned int fifo0_count;
  unsigned int 数据;
  unsigned int buffer_count = 0;
  unsigned int sample;

  CT_CFG.SYSCFG_BIT.STANDBY_INIT = 0;

  init_adc();

  while (1)
  {
     fifo0_count = HWREG (0x44e0d0e4);
  
     for (i=0;<fifo0_count; i++)
  {
   数据= HWREG (0x44e0d100);
   sample =数据和0xfff;
   PAYLOAD[buffer_count]=采样;
   Buffer_count ++;
   if (buffer_count>=8)
   {
    // 传递到其他 PRU
    _XOUT (10、21、0、有效载荷);
    asm (" LDI R31、36");
    Buffer_count = 0;
   }
  }
  }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

 

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

    我已通知工厂团队。 他们的反馈将在此处发布。

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

    要尝试以下几项操作:

    确保设备树中的"tscadc"节点内部具有"status = disable";"。 如您所知、触摸屏使用 ADC 通道0-3、并且有一个 Linux 多功能设备(MFD)驱动程序、它将尝试在触摸屏和通用 ADC 使用之间对外设的访问进行仲裁。 如果 PRU 访问的硬件与 Linux 尝试仲裁的硬件相同、则会发生冲突。 将状态设置为禁用会使 Linux 不知道外设、从而阻止这种情况发生。

    另一项建议是在 TSC/ADC 模块中发生状态转换之前进行轮询。 在时钟被启用前、任何到 TSC/ADC 模块的写入将被忽略:
    //启用 ADC 模块的时钟。 CM_WKUP_ADC_TSK_CLKCTL 寄存器
    HWREG (0x44e004bc)= 0x02;
    while (HWREG (0x44e004bc!= 0x02);

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

    您好 Jason、  

    感谢你的答复。

    确保 tscadc 确实已禁用。 我们还在设置时钟后使用"while"尝试了您的建议。 不幸的是,迄今尚未取得成功。

    我们仍在调查此问题、并尝试将此问题减少到更小的区域。 我希望我们能很快提出一个更具体的问题。

    这一问题对我们仍然很重要,因此我们继续努力寻找解决办法。

    如果您能给我们提供任何进一步的提示、我们将不胜感激。

    BR、

    Gyula

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

    Gyula、

    请在此处查看我对类似问题的答复: e2e.ti.com/.../2042212

    您能否查看此加电序列(或上面提供的代码)是否有帮助?

    Jason Reeder

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

    我们已经在您过去提到的代码中检查过该代码。 不幸的是、它对我们不起作用。
    最后、在不可计数的尝试之后、我们发现了一个似乎对我们也适用的代码。

    对于可能遇到类似"入门内容"问题的其他人、下面是指向此人来源的链接:
    github.com/.../pru0_main.c

    当然、我们从他的代码中省略了 GPIO 内容。
    感谢他的发表!

    也感谢您努力指导我们进入 PRU 和 ADC 世界。

    BR、
    Gyula