TEENSY 4.1 UDP issue

tomvp

New member
Hi,

I'm recently having an issue with my Teensy hanging in what appears to be the EthernetUDP constructor. I have simplified the code to the following which loads and runs fine as long as the declaration is left commented out. If I declare the Udp variable it hangs and doesn't connect COM3 or get to the point of starting Serial Monitor. I had been using a program successfully receiving UDP packets for several weeks and only ran into this issue this week when I wanted to make a couple changes.


#include <NativeEthernet.h>
#include <NativeEthernetUdp.h>

// MAC address and IP address for the Teensy board.
byte mac[] = { 0x04, 0xE9, 0xE5, 0x0D, 0x31, 0x2B };
bool useDHCP = false;
IPAddress ip(192, 168, 0, 5);
unsigned int localPort = 8888; // local port to listen on
// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

int led = 8;

// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
pinMode(13, OUTPUT);
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial)
{
; // wait for serial port to connect. Needed for native USB port only
delay(10);
}
Serial.println("Serial Connection complete");
}

void loop() {
digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(100); // wait for a second
digitalWrite(13, LOW); // turn the LED on (HIGH is the voltage level)
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(100); // wait for a second
Serial.println("Serial looping");
}


The compiler produces the following output:

Warning: Board teensy:avr:teensy32 doesn't define a 'build.board' preference. Auto-set to: AVR_TEENSY32
Memory Usage on Teensy 4.1:
FLASH: code:195788, data:72960, headers:8748 free for files:7848968
RAM1: variables:23840, code:61384, padding:4152 free for local variables:434912
RAM2: variables:12416 free for malloc/new:511872
No Teensy boards were found on any USB ports of your computer.
Please press the PROGRAM MODE BUTTON on your Teensy to upload your sketch.
RUN: "C:\Program Files (x86)\Arduino\hardware\teensy\..\tools\arm\bin\\arm-none-eabi-gdb" -ex "target extended-remote \\.\COM3" "C:\Users\vandertr\AppData\Local\Temp\arduino_build_473643\MyBlink.ino.elf"
Board at COM3 is not available



I have seen a reference to the QNEthernet library but haven't tried it. I'm looking to use a very simple library since all I'm doing is receiving packets being sent.

Thanks in Advance.
 
Here's some illustrative code that should work with QNEthernet. (Caveat: I'm not near a Teensy so haven't tested it.)

Code:
#include <QNEthernet.h>

using namespace qindesign::network;

constexpr uint16_t kUDPPort = 8888;  // Local port for listening

// IP configuration
const IPAddress staticIP(192, 168, 0, 5);
const IPAddress netmask(255, 255, 255, 0);
const IPAddress gatewayIP(192, 168, 0, 1);

EthernetUDP udp;
constexpr int kBufSize = Ethernet.mtu() - 20 - 8;  // 20-byte IP, 8-byte UDP header
uint8_t buf[kBufSize];

// Main program setup.
void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 4000) {
    // Wait for Serial to initialize
  }
  stdPrint = &Serial;  // Make printf work, a QNEthernet feature

  // Print the MAC address
  uint8_t mac[6];
  Ethernet.macAddress(mac);
  printf("MAC = %02x:%02x:%02x:%02x:%02x:%02x\n",
         mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

  // Start Ethernet
  printf("Starting Ethernet with static IP...\n");
  if (!Ethernet.begin(staticIP, netmask, gatewayIP)) {
    printf("Failed to start Ethernet!\n");
    return;
  }
  Ethernet.setDNSServerIP(gatewayIP);

  IPAddress ip = Ethernet.localIP();
  printf("    Local IP    = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
  ip = Ethernet.subnetMask();
  printf("    Subnet mask = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
  ip = Ethernet.gatewayIP();
  printf("    Gateway     = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
  ip = Ethernet.dnsServerIP();
  printf("    DNS         = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);

  // Start listening on the UDP port
  udp.begin(kUDPPort);
}

// Main program loop.
void loop() {
  int size = udp.parsePacket();
  if (size > 0) {
    // Print the packet contents
    printf("packet[%d]:", size);
    // Note: It's possible, due to IP reassembly, to receive a packet
    //       that's larger than the buffer size
    while (size > 0) {
      int read = udp.read(buf, std::min(size, kBufSize));
      for (int i = 0; i < read; i++) {
        printf(" %02x", buf[i]);
      }
      size -= read;
    }
    printf("\n");
  }
}
 
Thanks!

Thanks, I don't know if there is a library update issue or what.

I had working code that just stopped working when I tried making a simple change. I loaded the new code confident that I had the original sketch confirmed and the backup had already been tested a week or so before .

Testing QNEthernet is my next step when I can, I just wish I had an idea of why the NativeEthernet Library which had been working fine stopped working for me. I'm guessing at this point others aren't seeing the same issue.
 
Looking further at the code that you provided Is it necessary to setup a DNS gateway for QNEtherenet? All this node will ever do is listen for UDP packets sent to it.
 
It is not strictly necessary; it’s there, however, for completeness. Setting the DNS with the QNEthernet-style API matches the Arduino-style API that you were using before with NativeEthernet. With that API, not setting it actually sets a default, so I was giving it the same behaviour.
 
Here's a version that uses the `data()` function of the UDP socket. It obviates the need for reading into a buffer.

Other changes:
1. Using the gateway address as the DNS address in the Ethernet.begin() call,
2. Using CRLF line endings, and
3. Also watching for zero-length packets.

Code:
#include <QNEthernet.h>

using namespace qindesign::network;

constexpr uint16_t kUDPPort = 8888;  // Local port for listening

// IP configuration
const IPAddress staticIP(192, 168, 0, 5);
const IPAddress netmask(255, 255, 255, 0);
const IPAddress gatewayIP(192, 168, 0, 1);

EthernetUDP udp;

// Main program setup.
void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 4000) {
    // Wait for Serial to initialize
  }
  stdPrint = &Serial;  // Make printf work, a QNEthernet feature

  // Print the MAC address
  uint8_t mac[6];
  Ethernet.macAddress(mac);
  printf("MAC = %02x:%02x:%02x:%02x:%02x:%02x\r\n",
         mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

  // Start Ethernet
  printf("Starting Ethernet with static IP...\r\n");
  if (!Ethernet.begin(staticIP, netmask, gatewayIP, gatewayIP)) {
    printf("Failed to start Ethernet!\r\n");
    return;
  }

  IPAddress ip = Ethernet.localIP();
  printf("    Local IP    = %u.%u.%u.%u\r\n", ip[0], ip[1], ip[2], ip[3]);
  ip = Ethernet.subnetMask();
  printf("    Subnet mask = %u.%u.%u.%u\r\n", ip[0], ip[1], ip[2], ip[3]);
  ip = Ethernet.gatewayIP();
  printf("    Gateway     = %u.%u.%u.%u\r\n", ip[0], ip[1], ip[2], ip[3]);
  ip = Ethernet.dnsServerIP();
  printf("    DNS         = %u.%u.%u.%u\r\n", ip[0], ip[1], ip[2], ip[3]);

  // Start listening on the UDP port
  udp.begin(kUDPPort);
}

// Main program loop.
void loop() {
  int size = udp.parsePacket();
  if (size >= 0) {
    // Print the packet contents
    printf("packet[%d]:", size);
    // Note: It's possible, due to IP reassembly, to receive a packet
    //       that's larger than the buffer size
    const uint8_t *data = udp.data();
    for (int i = 0; i < size; i++) {
      printf(" %02x", data[i]);
    }
    printf("\r\n");
  }
}
 
Back
Top