Custom Teensy 4.1 Ethernet DHCP Troubleshooting

After getting help with Serial communication issues from this great forum I finally got my Custom Teensy 4.1 board working! I'm able to Program it finally and was eager to test my Ethernet connectivity with the DP83825L Ethernet PHY IC (U5 on my layout) and the J1B1211CCD RJ45 Connecter (P1 on my layout), however it doesn't want to cooperate.

While i can get a perceived link as proven by code tests and the activity LED blinking, the board isn't visible in the devices list in my gateway, nor can i ping it from my PC. i have tried both static and dynamic IP address assignment but neither have worked. I intend to use it to host a webserver for remote control of the GPIOs for reference. the following below is the debugging i've done over the past week to root out the problem source:

Hardware debugging:
  • Checked multiple times the TX and RX differential pairs are appropriately designed with 100 ohm impedance as per the DP83825l datasheet and aren’t too close to noisy traces to create interference.
  • Confirmed with DP83825l data sheet and TI PHY design guidelines to confirm the trace layout between the MCU and PHY is correctly done
  • Confirmed the PCB footprint for the jack is proper, I’m using the J1B1211CCD connector and the the 0.1uF capacitor per the ethernet kit from teensy.
  • When plugged into the switch which is connected to the gateway, the activity LED on the switch port flickered to the tune of the RJ45 jacks LED, signifying that the teensy LED wasn’t a facade. This also indicated that there is some level of traffic between the PHY IC and the Ethernet switch. However The '1000mbps Active' LED on the Ethernet switch wasn't On.
  • I attempted to probe the RJ45 transmit pins with my oscilloscope, although I struggled to get a good connection between the RJ45 pins and the probe, However I was able to individually test the TX+ and TX- pins with a passive probe individually and saw common mode noise ranging from ~12-18mHz with a Peak to Peak Voltage of ~1.6V (for both and the RX pins as well). from my research I've seen that a differential probe is required to actually examine signal integrity. However what I've seen on the pins is apparently expected when using a passive probe on Ethernet as its roughly half the differential pair. This test at least verifies signals are being transmitted roughly to the correct tune, but i cant rule out signal integrity issues just yet.

Software debugging:
  • Tested ethernet connection with QNEthernet library, can get a LINK status when CAT6 cable is inserted but can’t communicate with DHCP. Cannot be seen on gateway or be pinged.
  • The MAC address is retrievable from bootloader and is known
  • Created a test program to send the same test packet every second, and the activity LED flickers consistently when sending the packet and is a solid green when not sending.
  • When using Wireshark I can’t find any evidence of Activity when filtering for the MAC address or UDP port assigned in the code (I used 9999 for testing)
  • Tried both static IP assignment and dynamic to no success, ensuring my gateway and subnet mask are correctly set



Considering the router switch detects activity but the DHCP doesn't and probing has mostly ruled out physical issues, i believe my problems lie with the software potentially, however i don't want to rule out signal integrity as the problem as being custom designed its very likely. below is the screenshot of my board layout and my github is linked here. below is also different sketches i've used for testing for reference as well if anyone is able to point me in the right direction. I have also provided the PHY IC datasheet and the TI design check list that i followed when designing my traces incase that's the issue. I only use this forum as a last resort (as to not clog up the forum) but after a week of various tests, research and troubleshooting, I am running out of potential leads to investigate and I would appreciate any possible help greatly.

Thanks,
Alex

DP83825L datasheet
Texas Instruments PHY Design checklist

1747366699195.png


Link Test Code

C:
// SPDX-FileCopyrightText: (c) 2023 Shawn Silverman <shawn@pobox.com>
// SPDX-License-Identifier: AGPL-3.0-or-later

// LinkWatcher is a simple application that watches the link state
// using a listener. It doesn't try to set an address.
//
// This file is part of the QNEthernet library.

#include <QNEthernet.h>

using namespace qindesign::network;

// Program setup.
void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 4000) {
    // Wait for Serial
  }
  printf("Starting...\r\n");

  // Listen for link changes
  Ethernet.onLinkState([](bool state) {
    if (state) {
      printf("[Ethernet] Link ON");

      // We can use driver capabilities to determine what to print
      const auto &dc = Ethernet.driverCapabilities();
      if (dc.isLinkSpeedDetectable) {
        printf(", %d Mbps", Ethernet.linkSpeed());
      }
      if (dc.isLinkFullDuplexDetectable) {
        printf(", %s duplex", Ethernet.linkIsFullDuplex() ? "full" : "half");
      }
      if (dc.isLinkCrossoverDetectable) {
        printf(", %s crossover", Ethernet.linkIsCrossover() ? "is" : "not");
      }

      printf("\r\n");
    } else {
      printf("[Ethernet] Link OFF\r\n");
    }
  });

  // We just want to watch the link in this example, so don't start DHCP
  Ethernet.setDHCPEnabled(false);
  if (!Ethernet.begin()) {
    printf("ERROR: Failed to start Ethernet\r\n");
  }
}

// Program loop.
void loop() {
}


Wire Shark Test Code:

Code:
#include <QNEthernet.h>
#include <EthernetUdp.h>

using namespace qindesign::network;

////// CONFIGURATION //////

// Pick a static IP that’s valid on your LAN
IPAddress localIp(192, 168, 0, 123);
IPAddress subnetMask(255, 255, 255, 0);
IPAddress gateway(192, 168, 0, 1);


uint8_t mac[6] = { 0x04, 0xE9, 0xE5, 0x1A, 0x56, 0x64 };

// UDP settings
EthernetUDP udp;
const uint16_t UDP_PORT = 9999;
const char* PAYLOAD = "Test packet from Teensy";

void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 2000);


  if (!Ethernet.begin(mac, localIp, subnetMask, gateway)) {
    Serial.println("Ethernet.begin() failed");
    while (1);
  }


  Serial.print("IP Address: ");
  Serial.println(Ethernet.localIP());
  Serial.printf("Link is %s, speed = %uMbps, %s duplex\n",
    Ethernet.linkState() ? "UP" : "DOWN",
    Ethernet.linkSpeed(),
    Ethernet.linkIsFullDuplex() ? "full" : "half"
  );

  udp.begin(UDP_PORT);
}

void loop() {
  // send one broadcast packet per second
  udp.beginPacket(IPAddress(255, 255, 255, 255), UDP_PORT);
  udp.write((const uint8_t*)PAYLOAD, strlen(PAYLOAD));
  udp.endPacket();
  Serial.println("Packet sent");
  delay(1000);
}



Webserver Test Code (from: https://protosupplies.com/learn/prototyping-system-for-teensy-4-1-working-with-ethernet-2/)
Code:
/*
  Teensy 4.1 WebServer Example

  This program reads 6 analog inputs on the Teensy 4.1 and sends the results to
  a webpage in a web browser

  Modify the IPAddress ip, sn and gw to match your own local network
  before downloading the program.
 
  Based on the WebServer example program
  This example uses the QNEthernet.h library
*/

#include <QNEthernet.h>

using namespace qindesign::network;

// The IP address info will be dependent on your local network
// First 3 numbers must match router, last must be unique
//
IPAddress ip{10, 0, 0, 12};   // Unique IP
IPAddress sn{255,255,255,0};  // Subnet Mask
IPAddress gw{10,0,0,1};       // Default Gateway
// Initialize the Ethernet server library with the IP address and port
// to use.  (port 80 is default for HTTP):
EthernetServer server(80);
//===============================================================================
//  Initialization
//===============================================================================
void setup() {
  Serial.begin(115200);
 // Initialize the library with a static IP so we can point a webpage to it
  if (!Ethernet.begin(ip,sn,gw)) {
    Serial.println("Failed to start Ethernet\n");
    return;
  }

  // Just for fun we are going to fetch the MAC address out of the Teensy
  // and display it
  uint8_t mac[6];
  Ethernet.macAddress(mac);  // Retrieve the MAC address and print it out
  Serial.printf("MAC = %02x:%02x:%02x:%02x:%02x:%02x\n",
         mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
 
  // Show whether a cable is plugged in or not.
  Ethernet.onLinkState([](bool state) {
    Serial.printf("[Ethernet] Link %s\n", state ? "ON" : "OFF");
  });

  // start the webserver
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());

}
//===============================================================================
//  Main
//===============================================================================
void loop() {
 // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
          client.println("Refresh: 5");  // refresh the page automatically every 5 sec
          client.println();
          client.println("<!DOCTYPE HTML>");
         // Start HTML output to be displayed
          client.println("<html>");
          client.println("Teensy 4.1 WebServer<br />");
          // output the voltage value of each analog input pin
          for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
            int sensorReading = analogRead(analogChannel);
            // Convert reading to volts
            float volts = sensorReading * 3.3 / 1024.0;
            client.print("analog input ");
            client.print(analogChannel);
            client.print(" is ");
            client.print(volts);
            client.println("V<br />");
          }
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disconnected");
  }
}
 
Is there any specific tool that i could use to determine if packets are being sent? if i assemble a second board could i plug them into each other and read the received packets?
 
The Wireshark test code doesn’t look right.
1. Remove the EthernetUdp.h include.
2. Don’t use the MAC address form of begin(). Either remove the MAC address or change the argument order to: mac, ip, dns, gateway, subnet.
 
Last edited:
Back
Top