我对 DMA 工作集更新有一些疑问。
- 更新频率如何? 该文件说‘仲裁时’,但这似乎有点手摇。
- 是否有办法强制进行仲裁、以便在我检查工作集时始终更新该工作集? 当前我正在触发一个到最高优先级 DMA 通道的软件请求来复制1个字节。 这是否会强制仲裁? 如果通道由于已完成复制1个字节的硬件请求并且当前正在等待下一个字节的另一个硬件请求而没有‘活动’,会发生什么情况?
- 如果 DMA 通道无法及时处理请求、SCI 是否可以丢弃字节? 我当前为2个独立的 SCI 端口启用了该 RX 缓冲器。
- 我将在下面发布尝试通过轮询使 DMA 正常工作的方法。 这是否合理,或者是 DMA 的限制,我在这种情况下不能使用它?
最终目标:使用 DMA 将 SCI 接收到的字节复制到循环缓冲区、并通过轮询 DMA 寄存器在没有中断的情况下处理这些字节。
因为在您不知道当前设置的数据包的完整大小的情况下,DMA 不能很好地工作。
- 512字节循环缓冲区、DMA 将字节从 SCI->RD 复制到使用 DMA_HW 请求和 AUTO_INIT 打开、因此我不必重新启动它。
- 1个字节元素、每帧1个元素。 SCI 处于单字节模式。 (与多缓冲器相反)
- 设置 Porta / PortB BYPASS、以便立即复制1个字节以实现更快的通道仲裁。
轮询结构:
每个轮询间隔我都会检查以下内容:
FTCFLAG、用于查看 DMA 通道是否已处理帧传输请求。
如果是、
我清除 FTCFLAG。
我启动一个高优先级1字节 DMA 副本、该副本应启动任何活动通道并强制仲裁以更新工作集。
我禁用所有中断(错误除外)
我检查工作集、使缓冲区中当前的字节数递增、这是由于该通道的 CTCOUNT 寄存器中剩余的帧发生了变化。
我通过检查当前剩余的帧是否>之前剩余的帧来处理缓冲区回绕。 (表示 DMA 已完成并重新启动。 我想我也可以通过检查 BTFLAG 寄存器来获取该值)
我重新启用所有中断
如果否、我退出、直至下一轮询间隔。
我可以检查一下缓冲区中的字节数是否超过了缓冲区的大小(在我可以提取一些字节之前、我们已经走得太远并覆盖了缓冲区)。
当前波特率为115200、当前轮询率为333hz (轮询间隔为3ms)。 我目前绝对不会使链路饱和。 平均每秒250-700字节。
我的数据包大小不定,但具有特定的开始/结束字符,因此我有一个单独的过程来检查 DMA 请求复制到的‘字节接收器’缓冲区,然后提取并处理整个消息。 我遇到的问题是、有时 FTCFLAG 已设置、但工作集未更改。 这是因为过早清除 FTCFLAG 吗? 如果我太晚清除它、即使已接收到字节、也可能跳过轮询间隔。 (假设 DMA 请求在高优先级通道之后、但在我清除标志之前得到处理)。
我似乎也在丢弃数据包,尽管从理论上讲,这不应该丢弃任何字节。 (发送的每条消息都需要响应,有时我的响应都很晚,例如,超过300毫秒后,这样它们就会触发‘超时’错误,但一组数据包没有响应,表明有两种情况之一。 1.他们没有得到处理,2. 消息响应未排队/发送。 我目前正在调查此问题,如果未处理此问题,则可能是由于缺少字节而导致 CRC 失败,因此 TX 响应将排队进入类似的512缓冲区,该缓冲区使用单独的 DMA 通道发送 TX, 如果一次有太多消息排队、我可能会丢弃响应。)
我想 DMA 实际上可能会在轮询请求之间写入字节525、但我提取字节的过程会将该数字减少到低于下一轮询间隔之前的最大值。 我怀疑情况确实如此,但这并不是不可能的。 如果在轮询间隔期间 bufferCount > buffer_MAX_size、并且我通过 CTCOUNT 寄存器中的 FTC 变化递增 bufferCount、则设置了一个断点来触发。 它没有被击中。