Teensy 4.1 USB Host D- and D+

kasazin

Member
I'm currently working with a Teensy 4.1 and I'm running into an issue where USB communication doesn't seem to work properly — the board is not detecting my USB mouse at all.

I soldered pin headers to the USB Host (5-pin) pads on the Teensy 4.1. However, I’m concerned that the D- and D+ data lines might not be connected or functioning correctly.

To verify this, I tried checking continuity between the MicroUSB connector’s D-/D+ lines and the USB Host port’s D-/D+ pads. Should there normally be continuity (a beep) between these points? On my Teensy, I don’t get any continuity.

The 5V line on the USB Host port is present and confirmed, so power seems fine.

Is there any proper or recommended way to verify whether the D- and D+ lines of the USB Host interface are working? Or is there a method to diagnose whether the USB Host circuitry on the Teensy 4.1 is functioning?

Any suggestions or troubleshooting advice would be greatly appreciated.
 

Attachments

  • IMG_20251120_204956~2.jpg
    IMG_20251120_204956~2.jpg
    197 KB · Views: 16
To verify this, I tried checking continuity between the MicroUSB connector’s D-/D+ lines and the USB Host port’s D-/D+ pads. Should there normally be continuity (a beep) between these points?
No, because they are completely separate ports.
 
No, because they are completely separate ports.
Thank you for your reply.
So if they are completely separate ports, then it makes sense that there is no continuity between them.

In that case, what is the correct way to check whether the D- and D+ lines on the USB Host port are working properly?
Any guidance would be greatly appreciated. Please help me figure this out.
 
Maybe start by showing what code you've tried to use with it?

Typically when the port is idle, both D- and D+ should have approximately 15K resistance to GND. The readings you actually get can vary quite a bit depending on your meter.
 
Yes, there a couple ways to test. The hardware gives you a way to read whether the pins are in J, K or SE0 state. When Teensy 4.1 is tested, the bed-of-nails test fixture drives D+ and D- pins and uses that capability to confirm the pins receive correctly. I can assure you every Teensy 4.1 does get these data pins tested before it ships!

The hardware also has a special test mode which can drive the pins. Before today I never tried to use it. Turns out it's pretty simple. Here's a program which is similar to LED blink, but for the D+ and D- signals.

CAUTION: disconnect all USB hubs and devices before running this program!

Logic high should measure about 0.78 volts with a normal 10M impedance multimeter. This is high speed USB, so don't expect ordinary 3.3V signals. Please understand the USB 2.0 spec is about current delivered to a load impedance, so 0.78V isn't a rigid spec... it's just the number I saw when I ran this here on a Teensy 4.1.

Logic low should be close to zero. My multimeter reads 0.02 volts when both are low, and 0.006 volts when the other pin is high (0.78V).

Code:
// Test Teensy 4.1 USB Host D+ and D- data pins.
// CAUTION: disconnect all USB hubs and devices!!
//
// This test will drive the D+ and D- pins, similar to LED blink.
// Logic high should be approx 0.78 volts.
//
// https://forum.pjrc.com/threads/77474

#include <USBHost_t36.h>

USBHost myusb;

void setup() {
  Serial.begin(9600);
  Serial.println("Disconnect any USB hubs and devices!!");
  myusb.begin();

  // Turn off 5V power to USB host port.  The D- pin is next
  // to 5V power!  Reduces risk of accidentally shorting +5V
  // to the data pins while touching with multimeter leads.
  GPIO8_DR_CLEAR = 1 << 26;

  // EHCI 1.0 spec, 4.14 Port Test Modes, page 114
  USB2_USBCMD &= ~USB_USBCMD_ASE;   // disable async schedule
  USB2_USBCMD &= ~USB_USBCMD_PSE;   // disable periodic schedule
  USB2_PORTSC1 |= USB_PORTSC1_SUSP; // suspend port
  USB2_USBCMD &= ~USB_USBCMD_RS;    // clear run/stop bit
  delay(100);                       // wait for halted status
  Serial.println("Starting D+ & D- pins test");
}

void dplus_high() {
  Serial.println("D+ high ~780mV, D- low");
  USB2_PORTSC1 = (USB2_PORTSC1 & ~USB_PORTSC1_PTC(15)) | USB_PORTSC1_PTC(1);
}
void dminus_high() {
  Serial.println("D- high ~780mV, D+ low");
  USB2_PORTSC1 = (USB2_PORTSC1 & ~USB_PORTSC1_PTC(15)) | USB_PORTSC1_PTC(2);
}
void both_low() {
  Serial.println("D+ low, D- low");
  USB2_PORTSC1 = USB2_PORTSC1 & ~USB_PORTSC1_PTC(15);
}

void loop() {
  dplus_high();
  delay(6000);
  dminus_high();
  delay(6000);
  both_low();
  delay(6000);
}
 
Last edited:
Maybe start by showing what code you've tried to use with it?

Typically when the port is idle, both D- and D+ should have approximately 15K resistance to GND. The readings you actually get can vary quite a bit depending on your meter.
Thank you for the information.

I have been performing my tests using actual code on the Teensy, so I’ll share the sketch I used. If there is anything wrong with this approach, please let me know.

Here is the code I’ve been running to test the USB Host port:

I have been using this sketch to check whether the mouse is detected, but it never gets recognized.

If my testing method is incorrect, or if I should measure the D- / D+ lines differently, I would really appreciate your guidance.

Code:
#define USBHOST_PRINT_DEBUG
#define USBHDBGSerial Serial
#include <USBHost_t36.h>

// シンプルに必要なインスタンスだけ作る
USBHost myusb;
MouseController mouse1(myusb);

// VBUS enable pin for Teensy 4.1 (PTD6)
const int VBUS_EN_PIN = 33;

void setup() {
  Serial.begin(115200);
  unsigned long start = millis();
  while (!Serial && (millis() - start < 2000)) {}
  Serial.println("=== USBHost debug force start ===");

  // VBUS制御ピンを出力にして ON(必要なら OFF にして試す)
  pinMode(VBUS_EN_PIN, OUTPUT);
  digitalWrite(VBUS_EN_PIN, HIGH);
  Serial.println("VBUS_EN (pin33) set HIGH");

  // USBホスト初期化(デバッグ有効にしていると内部ログが Serial に出るはず)
  myusb.begin();
  Serial.println("myusb.begin() done");

  delay(500);
}

void loop() {
  myusb.Task(); // 必須:ライブラリのポーリング

  static unsigned long last = 0;
  if (millis() - last > 2000) {
    last = millis();
    // 常に状態を表示して、列挙が走っているか見る
    Serial.printf("Status: mouse available=%d\n", mouse1.available() ? 1 : 0);
  }

  // イベントベースで読み取る
  if (mouse1.available()) {
    uint8_t buttons = mouse1.getButtons();
    int x = mouse1.getMouseX();
    int y = mouse1.getMouseY();
    int wheel = mouse1.getWheel();
    int wheelH = mouse1.getWheelH();

    Serial.printf("[MOUSE] buttons=0x%02X X=%d Y=%d wheel=%d wheelH=%d\n",
                  buttons, x, y, wheel, wheelH);
    mouse1.mouseDataClear();
  }

  delay(5);
}
 
The hardware also has a special test mode which can drive the pins. Before today I never tried to use it. Turns out it's pretty simple. Here's a program which is similar to LED blink, but for the D+ and D- signals.

CAUTION: disconnect all USB hubs and devices before running this program!
Thank you very much for providing the code.
I really appreciate you taking the time to help me.

I’m currently away from home, but I will try the code as soon as I get back.
I’ll report the results afterward. Thanks again for your support!
 
Logic high should measure about 0.78 volts with a normal 10M impedance multimeter. This is high speed USB, so don't expect ordinary 3.3V signals. Please understand the USB 2.0 spec is about current delivered to a load impedance, so 0.78V isn't a rigid spec... it's just the number I saw when I ran this here on a Teensy 4.1.

Logic low should be close to zero. My multimeter reads 0.02 volts when both are low, and 0.006 volts when the other pin is high (0.78V).
I measured the D- and D+ lines using the code you provided. Here are the results:


Measurements between D- and GND:


  • D+ high, D- low: ~780 mV, 20.4 mV
  • D- high, D+ low: ~780 mV, 0.78 V
  • D+ low, D- low: 5.6 mV

Measurements between D+ and GND:


  • D+ high, D- low: ~780 mV, 0.795 V
  • D- high, D+ low: ~780 mV, 20.9 mV
  • D+ low, D- low: 5.6 mV

Based on these readings, is it correct to assume that the D- and D+ lines are working and recognized?
I’m relieved to see the voltages are present.
Thank you very much for your help—I really appreciate it!
 
Yes, seems very likely your hardware is working. Those measurements closely match the voltages I see here with a working Teensy 4.1.
 
Code:
  // VBUS制御ピンを出力にして ON(必要なら OFF にして試す)
  pinMode(VBUS_EN_PIN, OUTPUT);
  digitalWrite(VBUS_EN_PIN, HIGH);
  Serial.println("VBUS_EN (pin33) set HIGH");
What is the purpose of this code? Do you have something connected to pin 33?
 
Your program from msg #6 is missing USBHIDParser.

First I ran the example program by clicking in Arduino File > Examples > USBHost_t36 > Mouse with a Logitech B100 mouse connected to Teensy 4.1. The example Mouse program works fine.

Then I ran your program. It does not work. Then I coped 1 line with USBHIDParser from the Mouse example. Your program appears to work with this 1 line added. Here is the result I see in the Arduino Serial Monitor when I move the Logitech mouse after uploading the program.

Code:
=== USBHost debug force start ===
VBUS_EN (pin33) set HIGH
myusb.begin() done
Status: mouse available=0
Status: mouse available=0
[MOUSE] buttons=0x00 X=-1 Y=0 wheel=0 wheelH=0
[MOUSE] buttons=0x00 X=-1 Y=0 wheel=0 wheelH=0
[MOUSE] buttons=0x00 X=-3 Y=0 wheel=0 wheelH=0
[MOUSE] buttons=0x00 X=-2 Y=0 wheel=0 wheelH=0
[MOUSE] buttons=0x00 X=-3 Y=0 wheel=0 wheelH=0
[MOUSE] buttons=0x00 X=-2 Y=1 wheel=0 wheelH=0
[MOUSE] buttons=0x00 X=-2 Y=0 wheel=0 wheelH=0
[MOUSE] buttons=0x00 X=-2 Y=0 wheel=0 wheelH=0
[MOUSE] buttons=0x00 X=-4 Y=0 wheel=0 wheelH=0
[MOUSE] buttons=0x00 X=-4 Y=0 wheel=0 wheelH=0
[MOUSE] buttons=0x00 X=-3 Y=-1 wheel=0 wheelH=0
[MOUSE] buttons=0x00 X=-6 Y=-3 wheel=0 wheelH=0
[MOUSE] buttons=0x00 X=-6 Y=-3 wheel=0 wheelH=0
[MOUSE] buttons=0x00 X=-7 Y=-4 wheel=0 wheelH=0
[MOUSE] buttons=0x00 X=-3 Y=-2 wheel=0 wheelH=0
[MOUSE] buttons=0x00 X=-2 Y=-1 wheel=0 wheelH=0

I did not connect anything to pin 33. This test was just the Logitech B100 connected to a Teensy 4.1 by the USB Host Cable.

mousetest.jpg


This is a complete copy of the modified program:

Code:
#define USBHOST_PRINT_DEBUG
#define USBHDBGSerial Serial
#include <USBHost_t36.h>

// シンプルに必要なインスタンスだけ作る
USBHost myusb;
USBHIDParser hid2(myusb);
MouseController mouse1(myusb);

// VBUS enable pin for Teensy 4.1 (PTD6)
const int VBUS_EN_PIN = 33;

void setup() {
  Serial.begin(115200);
  unsigned long start = millis();
  while (!Serial && (millis() - start < 2000)) {}
  Serial.println("=== USBHost debug force start ===");

  // VBUS制御ピンを出力にして ON(必要なら OFF にして試す)
  pinMode(VBUS_EN_PIN, OUTPUT);
  digitalWrite(VBUS_EN_PIN, HIGH);
  Serial.println("VBUS_EN (pin33) set HIGH");

  // USBホスト初期化(デバッグ有効にしていると内部ログが Serial に出るはず)
  myusb.begin();
  Serial.println("myusb.begin() done");

  delay(500);
}

void loop() {
  myusb.Task(); // 必須:ライブラリのポーリング

  static unsigned long last = 0;
  if (millis() - last > 2000) {
    last = millis();
    // 常に状態を表示して、列挙が走っているか見る
    Serial.printf("Status: mouse available=%d\n", mouse1.available() ? 1 : 0);
  }

  // イベントベースで読み取る
  if (mouse1.available()) {
    uint8_t buttons = mouse1.getButtons();
    int x = mouse1.getMouseX();
    int y = mouse1.getMouseY();
    int wheel = mouse1.getWheel();
    int wheelH = mouse1.getWheelH();

    Serial.printf("[MOUSE] buttons=0x%02X X=%d Y=%d wheel=%d wheelH=%d\n",
                  buttons, x, y, wheel, wheelH);
    mouse1.mouseDataClear();
  }

  delay(5);
}
 
Back
Top