【问题标题】:Chip to chip communication protocol over SPI通过 SPI 的芯片到芯片通信协议
【发布时间】:2013-09-30 00:19:12
【问题描述】:

我正在尝试通过 SPI 在一侧的微控制器和另一侧的多核 TI 芯片上的 ARM 处理器之间设计一种有效的通信协议。

所需协议的要求:

1 - 支持排队的多会话,因为我有多个发送/接收线程,所以使用此通信协议的应用程序将不止一个,我需要该协议来处理这些请求的排队(我将继续持有缓冲区如果传输是队列,但我只需要协议来管理调度队列)。

2 - 通过 SPI 作为底层协议工作。

3 - 简单的错误检查。

在此线程:“Simple serial point-to-point communication protocol”中,PPP 是推荐的选项,但我认为 PPP 只完成了部分工作。

我还发现了轻量级 IP (LwIP) 项目,其特点是 PPP over serial(我假设我可以通过 SPI 使用它),所以我考虑了使用任何上层协议(如 TCP/UDP)的可能性其余所需的工作。幸运的是,我发现 TI 将 LwIP 作为其以太网软件的一部分包含在 starterware 包中,我认为这至少可以简化 TI 芯片方面的移植。

所以,我的问题是:

1 - 在这种通信方案中使用 LwIP 是否有效?由于 IP 标头对于点对点(芯片级)通信来说不是必需的,这会不会引入很多开销并降低吞吐量?

2 - 驻留在 LwIP 中的 TCP 或任何类似协议是否会处理传输请求的排队,例如,如果我通过套接字请求传输,而通信通道正忙于发送/接收对另一个线程的另一个套接字(会话)的请求,这会由协议栈管理吗?如果有,由哪个协议层管理?

3 - 它们是比 LwIP 更高效的协议栈,满足上述要求吗?

更新 1:需要考虑的更多要点

1 - SPI 是唯一可用的选项,我将它与可用的 GPIO 一起使用,以在从机有数据要发送时向主机指示。

2 - 当前实现的(非标准)协议使用带有SPI的DMA,消息格式为《STX_MsgID_length_payload_ETX》,消息片段长度固定,但当前方案的主要缺点是主机等待响应在发送另一个消息之前先处理消息(不是片段),这会降低吞吐量并且没有利用 SPI 的全双工特性。

3- 对这一点的改进是使用一种邮箱来接收分片,因此长消息可以被更高优先级的邮件打断,这样单个消息的分片就可以非顺序到达,但问题是这种设计导致事情变得复杂,特别是我没有太多可用资源供许多缓冲区使用控制器(主)端的邮箱方法。所以我认为这就像我在重新发明轮子,为一个简单的点对点链接设计一个协议栈,这可能效率不高。

4- SPI之上一般可以使用什么样的更高级的协议来建立多个会话,解决消息的排队/调度问题?

更新 2: 另一个有用的帖子“A good serial communications protocol/stack for embedded devices?

更新 3: 我看了 Modbus 协议,它似乎指定了应用层,然后直接指定了数据链路层用于串行线路通信,这听起来可以跳过面向网络的协议的不必要开销层。

对于预期目的,您认为这会比 LwIP 更好吗?另外,有没有像 LwIP 一样被广泛使用的开源实现,但适用于 Modbus?

【问题讨论】:

  • spi 是主从不是双向的。如果您想使用 lwip 或其他协议,您可能想使用串行/uart 而不是 spi。 lwip 会有很多开销,你可以自己做。
  • @dwelch - USB 也是主/从,但这很容易通过定期轮询从属设备来解决。
  • 不幸的是 SPI 是可用的选项,我已经将它与另一个 GPIO 一起使用,以便在从站数据可用时向主站指示。
  • 克里斯,明白,但也明白 USB 是为此而设计的,而且大部分轮询都内置在硬件中,不一定是软件必须经常做的事情。
  • 当然,必须在软件中进行轮询效率有点低,但看起来 OP 已经实现了硬件注意信号,所以这不是问题。

标签: embedded spi lwip


【解决方案1】:

我认为也许您对不起眼的 SPI 期望过高。

SPI 链接只是每个节点中的一对移位寄存器。主机选择单个节点连接到其 SPI 移位寄存器。当它移入数据时,从机同时移出数据。除非主机明确将数据输出时钟,否则不会交换数据。 SPI 上的高效协议涉及从机在主机输入时输出有用的东西。这可能很难安排,因此您通常需要一种指示空数据的方法。

在两个任意端点之间建立连接时,PPP 很有用,当端点是固定的并且事先知道的时,PPP 只会使事情变得不必要地复杂化。

SPI 不是一个非常复杂也不灵活的接口,可能不适合 TCP/IP 等重量级通用协议。由于 SPI 上的“寻址”是通过物理片选执行的,因此此类协议中固有的寻址是没有意义的。

流控制也是 SPI 的一个问题。在推送更多数据之前,主设备无法确定从设备是否已将数据从 SPI 复制到移位寄存器。如果您的从属 SPI 支持 DMA,您最好使用它。

无论哪种方式,我都建议您根据自己的目的开发一些特定的东西。由于 SPI 本身不是一个网络,因此您只需要一种方法来寻址所选节点上的线程。这可以像STX<thread ID><length><payload>ETX 一样简单。

2013 年 9 月 27 日添加以响应 cmets 通常 SPI 顾名思义用于连接外围设备,在这种情况下,协议由外围设备定义。例如,EEPROMS 通常使用跨供应商的通用或至少兼容的命令接口,而 SD/MMC 卡 SPI 接口使用标准化的命令测试和协议。

在两个微控制器之间,我想大多数实现都是专有的和特定于应用程序的。开放协议是为通用互操作性而设计的,并且可能会为封闭系统带来大量不必要的开销,除非节点运行的系统可能已经内置了网络堆栈。

我建议如果您确实想使用通用网络堆栈,您应该在每一端使用设备驱动程序抽象 SPI,这些设备驱动程序为 SPI 提供标准 I/O 流接口(open()、close()、read ()、write() 等),那么您可以使用更高级别的 PPP 和 TCP/IP 协议(​​尽管可能可以避免使用 PPP,因为连接是永久的)。但是,只有在两个节点都支持这些协议(例如运行 Linux)的情况下,这才具有吸引力,否则这将是大量的工作和代码,但收益甚微,而且肯定不会“高效”。

【讨论】:

  • 这些点中的大部分(可能除了最终吞吐量之外)也适用于 USB,但是通过 USB 到外部网络适配器运行网络协议被认为是完全合理的,甚至可以回到 12MB 的时代/s USB,SPI 可以适度小心匹配。确实没有理由不能与 SPI 一起使用相同的解决方案方法,例如主设备定期轮询从设备。
  • @ChrisStratton:没错,但也许不值得付出努力(至少对于所描述的应用程序而言)。 USB 比 SPI 复杂得多,它定义了硬件、互连、软件堆栈和设备配置文件。 SPI 没有定义这些,而且 SPI 控制器更加原始,实际上您可以使用 GPIO 和软件来实现 SPI。 USB 的回报是能够连接到第三方设备;借助 SPI,SD/MMC 卡和 EEPROM 等第三方设备使用更简单的协议。
  • 您也可以使用 GPIO 实现 USB。关键是如果 SPI 是可用的,它就可以发挥作用——您关心的是效率低下,而不是障碍。
  • 感谢您的回答和 cmets,您的意思是 ppp 所做的工作已经由 spi 处理,因为连接已经建立?请参阅已编辑的问题以获取与您的答案相关的一些附加点。
  • @ChrisStratton:我从来没有听说过有人在有点搞砸的 USB 中实现,如果它成功甚至 USB-IF 兼容,我会感到惊讶。 Bit-bashing SPI 很常见。
【解决方案2】:

我假设您真的不想要或没有空间在微控制器上安装完整的 ip (lwip) 堆栈?这听起来有点矫枉过正。为什么不直接滚动您自己的简单数据包结构来移动您需要移动的数据项。根据双方对 spi 的支持方式,您可能会或可能无法使用它来定义数据的帧,如果不是简单的开始模式、长度和尾随校验和,也许尾部模式就足以找到数据包边界流(与串行/uart 解决方案没有什么不同)。您甚至可以将 PPP 解决方案与开始模式一起使用,我认为每当开始模式恰好出现在数据中时,使用两字节模式的有效负载结束模式。我现在不记得所有细节了。

无论你的框架是什么,然后添加一个数据包类型和你的握手,或者如果数据只是被微控制器武装,那么你甚至不需要这样做。

回到您的直接问题。是的,我认为 ip 堆栈(lwip 或其他)会引入很多开销。带宽和更重要的是支持该堆栈所需的代码量都会消耗双方的 rom/ram。如果您最终需要以 ip 方式(由嵌入式系统托管的网站)呈现这些数据,那么在路径中的某个位置您需要一个 ip 堆栈等。

我无法想象 lwip 会为您管理您的队列。我想你需要自己做。各种队列可能希望与处理单个 spi 总线的单个驱动程序通信(假设有一个具有多个芯片选择的单个 spi 总线)。它还取决于您如何使用 spi 接口,如果您允许 arm 与多个微控制器通信,并且数据包从该控制器分解成一点点,从该控制器分解成一点点,这样就没有人需要等待早在他们获得更多字节的数据之前。或者一个完整的帧是否必须从一个微控制器移动,然后才能移动到下一个 gpio 中断以提取那些数据?总而言之,我假设您必须像在任何其他有多个共享资源用户(rtos、成熟的操作系统等)的情况下一样管理共享资源。我根本不记得lwip,但是使用完整的伯克利套接字应用程序接口,用户可以编写单独的应用程序,其中每个应用程序只关心一个TCP或UDP端口,并且库和驱动程序管理将这些数据包分离到每个应用程序以及IP 堆栈的所有规则。

如果您还没有进行通过 spi 接口移动数据的实验,我将首先从简单的实验开始,以了解它是否有效,您可以进行的传输大小每个 spi 转换等都可靠。您的解决方案自然可能会退出这些实验。

【讨论】:

  • 感谢您的详细回答,实际上第 2 点中提到的当前实施方案已经很好地解决了半双工和阻塞单个消息响应的缺点。这就是为什么我正在寻找通常在 SPI 上使用的标准堆栈,甚至以标准方式实现它,而不是重新设计可能引入的缺陷。
猜你喜欢
  • 1970-01-01
  • 2020-08-25
  • 2020-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多