ESP32-S3 USB Serial JTAG on External PHY?

seancross
Posts: 10
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: 10
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: 10
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: 10
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: 10
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: 51
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?

Who is online

Users browsing this forum: No registered users and 29 guests