running NativeEthernet flat out....but why is delay needed?

Status
Not open for further replies.

bschena

Active member
So, I'm shoving packets between two identical T4.1s using UDP and the NativeEthernet library.

Here's the Loop code:

Code:
  Udp.beginPacket(destinationNodeIP, destinationPort); // aim the UDP packet to the destination IP:Port
  Udp.write(sendBuffer);  // send the buffer
  Udp.endPacket();        // terminate the packet
  Udp.flush();            // flush the send buffer, housekeeping

  delayMicroseconds(SEND_DELAY_uS); // microsecond delay. still trying to determine if this is necessary

I've found that nothing works without the delayMicroseconds(SEND_DELAY_uS) line.

Further, I've found that I need to set the delay to something above 100uS. It seems to be more reliable at 200uS, and doesn't work at all at 50, 10, or 0. 100uS occasionally works, but not reliably.

Anyone have any idea why this might be? setup and hold times with the Phy? something else?

Really curious to see if I can get this to run at top speed - faster is better for my application (haptics).

FWIW, I'm seeing about 9.5kHz packet (receive) rates from one T4.1 to another using UDP with the delay = 100uS - damn impressive, even as it is.

/b/
 
Honestly I’m not sure about why the delay is needed, also flush for UDP has never done anything. I’m curious if it’s actually not sending out the packet or if the receiving Teensy is just missing it, I’ll admit I’ve never done Teensy to Teensy tests myself. Last time I did any kind of speed tests I want to say it was getting somewhere in the range of 80-90 Mbps for TCP transfer depending on the buffer size.
 
I haven't tested teensy to teensy, but I have tested T4.1 to/from linux over 100mbs wired ethernet. The linux box sends 40 1000-byte UDP packets at 97mbs and T41 receives all 40 packets at 94 mbs (94.42 mbs 40 pkts 40000 bytes on port 54040 192.168.1.4). And the T4.1 can blast 1000-byte UDP packets to the linux box @98mbs and the linux box receives all 40 packets (recvd 40 pkts 12249.352703 pps 12249.352703 KBs 97994.821626 Kbs lth=1000)

Code:
void udp_send(int reps, int nbytes) {
  uint32_t  i, t1, t2;
  float mbs;

  t1 = micros();
  for (i = 0; i < reps; i++) {
    Udp.beginPacket(MyServer, 2000);   // to udpsink
    Udp.write(packetBuffer, nbytes);
    Udp.endPacket();
  }
  t2 = micros() - t1;
  mbs = (8.*nbytes * reps) / t2;
  Serial.printf("UDP blast %d reps %d bytes %d us %f mbs\n", reps, nbytes, t2, mbs);
}

void udp_recv() {
  uint32_t i, t1, t2, pkts, bytes, ipaddr;
  char buff[128];
  double mbs;

  Serial.print(Ethernet.localIP());
  while (1) {
    sprintf(buff, " port %d, hit key to stop", localPort);
    Serial.println(buff);
    pkts = bytes = 0;
    while (!Serial.available()) {
      int n = Udp.parsePacket();
      if (n) {
        if (!bytes) t1 = micros();
        t2 = micros();
        bytes += Udp.read(packetBuffer, 1000);
        pkts++;
      }
    }
    t1 = t2 - t1;
    mbs = (8.*bytes) / t1;
    Serial.print(mbs);
    sprintf(buff, " mbs %d pkts %d bytes on port %d ", pkts, bytes, Udp.remotePort());
    Serial.print(buff);
    IPAddress remote = Udp.remoteIP();
    Serial.println(remote);
    while (Serial.available()) Serial.read(); // consume
  }
}
 
Honestly I’m not sure about why the delay is needed, also flush for UDP has never done anything. I’m curious if it’s actually not sending out the packet or if the receiving Teensy is just missing it, I’ll admit I’ve never done Teensy to Teensy tests myself. Last time I did any kind of speed tests I want to say it was getting somewhere in the range of 80-90 Mbps for TCP transfer depending on the buffer size.

Good question - not sure what's happening at the wire level. All I know is that if I don't add the delay, nothing arrives on the receive end. Seems like I'll need to get Wireshark running to find out.

In my application, the packets can be small (servo commands, mainly) but I need to maximize updates-per-second/minimize latency in order to get good performance. So this is a case where Mb/s or MB/s isn't the main concern. This is also the reason I'm using UDP - late-data is same as no-data.

I see that the default packet size is 24Bytes. Can I arbitrarily increase this to say 50 or 100Bytes without hosing anything? From your comments, it sounds like you can bump the packet size up almost arbitrarily. I'm just using NativeEthernet as configured "out of the box" at the moment.

Oh, and thanks for mentioning Udp.Flush....I wasn't sure if that was useful or not, but it seemed worth a try. Anyone know why flushing UDP isn't required, or isn't useful? Is that something that just happens automatically anyway?

thx!
 
I haven't tested teensy to teensy, but I have tested T4.1 to/from linux over 100mbs wired ethernet. The linux box sends 40 1000-byte UDP packets at 97mbs and T41 receives all 40 packets at 94 mbs (94.42 mbs 40 pkts 40000 bytes on port 54040 192.168.1.4). And the T4.1 can blast 1000-byte UDP packets to the linux box @98mbs and the linux box receives all 40 packets (recvd 40 pkts 12249.352703 pps 12249.352703 KBs 97994.821626 Kbs lth=1000)

Code:
void udp_send(int reps, int nbytes) {
  uint32_t  i, t1, t2;
  float mbs;

  t1 = micros();
  for (i = 0; i < reps; i++) {
    Udp.beginPacket(MyServer, 2000);   // to udpsink
    Udp.write(packetBuffer, nbytes);
    Udp.endPacket();
  }
  t2 = micros() - t1;
  mbs = (8.*nbytes * reps) / t2;
  Serial.printf("UDP blast %d reps %d bytes %d us %f mbs\n", reps, nbytes, t2, mbs);
}

void udp_recv() {
  uint32_t i, t1, t2, pkts, bytes, ipaddr;
  char buff[128];
  double mbs;

  Serial.print(Ethernet.localIP());
  while (1) {
    sprintf(buff, " port %d, hit key to stop", localPort);
    Serial.println(buff);
    pkts = bytes = 0;
    while (!Serial.available()) {
      int n = Udp.parsePacket();
      if (n) {
        if (!bytes) t1 = micros();
        t2 = micros();
        bytes += Udp.read(packetBuffer, 1000);
        pkts++;
      }
    }
    t1 = t2 - t1;
    mbs = (8.*bytes) / t1;
    Serial.print(mbs);
    sprintf(buff, " mbs %d pkts %d bytes on port %d ", pkts, bytes, Udp.remotePort());
    Serial.print(buff);
    IPAddress remote = Udp.remoteIP();
    Serial.println(remote);
    while (Serial.available()) Serial.read(); // consume
  }
}

This is helpful - curious to see how other people have solved a similar problem.
 
Status
Not open for further replies.
Back
Top