ESP32-S3 USB Serial JTAG on External PHY?

seancross
Posts: 11
Joined: Sun Jun 19, 2022 3:59 pm

ESP32-S3 USB Serial JTAG on External PHY?

Postby seancross » Tue Nov 07, 2023 2:55 pm

Hi,

I'm designing a board that has USB, and I'd like to still be able to debug it. Accordingly, I've built a small test PCB that breaks out both the int and ext pins to a USB-C connector.

1. At boot, I get SERIAL_JTAG on INT USB
2. If I try the tinyusb console program, I get WARP on INT USB
3. If I call `usb_phy_ll_int_jtag_enable(&USB_SERIAL_JTAG);` then I get SERIAL_TAG back on INT USB even without deinitializing tinyusb
4. I get no useful output on EXT USB regardless of what I try.

When I say "no useful output" I mean I can see my host PC attempting to enumerate, but it gives up. I see traffic flowing -- both DP and DM -- but the ESP32-S3 does not do anything with the signals. The waveforms are well-shaped and do not appear to be suffering from any sort of contention. They are 3.3V, as is expected.

I would expect that I would see the MTDO/JTAG/GPIO40/OEN go high and some interesting data to appear on MTCK/JTAG/GPIO39/VPO and GPIO38/VMO, but those pins are absolutely still. It's as if they're not muxed for USB PHY support.

My PCB has D+ go to MTMS, and D- go to MTDI. Then pins MTCK and GPIO38 go through a small buffer (SN74AUP1G125DCKR) that outputs on negative edge.

Since I don't see GPIO38, MTCK, or MTDO toggling I can only assume that the block isn't receiving the signals.

Are there any examples of how to get the SERIAL_JTAG block working? Are there steps I need to take beyond simply calling `usb_phy_ll_ext_jtag_enable(&USB_SERIAL_JTAG)`? Do I need to adjust pin mux somewhere?

seancross
Posts: 11
Joined: Sun Jun 19, 2022 3:59 pm

Re: ESP32-S3 USB Serial JTAG on External PHY?

Postby seancross » Wed Nov 08, 2023 2:13 am

One thing I've noticed is that `gpio_sig_map.h` has mappings for the following:

Code: Select all

#define USB_EXTPHY_VP_IDX             55
#define USB_EXTPHY_OEN_IDX            55
#define USB_EXTPHY_VM_IDX             56
#define USB_EXTPHY_SPEED_IDX          56
#define USB_EXTPHY_RCV_IDX            57
#define USB_EXTPHY_VPO_IDX            57
However those signals are undocumented in the reference manual and are listed as `-`.

I've tried setting `.external_phy = true,` in the tusb configuration in the hopes that it would support an external PHY, but I still see absolutely no movement on the OEN or VPO/VMO signals where I'd expect to see OEN driven several cycles after the end of a USB frame.

seancross
Posts: 11
Joined: Sun Jun 19, 2022 3:59 pm

Re: ESP32-S3 USB Serial JTAG on External PHY?

Postby seancross » Wed Nov 08, 2023 2:44 am

One slightly concerning thing I'm starting to realize now that I have this board fabricated and I'm finding it doesn't work -- the `RCV` pin appears to be undocumented.

The reference manual on page 756 shows five pins are required: VP, VM, OEN, VPO, and VMO, but I see references in the code to a signal labeled "RCV". Furthermore, it appears to be on pin 21.

seancross
Posts: 11
Joined: Sun Jun 19, 2022 3:59 pm

Re: ESP32-S3 USB Serial JTAG on External PHY?

Postby seancross » Wed Nov 08, 2023 2:46 am

After shorting VP to GPIO21 I'm starting to get somewhere. So it definitely seems like it's missing something in the documentation. I'm going to rework a second board and see if I can get something updated.

Is the RCV signal documented anywhere, or will it be?

seancross
Posts: 11
Joined: Sun Jun 19, 2022 3:59 pm

Re: ESP32-S3 USB Serial JTAG on External PHY?

Postby seancross » Wed Nov 08, 2023 9:37 am

After further investigation, I've managed to come up with the following function -- posted here in the hopes that it will help someone else:

Code: Select all

#include "esp_private/usb_phy.h"
#include "hal/usb_phy_ll.h"
#include "soc/usb_pins.h"
#include "driver/gpio.h"
#include "esp_check.h"

static esp_err_t configure_usb_jtag(void)
{
    static usb_phy_handle_t usb_jtag_phy_hdl;
    // Drive 0 out D+ in order to override the 1.5k pullup
    // and force a reset, since we're changing which PHY
    // is driving the bus and the host may not realize that
    // the part needs re-enumeration.
    {
        // zero-initialize the config structure.
        const gpio_config_t io_conf = {
            .intr_type = GPIO_INTR_DISABLE,
            .mode = GPIO_MODE_OUTPUT,
            .pin_bit_mask = ((1ULL << USBPHY_OEN_NUM) | (1ULL << USBPHY_VPO_NUM)),
            .pull_down_en = 0,
            .pull_up_en = 0,
        };
        // configure GPIO with the given settings
        gpio_config(&io_conf);
        // Drive the VPO line low, which will coutneract the 1.5k pullup
        // (which we cannot otherwise disable).
        gpio_set_level(USBPHY_VPO_NUM, 0);
        // Enable the buffers to drive the value out to override the 1.5k pullup
        gpio_set_level(USBPHY_OEN_NUM, 0);

        // USB resets require 5ms minimum
        vTaskDelay(pdMS_TO_TICKS(10));

        // External PHY IOs config
        const usb_phy_ext_io_conf_t ext_io_conf = {
            .vp_io_num = USBPHY_VP_NUM,
            .vm_io_num = USBPHY_VM_NUM,
            .rcv_io_num = USBPHY_RCV_NUM,
            .oen_io_num = USBPHY_OEN_NUM,
            .vpo_io_num = USBPHY_VPO_NUM,
            .vmo_io_num = USBPHY_VMO_NUM,
        };

        const usb_phy_config_t usb_jtag_phy_conf = {
            .controller = USB_PHY_CTRL_SERIAL_JTAG,
            .otg_mode = USB_PHY_MODE_DEFAULT,
            .otg_speed = USB_PHY_SPEED_UNDEFINED,
            .target = USB_PHY_TARGET_EXT,
            .ext_io_conf = &ext_io_conf,
        };

        ESP_RETURN_ON_ERROR(usb_new_phy(&usb_jtag_phy_conf, &usb_jtag_phy_hdl), "usbphy-jtag", "Install USB JTAG PHY failed");
    }
    usb_phy_ll_ext_jtag_enable(&USB_SERIAL_JTAG);
    return ESP_OK;
}
If you call it, the USB Serial JTAG device will appear on the second PHY. It will also drive D+ LOW, overriding the pullup that may or may not be permanently installed and causing re-enumeration.

Note that `esptool.py` doesn't yet like this solution, mostly because resetting the device doesn't reset the port so the host just sees a series of NAKs from the device. I'll have to investigate efuses now to see how to work around that.

I'm concerned about needing to include `esp_private/usb_phy.h` but I can't see any other way to call `usb_new_phy()`.

martins
Posts: 55
Joined: Tue Aug 24, 2021 8:58 am

Re: ESP32-S3 USB Serial JTAG on External PHY?

Postby martins » Wed Nov 08, 2023 10:59 am

Thanks for sharing the solution, I had no Idea this was possible.

Although I suppose the easier would be to disable USB-Serail-JTAG peripheral alltogether and use JTAG pins directly with external USB-JTAG adapter (like ESP-PROG for example), just like you would with ESP32's with no USB peripheral. The app itself would work with USB-OTG peripheral only. At least I suppose this should work?

MehranVZ
Posts: 1
Joined: Thu Feb 06, 2025 11:16 am

Re: ESP32-S3 USB Serial JTAG on External PHY?

Postby MehranVZ » Thu Feb 06, 2025 11:18 am

What is the part number of the USB PHY that you used? And i'll be thankful if you recommend me any other USB PHY that you know of which works with ESP32-S3

seancross
Posts: 11
Joined: Sun Jun 19, 2022 3:59 pm

Re: ESP32-S3 USB Serial JTAG on External PHY?

Postby seancross » Fri Feb 07, 2025 5:15 am

I just used a pair of buffers, but you might be able to do it with just a resistor. The part number is SN74AUP1G125DCKR. I also put down way too many resistors in case things went wrong. It seems to work well!
Attachments
ESP32S3-external-phy.png
ESP32S3-external-phy.png (33.03 KiB) Viewed 2611 times

ESP_Sprite
Posts: 9986
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32-S3 USB Serial JTAG on External PHY?

Postby ESP_Sprite » Sat Feb 08, 2025 6:16 am

FWIW the part we used at Espressif to test this while it was in development is the SP5301. Not sure if that's still in production, though, although it's not hard to still get.

Who is online

Users browsing this forum: No registered users and 88 guests