嵌入式IP堆栈:可以/接受异步发送吗?
我正在尝试为 8 位 AVR MCU 实现一个非常小的 IP 堆栈。我不希望它支持 TCP,因为它真的太大了,我不需要它,而是 UDP(当然还有 ARP 和 ICMP)。
我希望堆栈代码适合 16 kiB ROM 和 1 kiB RAM,当然为应用程序留出尽可能多的空间。我使用基于 ENC28J60 的板进行 PHY/MAC 管理,该板具有内部 8 kiB RX/TX 循环缓冲区。当数据包到达该芯片时,它会将它们一个接一个地写入 RX 缓冲区,但不会覆盖最旧的数据包。最旧的数据包由一个指针指向,当用户读取完该数据包时,必须更新该指针以指向下一个数据包。当新数据包到达时,它还会在其引脚之一上发送中断。
对于 RX 部分,我希望像 lwIP 一样工作:当我们收到中断(保存其地址和大小)时发出新数据包已准备就绪的信号,但仅在用户调用我们的 IP 时才继续处理堆栈函数。这应该可以正常工作;如果用户没有足够频繁地调用我们的函数,新到达的数据包将被丢弃,仅此而已。用户向堆栈提供 UDP 回调。
现在,问题是关于 TX 的。假设我想将 UDP 数据包发送到某个我不知道链接地址的 IP。发送数据包之前必须先发送 ARP 请求。如果 UDP 数据包在 ARP 回复之前到达怎么办?它必须由我的 UDP 回调处理,但是如果我想从此回调发送一些内容怎么办?我还在这儿等待 ARP 回复。可以肯定的是,这种阻塞机制是不对的。
我的问题是:可以/接受异步发送吗?因此,如果我想发送某些内容,我会为发送函数提供回调,并在可以发送 UDP 数据包时调用它。这样,一切都是事件驱动的。
I am trying to implement a very small IP stack for 8-bit AVR MCUs. I don't want it to support TCP, because it's really too big and I don't need it, but rather UDP (and, of course, ARP and ICMP).
I want the stack code to fit into 16 kiB of ROM and 1 kiB of RAM, of course letting as much space as possible for the application. I am using an ENC28J60-based board for PHY/MAC management, which has an internal 8 kiB RX/TX circular buffer. As packets arrive into this chip, it writes them one after the other into the RX buffer but won't overwrite the oldest one. The oldest one is pointed to by a pointer which must be updated to point to the next packet when the user is done reading it. It also sends an interrupt on one of its pins when a new packet has arrived.
For the RX part, I want to work just like lwIP does: signal that a new packet is ready when we receive an interrupt (save its address and size) but proceed it only when the user calls our IP stack function. This should work okay; if the user does not call our function often enough, the new arriving packets will be dropped and that's it. The user provides the stack with an UDP callback.
Now, the problem is about TX. Let's say I want to send an UDP packet to some IP for which I don't know the link address. An ARP request has to be sent before my packet is sent. What if an UDP packet comes in before the ARP reply? It has to be processed by my UDP callback, but what if I want to send something from this callback? I'm still waiting for an ARP reply here. For sure this blocking mechanism is not right.
My question is: is it okay/accepted to have asynchronous sending? Thus if I want to send something, I provide the send function with a callback and its get called when the UDP packet may be sent. This way, everything is event-driven.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
至于异步发送是否“可接受”,我无法想象为什么它会成为问题,只要您可以在代码大小要求中实现即可。
至于实现这种方案的最佳方法,我不知道你想要支持多大的数据包大小(我猜比理论最大值64K小很多),但我会分配一环发送缓冲区,并且每当负责实际发送到硬件的进程运行其循环/中断/无论什么时候,它都会检查每个活动缓冲区的 ARP 状态(有 ARP 条目、未完成的 ARP 请求、超时的 ARP 请求、没有 ARP 条目或未完成的请求) ) 和采取适当的操作(分别:使用适当的 MAC 推送到硬件、跳过本次、丢弃、发送 ARP 请求)。您可以在每次更新 ARP 表时触发此发送例程运行,以便满足任何必要的实时要求(尽管有些人会认为以太网不是也永远不会是一个真正具有实时能力的系统,但这就是另一个不介意激烈争论的论坛的主题)。
As to whether it's "acceptable" to have asynchronous sending, I can't imagine why it would be a problem, so long as you can implement that in your code size requirements.
As to the best way to implement such a scheme, I don't know how big a packet size you want to support (I'm guessing a lot less than the theoretical maximum of 64K), but I would allocate a ring of send buffers, and whenever the process responsible for actually sending to the hardware ran its loop/interrupt/whatever, it would check each live buffer for its ARP status (has ARP entry, ARP request outstanding, ARP request timed out, no ARP entry or request outstanding) and take the appropriate action (respectively: push to hardware with appropriate MAC, skip this time, discard, send ARP request). You could trigger this send routine to run every time the ARP table is updated so that you could meet any necessary real-time requirements (although some people would argue that Ethernet is not and will never be a truly real-time capable system, but that's a topic for another forum that doesn't mind flamewars).
你能有两个回调(基本上是异步路径),一个用于从 IP 层接收,一个用于发送到 IP 吗?
另外,如果您要实现层,我认为 IP 发送/路由功能应该处理该层的 ARP 回复。
Can you have two callbacks(basically async paths), one for receiving from IP layer and one for sending to IP?
Also, if you are implementing layers, I think the IP send / route function should take care of the ARP reply at that level.