我正试图通过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作为其起始软件包中的以太网SW的一部分,我认为这至少可以在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?
答案 0 :(得分:3)
我想也许你期待太多卑微的SPI。
SPI链路在每个节点中只是一对移位寄存器。主器件选择单个节点连接到其SPI移位寄存器。随着数据的移位,从机同时将数据移出。除非主机明确地将数据计时,否则不会交换数据。 SPI上的高效协议涉及从机在主机输入时输出有用的东西。这可能很难安排,因此您通常需要一种指示空数据的方法。
PPP在两个任意端点之间建立连接时很有用,当端点是固定的并且已知先验时,PPP除了不必要地使事情复杂化之外没有任何其他用途。
SPI不是一个非常复杂或灵活的接口,可能不适合重量级通用协议,如TCP / IP。由于SPI上的“寻址”是通过物理芯片选择来执行的,因此这些协议中固有的寻址毫无意义。
流量控制也是SPI的问题。在推送更多数据之前,主机无法确定从机是否已将数据从SPI复制到移位寄存器。如果你的从SPI支持DMA,你最好使用它。
无论哪种方式,我建议您根据自己的目的开发一些特定的东西。由于SPI不是这样的网络,因此您只需要一种方法来处理所选节点上的线程。这可以像STX<thread ID><length><payload>ETX
一样简单。
于2013年9月27日添加以回应评论 通常,SPI顾名思义用于连接外围设备,在该上下文中,协议由外设定义。例如,EEPROMS通常在供应商之间使用公共或至少兼容的命令接口,并且SD / MMC卡SPI接口使用标准化的命令测试和协议。
在两个微控制器之间,我认为大多数实现都是专有的和特定于应用程序的。开放协议是为通用互操作性而设计的,并且实现这可能会给封闭系统带来显着的不必要开销,除非节点运行的系统已经内置了网络堆栈。
我建议如果你确实想要使用通用网络堆栈,你应该在每一端用设备驱动程序抽象SPI,为SPI提供一个标准的I / O流接口(open(),close(),read (),write()等),然后你可以使用更高级别的PPP和TCP / IP协议(虽然可以避免PPP,因为连接是永久性的)。然而,如果两个节点都已经支持这些协议(例如运行Linux),那么这将是有吸引力的,否则它将是重要的努力和代码,几乎没有任何好处,并且肯定不会“高效”。
答案 1 :(得分:1)
我假设你真的不想要或有空间在微控制器上使用完整的ip(lwip)堆栈?这听起来有点矫枉过正。为什么不只是滚动自己的简单数据包结构来移动需要移动的数据项。根据双方支持spi的方式,您可能会或可能无法使用它来定义数据的帧,如果不是简单的起始模式,长度和尾随校验和以及尾部模式就足以找到数据包边界流(与串行/ uart解决方案没有区别)。你甚至可以使用带有启动模式的PPP解决方案,并且每当启动模式恰好出现在数据中时,我认为有效负载的结束模式使用双字节模式。我现在不记得所有细节了。
无论你的帧是什么,然后添加一个数据包类型和你的握手,或者如果数据只是微控制器,那么你甚至不需要这样做。
回到您的直接问题。是的,我认为ip栈(lwip或其他)会引入很多开销。带宽和更重要的是,支持该堆栈所需的代码量将在两侧咀嚼rom / ram。如果您最终需要以ip方式(由嵌入式系统托管的网站)呈现此数据,那么在路径中的某个位置需要ip堆栈等。
我无法想象lwip会为你管理你的队列。我想你需要自己做。各种队列可能想要与处理单个spi总线的单个驱动程序进行通信(假设有一个spi总线有多个芯片选择)。它还取决于你如何使用spi接口,如果你允许arm与多个微控制器通信,并且数据包从该控制器稍微分解一点,那么没有人必须等到早在他们获得更多字节的数据之前。或者一个完整的帧必须从一个微控制器移动到移动到下一个gpio中断之前拉动那些人数据?它的长短是因为我认为你必须管理共享资源,就像你拥有共享资源的多个用户(rtos,完整的操作系统等)的任何其他情况一样。我不记得lwip那么好,但是使用完整的berkeley套接字应用程序界面,用户可以编写单独的应用程序,其中每个应用程序只关心一个TCP或UDP端口,并且库和驱动程序管理将这些数据包分离到每个应用程序以及IP堆栈的所有规则。
如果您还没有通过spi接口进行数据移植的实验,我首先要从简单的实验开始,只是为了了解它有多好或无法工作,你可以做的传输大小可靠的每次spi转换等。你的解决方案可能自然地脱离了那些实验。