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/AM3352:在用户空间中寻找快速高效的 UART 处理

Guru**** 2559190 points
Other Parts Discussed in Thread: AM3352

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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/625504/linux-am3352-looking-for-quick-and-efficient-uart-handling-in-userspace

器件型号:AM3352

工具/软件:Linux

你(们)好

我在基于运行内核4.4.19的 BeagleBone 的定制板上运行

root@AM335x-EVM:~ cm# uname -a
Linux AM335x-EVM 4.4.4.19-gdb0b54cdd #238抢先于8月25日星期五16:25:18 AEST 2017 armv7l GNU/Linux 

我想知道获取快速高效 UART 通信的最佳方式是什么。

电路板的布局使得 am3352和 DSP 之间有一个 UART 通信
还有一个 GPIO 用作从 DSP 到 am3352的 IRQ。

工艺流程如下。
- DSP 断言 IRQ GPIO 线路
- DSP 在 UART 上发送22个字节
- am3352检测 IRQ GPIO 并向 DSP 发送12个字节
- am3352从 UART 接收字节

每10ms 就会发生这样的交换。

目前、我正在调用轮询、观察 GPIO 和 UART 节点的文件描述符。
UART 端口配置为115k2波特、原始模式和低延迟。

在这种配置下、我发现22个字节通常以3个块的形式读取。
即、每10ms、对于 GPIO、轮询返回一次、对于 UART、轮询返回三次

使用顶部观察该过程使用93%的 CPU;这似乎太过分了。

理想情况下、我希望指定在大约200uS 的"超时"后通知传入字节的 UART;以便我可以读取一次这些字节

但是、termios 结构中的 VTIME 仅具有0.1的分辨率
-是否有人知道以比这更精确的分辨率在原始模式下配置 TTY 节点行为的方法?
或者还有其他方法可以做到这一点吗?

感谢您的任何建议。


祝你一切顺利、
Richard

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

    我通过 www.ti.com/.../spruh73p.pdf 了解了 AM335x TRM。 第4319页详细介绍了 UART 的 DMA 请求。 我很好奇、您是否可以了解这一点。 它可以帮助降低 CPU 负载、您的应用可以平稳运行。
    请分享您的观察结果。

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

    谢谢

    我了解了有关 UART 处理的 TRM  

    • 我尝试使用已分配给另一个(未使用) UART 的 DRM 通道、但在尝试读取文件时、似乎会迅速出现资源占用错误
    • 现在、我已经返回到非 DRM 方法。

    我一直在尝试 VTIME 和 Vmin、并有一些意外的观察结果。

    • VTIME 阈值看起来明显小于所要求的0.1秒
    • 在某种程度上、我可以将我的24字节数据包作为单次读取接收。

    在薄循环中实施计时器时,我可以看到,等待轮询返回的时间超过95%

    但是,如果我在另一个 shell 上运行,我可以看到简单的测试应用程序占用了大于92%的 CPU  

    如果能了解到为什么会发生这种情况,我将不胜感激。

    感谢您的任何建议。

    此致、

    Richard

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

    感谢您分享您的观察结果。 是否确定>92%的 CPU 负载是由 ARM-DSP UART 代码引起的? 我可以看到、您每10ms 使用一个 GPIO 来实现 IRQ。 IRQ 是每次升高还是处于轮询模式?

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

    我已经移除了 GPIO 轮询、现在尝试隔离周期的运行位置。

    代码的结构如下所示:

    静态内联 void _handleGet (int FD){
    const uint16_t kReadBufferSize = 512;
    uint8_t buffer[kReadBufferSize];
    
    int bytes_available;
    ioctl (FD、FIONREAD、 bytes_available);
    
    if (bytes_available > kReadBufferSize){
    InCounter.overoverp++;
    //游戏 over - clear
    tcflush (fd、TCIFLUSH);
    }
    int n = read (fd、&buffer、kReadBufferSize);
    if (n > 0){
    FIFOBuffer* fb = comms_getLUSH;}int (
    i
    
    
    )(i +);(i +);(in +)(i +);(i +
    
    }
    
    //在无限 while 循环中调用

    //根据返回代码 触发事件_handleTriggers (const int portFile){ uint8_t gpioByte; const uint8_t kDescriptorCount = 1; struct pollfd 巡回检测[2]={ .fd = pollFile、&Events =(Pollin | POLLPRI | portLERR)= 0; pollt pollt polld*= 0;pollt pollt pollt pands = 0*= pollt pollt pt pollt pollt pollt pollt poll 触发事件结果= kNoEvent; while (结果= kNoEvent){ _stampTime (kPoll); RV = POLL (POLs、kDescriptorCount、20000); _stampTime (kPollStops); if (RV > 0){ if (port->REVENDRVENDRVENDRV & Pollin)||(port->REVENVENDRVENVENVENVENDR& POLLPRI))}{ result |= kMessageEvent; handleGet (port->FD); } 其他{ sToCount++; } 返回 结果; }

    我在轮询函数前后设置时间戳、并继续运行这两个戳之间的差异的直方图、我会定期复位这两个戳:

    轮询时间(us)值=二进制上限
    纸槽0 9000 55
    纸槽1 9250 6.
    纸槽2 9500 4.
    纸槽3 9750 55
    纸槽4 10000 2822
    纸槽5 > 10000 58
    外部投票时间(us)
    纸槽0 200 2463
    纸槽1 500 528
    纸槽2 1000 1
    bin 3 2000 0
    纸槽4 5000 7.
    纸槽5 > 5000 0
    

    将发送的字节间隔为10ms、并且每次调用_handleGet 时字节记录确认我将接收到24个字节  

    因此、在绝大多数情况下、这只是等待民意测验电话返回:  

    但是、"运行顶层"可提供:

    PID 用户 PR NI virt RES SHR S %CPU %MEM time+命令
    1375根 20 0 9620 1100 1024 R 94.2 0.4 0:41.61 dspwatch <<这是简单的测试应用
    1380根 20 0 3036 1776 1388 R 3.4 0.7 0:00.64顶部
    749根 20 0 2292 836 748 S 0.9 0.3 7:59.32 rngd 

    这是我无法解释的。

    我在使用选择、轮询或 epoll 之间看不到 CPU 使用率的明显变化
    如果我添加/删除 GPIO 文件描述符的轮询或删除传出数据包的传输、也不会改变

    感谢您的任何建议。

    祝你一切顺利、

    Richard