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.

[参考译文] 编译器/处理器 SDK-AM335X:从 PRU 到 ARM 的数据传输

Guru**** 2553370 points


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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/608062/compiler-processor-sdk-am335x-data-transfer-from-pru-to-arm

器件型号:PROCESSOR-SDK-AM335X

工具/软件:TI C/C++编译器

我正在尝试使用 PRU 作为我的研究的编码器。

我使用的是 BeagleBlack 板、具有 Debian 和 RT_preempt 补丁。
我的目标是能够从 PRU (在 PRU 中计算)发送一个整数并将其发送到 ARM、以便能够实时使用它。 我的背景是机械结构、因此我在理解该过程时遇到了一些问题。 尽管如此、我一直在尝试了解 TI 和某个 git 集线器库(https://github.com/ZeekHuge/BeagleScope)上提出的示例。 到目前为止、我可以使用 PRU_rpmsg_send 函数计算 PRU 上的值并将其发送到 ARM、但当我对该值执行 cat 命令时、我会获得一个字母或一个未知的字符。 我已经尝试了多种解决方案来避免这种情况、但我无法确定这种情况。

您能帮您解决这个问题。

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

    TI 不支持 Debian。 我将通知 PRU 专家。 如果他们有一些建议、他们会在这里发表评论。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    当您从用户空间中“cat”该值时,它在显示该值时采用 ASCII 字符编码。 例如、十进制值65将显示为"A"。

    您需要使用用户空间程序来打开/dev/rpmsg_pruX 字符设备、从字符设备读取数据、然后将读取值转换为所需的类型:

    PRU 侧:
    int number = 65;
    PRU_rpmsg_send (&transport、dst、src、&number、sizeof (int));

    ARM 用户空间 C 程序:
    #define MAX_BUFFER_SIZE 512
    char readBuf[MAX_buffer_size];
    struct pollfd pollfds[1];
    INT RESULT = 0;
    int 编号;
    /*打开 rpmsg_PRU 字符设备文件*/
    pollfds[0].fd =打开(/dev/rpmsg_pru30、O_RDWR);
    结果=读取(pollfds[0].fd、readBuf、MAX_buffer_size);
    if (结果>0)
        number=(int*) readBuf;
    /*关闭 rpmsg_PRU 字符设备文件*/
    Close (pollfds[0].fd);

    我没有准确测试该代码、但它应该非常接近您的需求。

    Jason Reeder

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

    非常感谢您的快速回答。 我是按照你的建议做的,也是我自己做的一些事情。 由于输出值与我在 PRU 侧设置的输出值相同、因此看起来工作正常。 我尝试的值大于255、在我的情况下为1000。 此外、我使用的是 C++、但我认为它没有那么大的变化。 如果其他人有相同的问题、我将编写我的代码。

    PRU 侧:

    int number = 1000;
    PRU_rpmsg_send (&transport、dst、src、&number、sizeof (int));

    ARM 用户空间 C++程序:

    #define MAX_BUFFER_SIZE 512
    char readBuf[MAX_buffer_size];
    struct pollfd pollfds[1];
    INT RESULT = 0;
    int 编号1;
    int 编号2;
    int 编号3;
    int 编号4;
    int finalResult;
    char filename[18]="/dev/rpmsg_pru31;
    int fd;

    /*打开 rpmsg_PRU 字符设备文件*/
    pollfds[0].fd = open (filename、O_RDWR);
    结果=读取(pollfds[0].fd、readBuf、MAX_buffer_size);
    if (结果>0)
          number1=(int)(readBuf[0]);
          number2=(int)(readBuf[1]);
          Number3=(int)(readBuf[2]);
          Number4=(int)(readBuf[3]);
    /*关闭 rpmsg_PRU 字符设备文件*/
    Close (pollfds[0].fd);

    finalResult=number1+number2*256+number3*256*256+number4*256*256*256*256;
    COUT <<"PRU 发送的号码为:"<< finalResult << endl;

    由于我想将其用于实时目的、我将测试它是否可以在1ms 循环中完成、并发布结果。

    总之、非常感谢您的帮助、质量和速度。

    V. Babin

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

    Reeder 先生,感谢你的支持。

    正如我先前所说的、我已经测试了您的解决方案、但我仍然面临一些问题。 为了对其进行解释、我将进一步详细介绍在我的案例中使用 PRU 的目标。

    我想将 PRU 用作"计数器板":从连接到信号 A 和 B 的两个引脚、我希望能够测量编码器给出的角度。 为此、PRU 会创建一个 while 循环、如果逻辑状态与上一个逻辑状态不同、则该循环会检查每个引脚。 如果与逻辑测试不同、我可以说它是正还是负递增。 (到目前为止、我仅使用引脚、但希望扩展到2)。 如前所述、我通过 PRU_rpmsg_send 将该值发送到 ARM。

    我现在面临的问题是在手臂侧。 目的是每1ms 获取一次 PRU 发送的最后一个值、以使用它来实时计算编码器的速度(我不需要 PRU 发送的所有值、而只需要最新值)。 根据我现在使用的方法、似乎我从读取的最新值读取缓冲区。 这会产生两个问题、我无法访问发送的最新值、因此速度计算错误、并且缓冲区似乎已满(通道的逻辑状态每 ms 变化大约10次、因此10kHz)。 根据我所阅读的不同文档、

    https://git.ti.com/pru-software-support-package/pru-software-support-package/blobs/fcbe64c1fbde0ae0f4946a2c3a67c224895b67d3/lib/src/rpmsg_lib/pru_rpmsg.c

    https://git.ti.com/pru-software-support-package/pru-software-support-package/blobs/aa9606013059eb8728bcc1165c5032f0589469e0/include/pru_rpmsg.h

    https://git.ti.com/pru-software-support-package/pru-software-support-package/blobs/aa9606013059eb8728bcc1165c5032f0589469e0/include/pru_virtqueue.h

    我觉得只有当 ARM 读取时、才会从缓冲区中删除一个数据。

    那么,您能否告诉我是否有一个解决方案来读取缓冲区的最后一个值? 读取最后一个值后是否有删除缓冲区内容的解决方案?

    此致、

    V. Babin

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

    rpmsg 字符设备驱动程序使用内核 FIFO 来存储来自 PRU 的消息、直到用户空间读取这些消息。 因此、您的观察结果是正确的、即您在读取时未看到来自 PRU 的最新消息(先入先出)、并且如果用户空间未从 PRU 中读取、则 FIFO 将会填满、因为 PRU 会继续写入该消息。

    以下是几种实现您所需结果的方法:

    • 在用户空间和 PRU 之间设置一个非常简单的请求协议
      • 拥有用户空间发送 PRU 发送最新数据的请求(可能就像将一个字符从用户空间写入 rpmsg_PRU 设备一样简单)
      • PRU 可以持续监控引脚并保留最新数据的本地副本。 当从用户空间接收到消息时、PRU 可以发送包含最新数据的消息
      • 让用户空间每毫秒发送一次请求
    • 只有 PRU 每毫秒发送一次最新数据
      • 您可以使用 PRU_ICSS_PRU_CTRL 寄存器中的周期寄存器、该寄存器设置为每毫秒仅发送一个包含最新数据的 rpmsg
    • 您可以让用户空间程序不断从字符设备读取数据并丢弃除每毫秒一条消息外的所有数据

    我的建议是第一个选择、但这三个选项都适用于您的用例。

    Jason Reeder

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

    非常感谢您的回复。

    我已经通过修改"Hello World"示例的代码尝试了您的第一个选项、我能够每1ms 进行一次通信。 尽管如此、由于我使用 PRU 的目标是为编码器做一个计数器板、因此我在环路两个引脚(编码器的通道 A 和 B)的逻辑状态的同时检查 A (无限)内的情况、并在必要时递增角度。 该解决方案在编码器的速度旋转达到一定速度之前工作正常。 ARM 和 PRU 之间的通信似乎需要太多的时间、因此 while 循环需要太多的时间来完成、从而在循环期间丢失了逻辑状态的更改。

    PS:从 ARM 方面,我使用时间戳来测量向 PRU 发送消息并接收应答的持续时间,在 BeagleBone Black 上,使用 RT_PREOTE 修补程序,完成该过程大约需要0.4ms。

    我将继续搜索更快地将数据传输到 ARM 的方法。

    此致、

    V. Babin