USB Debug Guide for Zynq UltraScale+ and Versal Devices

USB Debug Guide for Zynq UltraScale+ and Versal Devices

This page demonstrate the overview of how to debug PS USB controller on Versal & ZynqMP platforms.

Table of Contents

Basic checks before debugging further

Observing the failure:

  • Host mode - Run the below command to check whether pendrive detected or not.

      lsusb

  • Device mode - Need to check this below node is created or not

   /sys/class/udc/*/uevent

Diagnosis:

Guidelines on debugging USB runtime failures

  • Check hardware design

  • USB driver logs

  • Dynamic debug

  • ftrace (function tracer)

  • USB register dump

  • USB protocol analyzer trace

USB Hardware Design

  • Review schematics

  • Review PCB layout - Refer to Xilinx pcb guidelines recommendations

USB driver logs

Kernel USB drivers print error messages when USB behaves abnormally:

  • Error messages

  •   Kernel crash dump

These messages might be the first hint of an issue, it can be cross checked.

Dynamic debug

Another useful debugging method is with dynamic debugging. By default driver stack has a lot of dynamic debug prints added . The prints are added using dev_dbg(). These prints are not enabled by default. They needs to be enabled using the below for dynamic debug

Dynamically enable/disable kernel debug code at runtime to obtain kernel debug log:

pr_debug()/dev_dbg0()

print_hex_dump_debug()/print_hex_dump_bytes()

Benefits:

  • Almost no overhead when log code is not enabled.

  • Turn on/off debug log at runtime.

  • No need to recompile the kernel.


Debugfs control example

mount -t debugfs none /sys/kernel/debug/ echo 8 > /proc/sys/kernel/printk echo -n 'file drivers/usb/dwc3/otg.c +p' > /sys/kernel/debug/dynamic_debug/control echo -n 'file drivers/usb/core/hub.c +p' > /sys/kernel/debug/dynamic_debug/control echo -n 'file drivers/usb/dwc3/core.c +p' > /sys/kernel/debug/dynamic_debug/control echo “file xxx.c +p” > /sys/kernel/debug/dynamic_debug/control echo “file dwc3.c line 1603 +p” > /sys/kernel/debug/dynamic_debug/control echo “file drivers/usb/core/* +p” > /sys/kernel/debug/dynamic_debug/control echo “file xxx.c -p” > /sys/kernel/debug/dynamic_debug/control

The below method can also be used for enabling dynamic debug for a range of files present in a folder

echo 8 > /proc/sys/kernel/printk echo -n "file drivers/usb/* +p" > /sys/kernel/debug/dynamic_debug/control

Ftrace

It is quite common for USB to enter into issues. The easiest way of debugging the host and Gadget mode drivers is using the trace. Using tracers we can capture the live debug data.

Below Kernel configurations need to be enabled for ftrace usage

CONFIG_FUNCTION_TRACER=y CONFIG_DYNAMIC_FTRACE=y CONFIG_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y

Ftrace usage:

Please run this below commands after booting the board

mount -t debugfs none /sys/kernel/debug/ cd /sys/kernel/debug/tracing/ echo 0 > tracing_on (keep trace from filling up until we set filter) echo function_graph > current_tracer echo dwc3* > set_ftrace_filter XPATH=/sys/kernel/tracing/events echo 1 > ${XPATH}/gadget/usb_ep_alloc_request/enable echo 1 > ${XPATH}/gadget/usb_ep_clear_halt/enable echo 1 > ${XPATH}/gadget/usb_ep_dequeue/enable echo 1 > ${XPATH}/gadget/usb_ep_disable/enable echo 1 > ${XPATH}/gadget/usb_ep_enable/enable echo 1 > ${XPATH}/gadget/usb_ep_fifo_flush/enable echo 1 > ${XPATH}/gadget/usb_ep_fifo_status/enable echo 1 > ${XPATH}/gadget/usb_ep_free_request/enable echo 1 > ${XPATH}/gadget/usb_ep_set_halt/enable echo 1 > ${XPATH}/gadget/usb_ep_set_maxpacket_limit/enable echo 1 > ${XPATH}/gadget/usb_ep_set_wedge/enable echo 1 > ${XPATH}/gadget/usb_gadget_giveback_request/enable echo 1 > ${XPATH}/gadget/usb_gadget_wakeup/enable echo 1 > ${XPATH}/dwc3/dwc3_ep_queue/enable echo 1 > ${XPATH}/dwc3/dwc3_ep_dequeue/enable echo 1 > ${XPATH}/dwc3/dwc3_gadget/enable echo 1 > ${XPATH}/dwc3/dwc3_gadget_giveback/enable echo 1 > ${XPATH}/dwc3/dwc3_prepare_trb/enable echo 1 > ${XPATH}/dwc3/dwc3_complete_trb/enable echo 1 > ${XPATH}/dwc3/dwc3_event/enable echo 1 > ${XPATH}/dwc3/dwc3_gadget_ep_cmd/enable echo 81920 > ${XPATH}/../buffer_size_kb echo 1 > tracing_on cat trace

HOST Mode:

echo 1 > /sys/kernel/debug/tracing/events/xhci-hcd/enable echo 1 > /sys/kernel/debug/tracing/events/xhci-hcd/xhci_address_ctx/enable echo 1 >  /sys/kernel/debug/tracing/events/xhci-hcd/xhci_cmd_completion/enable echo 1 > /sys/kernel/debug/tracing/events/xhci-hcd/xhci_dbg_address/enable echo 1 > /sys/kernel/debug/tracing/events/xhci-hcd/xhci_dbg_cancel_urb/enable echo 1 > /sys/kernel/debug/tracing/events/xhci-hcd/xhci_dbg_context_change/enable echo 1 > /sys/kernel/debug/tracing/events/xhci-hcd/xhci_dbg_init/enable echo 1 > /sys/kernel/debug/tracing/events/xhci-hcd/xhci_dbg_quirks/enable echo 1 > /sys/kernel/debug/tracing/events/xhci-hcd/xhci_dbg_reset_ep/enable echo 1 > /sys/kernel/debug/tracing/events/xhci-hcd/xhci_dbg_ring_expansion/enable echo 1 > /sys/kernel/debug/tracing/events/xhci-hcd/xhci_tx_completion/enable echo 1 > /sys/kernel/debug/tracing/events/xhci-hcd/xhci_queue_trb/enable echo 1 > /sys/kernel/debug/tracing/events/xhci-hcd/xhci_handle_event/enable


GADGET Mode:

echo 1 > /sys/kernel/debug/tracing/events/dwc3/dwc3_ep_queue/enable echo 1 > /sys/kernel/debug/tracing/events/dwc3/dwc3_ep_dequeue/enable echo 1 > /sys/kernel/debug/tracing/events/dwc3/dwc3_gadget/enable echo 1 > /sys/kernel/debug/tracing/events/dwc3/dwc3_gadget_giveback/enable echo 1 > /sys/kernel/debug/tracing/events/dwc3/dwc3_prepare_trb/enable echo 1 > /sys/kernel/debug/tracing/events/dwc3/dwc3_complete_trb/enable echo 1 > /sys/kernel/debug/tracing/events/dwc3/dwc3_event/enable echo 1 > /sys/kernel/debug/tracing/events/dwc3/dwc3_gadget_ep_cmd/enable

Capturing the Trace:

The enabled trace can be captured using the below command

cat /sys/kernel/debug/tracing/trace

Deleting the trace:

echo > /sys/kernel/debug/tracing/trace

Register dump

cat /sys/kernel/debug/fe200000.dwc3/regdump > regdump.txt

Guidelines to Debug USB PHY issues (ULPI PHY validation)

In ZynqMP/Versal platforms, GUSB2PHYACC_ULPI (0xfe20c280) is provided to send TX CMDs to the ULPI phy from Dwc3 controller. This below is the details of the register

EXAMPLE:

The below is the sequence to read the Vendor/Product ID from the attached ULPI phy.

Write 0xFE20C280 with the below information

  1. REGADDR = 0x00 (Vendor ID offset of the ULPI phy)

  2. REGWR = 0 (Since we are reading the vendor id)

  3. NEWREGREQ = 1 (Always 1 for read/write

 devmem 0xfe20c280 32 0x2000000

Now read the register and see the REGDATA field for the returned information. For SMSC3320 0x01000024 is returned. Decoding the returned value.

  • REGDATA = Returned information from ULPI phy (0x24)

  • VSTSDONE =1 (this should be set to 1 if properly read)


GUSB2PHYCFG (Global USB2 PHY Configuration Register)

This register is used for controlling the ULPI phy from DWC3 controller

Register Name(GUSB2PHYCFG )

Description

Register Name(GUSB2PHYCFG )

Description

GUSB2PHYCFG.PHYSOFTRST 

This bit is used to drive ULPI phy reset signal in Versal. For ZynqMp this is dummy.

GUSB2PHYCFG.ULPIEXTVBUSDRV

this bit is used to update ULPI OTG Control register[bit 6] bit. Some of the ULPI Phys like USB3340 requires this bit to be set for normal USB operation

GUSB2PHYCFG. ULPIAUTORES

This bit updates the ULPI InterfaceConrtol Register[bit 4]. This enables the ULPI phy to auto-resume when suspended.

GUSB2PHYCFG.XCVRDLY

This bit is used in both ZynqMp/Versal platforms to add delay between the assertion of the ULPI Transceiver Select signal (for HS) and the assertion of the TxValid signal during a HS Chirp. This delay is useful for some ULPI Phys like USB3340. The delay is inserted after selecting ULPI transceiver selection (like FS/HS) and requesting TXValid signal to the ULPI phy for starting a HS Chirp reset sequence.

GUSB2PHYCFG.SUSPENDUSB20 

This bit enables the USB2.0 PHY to enter Suspend mode if Suspend conditions are valid. This bit updates the ULPI phy Function Ctrl[bit 6].

Significance of usb2_phy_reset (Available only in Versal platforms)

usb3_phy_reset is a part of USB vendor registers available in versal platform.  This bit masks the ULPI phy reset signal coming out from DWC3 controller from reaching the ULPI phy. By default, this mask is set to "1" allowing the ULPI reset signal reaching the ULPI phy.

usb2_phy_reset → "1" . Allows the ULPI phy reset signal reaching the ULPI phy

usb2_phy_reset → "0". Masks the ULPI phy reset signal from reaching to the ULPI phy.

Common Issues with ULPI phy

It is quite common for many clients to modify the schematic based on the reference design provided by Xilinx. Most clients tend to use different ULPI Phys other than SMSC3320 (which is recommended by Xilinx) like USB3340/TIUSB1210.

Each ULPI phy has there own configuration requirements. Missing in these configuration steps may cause behaviour incorrect problems.

The below are the basic steps to identify any issue with ULPI phy

  1. Ensure that the ULPI phy RESETN pin got RESET toggle sequence before proceeding with the below steps

  2. In Host/Gadget mode, the very first step is to check if able to access ULPI registers. Please follow the steps mentioned in  "How ZynqMp/Versal Dwc3 controller controls the ULPI phy?" section above and see if able to read the ULPI phy registers.

  3. If not able to read the ULPI phy registers then there can be clocking issue.  ULPI phy requires 24MHZ crystal oscillator, check if the clock is proper. Also check if the clock out coming from ULPI phy is 60 MHZ.

  4. Some of the ULPI Phys has a configuration to operate in CLK OUT or CLK IN mode. Need to check datasheet and need to properly configure the phy to operate in CLK OUT mode

  5. Some Phys like TIUSB1210 may require ULPI regs OTG CTRL.DrvVbusExternal andOTG CTRL.DrvVbus to operate properly

  6. Check if CPEN ping is getting driven properly

  7. Some of ULPI PHY like USB 3340 may need some delay between dwc3 link selecting the ULPI PHY transceiver(to full/high speed) and dwc3 link issuing command to send HS CHIRP sequence (for Detection of HS device by host). This can be done by setting XCVRDLY.

Disabling Low Power Mode entries in USB 3.0 mode

By default USB 3.0 supports U1/U2 Low Power Mode. The device communicates to the host about the low power mode timeouts (U1timeout and U2timeout) values using the LPM transfers. Allowing LPM modes may be useful when power saving is needed but may be useless if performance is needed.

The LPM entries can be disabled by updating the below 

In Gadget mode

Disable the DCTL.INITU2ENA, DCTL.INITU1ENA,DCTL.ACCEPTU2ENA, DCTL.ACCEPTU2ENA

In Host Mode:
Update the PORTPMSC_30.U2_TIMEOUT andPORTPMSC_30.U1_TIMEOUT values to 0xF

USB Register Dumps for all the USB modes

For Host mode

Need to cross check the below details if the device not detected by host,

  1. Check USB ref clock = 250MHz

  2. Check GT lane config

  3. Probe ref clock = 26MHz

  4. Check vbus status

  5. Read GCTRL register for operation mode, got connect event , TD config, SOF is fine(not ok timer issue),
    read error register.

  6. Read the port states PORTSC_20(0xFE200420)

  7. Get the USB phy dump.

  8. USB phy details.

  9. USB hot-plug is working or not

  10. Get Serdes lane dump if USB-3.0 is used.

Host_mode_reg_dump

#!/bin/sh echo " USB0_BUS_REF_CTRL=0xFF5E0060= $(devmem 0xFF5E0060)" echo " DCTL =0xFE20C704 = $(devmem 0xFE20C704)" echo " DEVTEN =0xFE20C708 = $(devmem 0xFE20C708)" echo " DSTS =0xFE20C70C = $(devmem 0xFE20C70C)" echo " USBSTS =0xFE200024 = $(devmem 0xFE200024)" echo " LINK_ERROR_COUNT =0xFE200438= $(devmem 0xFE200438)" echo " USBSTS=0XFE200024= $(devmem 0XFE200024)" echo " USBCMD=0XFE200020= $(devmem 0XFE200020)" echo " PORTSC(PORTSC_20)=0XFE200420= $(devmem 0XFE200420)" echo " PORTSC(PORTSC_30)=0XFE200430= $(devmem 0XFE200430)" echo " PORTPMSC(PORTPMSC_20)=0XFE300424= $(devmem 0XFE300424)" echo " GCTL=0XFE30C110= $(devmem 0XFE30C110)" echo " GUSB2PHYCFG=0XFE20C200= $(devmem 0XFE20C200)" echo " GFLADJ=0XFE20C630= $(devmem 0XFE20C630)" echo " GUSB3PIPECTL(usb3_0_xhci)=0XFE20C2C0= $(devmem 0XFE20C2C0)" echo " GUSB3PIPECTL(usb3_1_xhci)=0XFE30C2C0= $(devmem 0XFE30C2C0)" echo " DSTS=0XFE20C70C= $(devmem 0XFE20C70C)"

Device_mode_reg_dump

#!/bin/sh echo " DSTS=0XFE20C70C= $(devmem 0XFE20C70C)" echo " DCTL=0XFE20C704= $(devmem 0XFE20C704)" echo " DCFG=0XFE20C700= $(devmem 0XFE20C700)" echo " GUSB2PHYCFG=0XFE20C200= $(devmem 0XFE20C200)"

Otg_mode_register_dump

#!/bin/sh echo " GCTL=0XFE20C110= $(devmem 0XFE20C110)" echo " GSTS=0XFE20C118= $(devmem 0XFE20C118)" echo " GOSTS=0XFE20CC10= $(devmem 0XFE20CC10)" echo " OCTL=0XFE20CC04= $(devmem 0XFE20CC04)" echo " OCFG=0XFE20CC00= $(devmem 0XFE20CC00)" echo "***********************OTG USB2.0*******************************" echo " USB2 PHYCFG Register =0xFE20C200=$(devmem 0xFE20C200)" echo " USB3 PIPECTL Register =0xFE20C2C0=$(devmem 0xFE20C2C0)" echo " fpd_pipe_clk Register =0xFF9D007C=$(devmem 0xFF9D007C)" echo " fpd_power_prsnt Register =0xFF9D0080=$(devmem 0xFF9D0080)" echo " LPD_SWITCH_CTRL Register =0xff5e00a8=$(devmem 0xff5e00a8)" echo " USB3_DUAL_REF_CTRL Register =0xff5e004c=$(devmem 0xff5e004c)" echo " GHWPARAMS6=0xFE20C158= $(devmem 0xFE20C158)" echo " OCFG=0xFE20CC00= $(devmem 0xFE20CC00)" echo " GSTS=0xFE20C118= $(devmem 0xFE20C118)" echo " USB3_0_XHCI_GDBGLTSSM =0xfe20c164=$(devmem 0xfe20c164)" echo " GTXFIFOSIZ0=0xFE20C300 $(devmem 0xFE20C300)" echo " GTXFIFOPRIDEV=0xFE20C610= $(devmem 0xFE20C610)" echo " GDMAHLRATIO=0xFE20C624= $(devmem 0xFE20C624)" echo " OSTS-OTG Status Register =0xFE20CC10=$(devmem 0xFE20CC10)" echo " OEVTEN-OTG Events Enable Register Setting =0xFE20CC0C=$(devmem 0xFE20CC0C)" echo " OEVT-OTG Events Register =0xFE20CC08=$(devmem 0xFE20CC08)" echo " OCTL-OTG Control Register =0xFE20CC04=$(devmem 0xFE20CC04)" echo "***********************OTG USB2.0 END*******************************" echo "***********************ZCU102 ULPI_PHY_RESETB*******************************" echo "*******Write – 0x202; Sleep(1s); Write – 0x2;Sleep(1s);Write – 0x202*********" echo " ZCU102 ULPI_PHY_RESETB - AND JTAG config mode =0xFF5E0250 =$(devmem 0xFF5E0250)" echo "***********************ZCU102 ULPI_PHY_RESETB END **************************"

Serdes Lane check registers

#!/bin/sh echo "/*********************LANE 0 START*******************************/" echo " L0_TM_EQ_ST0 $(devmem 0xFD401AD8)" echo " L0_TM_EQ_ST1 $(devmem 0xFD401ADC)" echo " L0_TM_EQ_ST2 $(devmem 0xFD401AE0)" echo " L0_PLL_STATUS_READ_0 $(devmem 0xFD4013E0)" echo " L0_PLL_STATUS_READ_1 $(devmem 0xFD4013E4)" echo " L0_TM_SAMP_STATUS0 $(devmem 0xFD401A80)" echo " L0_TM_SAMP_STATUS1 $(devmem 0xFD401A84)" echo " L0_TM_SAMP_STATUS2 $(devmem 0xFD401A88)" echo " L0_TM_SAMP_STATUS3 $(devmem 0xFD401A8C)" echo " L0_TM_ILL_STATUS0 $(devmem 0xFD401A98)" echo " L0_TM_ILL_STATUS1 $(devmem 0xFD401A9C)" echo " L3_CALIB_PIPE_NSW_CODE_STATUS $(devmem 0xFD40EF1C)" echo " L3_CALIB_RX_CODE_STATUS $(devmem 0xFD40EF28)" echo " L0_TM_MISC_ST_0 $(devmem 0xFD401AC8)" echo " L3_CALIB_ICAL_CODE_STATUS $(devmem 0xFD40EF24)" echo " L0_BG_POWER_GOOD_STATUS $(devmem 0xFD402B18)" echo " L0_SUPPLY_POWER_GOOD_STATUS $(devmem 0xFD402B1C)" echo " L3_CALIB_DONE_STATUS $(devmem 0xFD40EF14)" echo " L3_CALIB_PIPE_PSW_CODE_STATUS $(devmem 0xFD40EF18)" echo " L0_TXPMA_ST_0 $(devmem 0xFD400B00)" echo " L0_TXPMA_ST_1 $(devmem 0xFD400B04)" echo " L0_TXPMA_ST_2 $(devmem 0xFD400B08)" echo " L0_TXPMA_ST_3 $(devmem 0xFD400B0C)" echo " L0_TXPMA_ST_4 $(devmem 0xFD400B10)" echo " L0_TM_ILL9 $(devmem 0xFD401984)" echo " L0_TM_ILL13 $(devmem 0xFD401994)" echo "***********************END*******************************" echo "/*********************LANE 2 START*******************************/" echo " L2_TM_EQ_ST0 $(devmem 0xFD409AD8)" echo " L2_TM_EQ_ST1 $(devmem 0xFD409ADC)" echo " L2_TM_EQ_ST2 $(devmem 0xFD409AE0)" echo " L2_PLL_STATUS_READ_0 $(devmem 0xFD40A3E0)" echo " L2_PLL_STATUS_READ_1 $(devmem 0xFD40A3E4)" echo " L2_TM_SAMP_STATUS0 $(devmem 0xFD409A80)" echo " L2_TM_SAMP_STATUS1 $(devmem 0xFD409A84)" echo " L2_TM_SAMP_STATUS2 $(devmem 0xFD409A88)" echo " L2_TM_SAMP_STATUS3 $(devmem 0xFD409A8C)" echo " TM_ILL_STATUS0 $(devmem 0xFD409A98)" echo " TM_ILL_STATUS1 $(devmem 0xFD409A9C)" echo " L3_CALIB_PIPE_NSW_CODE_STATUS $(devmem 0xFD40EF1C)" echo " L3_CALIB_RX_CODE_STATUS $(devmem 0xFD40EF28)" echo " L2_TM_MISC_ST_0 $(devmem 0xFD409AC8)" echo " L3_CALIB_ICAL_CODE_STATUS $(devmem 0xFD40EF24)" echo " L0_BG_POWER_GOOD_STATUS $(devmem 0xFD402B18)" echo " L0_SUPPLY_POWER_GOOD_STATUS $(devmem 0xFD402B1C)" echo " L3_CALIB_DONE_STATUS $(devmem 0xFD40EF14)" echo " L3_CALIB_PIPE_PSW_CODE_STATUS $(devmem 0xFD40EF18)" echo " L2_TXPMA_ST_0 $(devmem 0xFD408B00)" echo " L2_TXPMA_ST_1 $(devmem 0xFD408B04)" echo " L2_TXPMA_ST_2 $(devmem 0xFD408B08)" echo " L2_TXPMA_ST_3 $(devmem 0xFD408B0C)" echo " L2_TXPMA_ST_4 $(devmem 0xFD408B10)" echo " L2_TM_ILL9 $(devmem 0xFD409984)" echo " L2_TM_ILL13 $(devmem 0xFD409994)" echo "***********************END*******************************"

 

USB PHY reset

On ZCU102, USB PHY ULPI reset is connected to the PS_MODE1 pin.  ULPI reset are done twice, once in FSBL and then in Linux as part of Serdes driver during PHY initialization.
both resets is done by writing to the PS_MODE register directly.

For custom board, if USB doesn't work, they can try to issue the reset again in the Linux.
If customer uses EMIO 0 as reset pin GPIO, then we can try to do the following sequence on Linux prompt

echo 416 >/sys/class/gpio/export echo out > /sys/class/gpio/gpio416/direction echo 1 > /sys/class/gpio/gpio416/value sleep 2 echo 0 > /sys/class/gpio/gpio416/value sleep 2 echo 1 > /sys/class/gpio/gpio416/value echo 416 >/sys/class/gpio/unexport

USB Gadget scripts

MASS STORAGE

dd if=/dev/zero of=/tmp/mydev count=512 bs=1M mount -t configfs none /sys/kernel/config cd /sys/kernel/config/usb_gadget mkdir g1 cd g1 echo "64" > bMaxPacketSize0 echo "0x200" > bcdUSB echo "0x100" > bcdDevice echo "0x03FD" > idVendor echo "0x0501" > idProduct mkdir -p strings/0x409 echo "complaince es1" > strings/0x409/serialnumber echo "xilinx" > strings/0x409/manufacturer echo "versal" > strings/0x409/product #echo "high-speed" > max_speed mkdir functions/mass_storage.ms0 mkdir configs/c1.1 echo 0xC0 > configs/c1.1/bmAttributes echo /tmp/mydev > functions/mass_storage.ms0/lun.0/file echo 1 > functions/mass_storage.ms0/lun.0/removable ln -s functions/mass_storage.ms0/ configs/c1.1/ echo "fe200000.dwc3" > UDC

RNDIS Gadget

mount -t configfs none /sys/kernel/config cd /sys/kernel/config/usb_gadget mkdir g1 cd g1 echo "64" > bMaxPacketSize0 echo "0x200" > bcdUSB echo "0x100" > bcdDevice echo "0x03FD" > idVendor echo "0x0502" > idProduct mkdir configs/c1.1 mkdir functions/rndis.rn0 ln -s functions/rndis.rn0/ configs/c1.1/ echo "fe200000.dwc3" > UDC ifconfig usb0 10.10.70.1 ifconfig usb0 up

HID gadget

mount -t configfs none /sys/kernel/config/ echo ""Creating HID..."" cd /sys/kernel/config/usb_gadget/ mkdir -p gadget cd gadget echo 0x0525 > idVendor echo 0xa4ac > idProduct echo 0x00 > bDeviceClass echo 0x00 > bDeviceSubClass echo 0x00 > bDeviceProtocol bmAttributes mkdir -p strings/0x409 echo ""0000000001"" > strings/0x409/serialnumber echo ""manufacturer"" > strings/0x409/manufacturer echo ""HID Gadget"" > strings/0x409/product mkdir -p functions/hid.usb0 echo 1 > functions/hid.usb0/protocol echo 1 > functions/hid.usb0/subclass echo 8 > functions/hid.usb0/report_length echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08\\x81\\x02\\x95\\x01\\x75\\x08\\x81\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\x65\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 > functions/hid.usb0/report_desc mkdir -p configs/c.1/strings/0x409 echo ""Conf 1"" > configs/c.1/strings/0x409/configuration echo 0x00 > configs/c.1/MaxPower echo 0xC0 > configs/c.1/bmAttributes ln -s functions/hid.usb0 configs/c.1/ ls /sys/class/udc > UDC //Key Press echo -ne ""\0\0\0\0\0\0\0\0"" > /dev/hidg0 echo -ne ""\0\0\x06\0\0\0\0\0"" > /dev/hidg0 echo -ne ""\0\0\0\0\0\0\0\0"" > /dev/hidg0 echo -ne ""\0\0\x07\0\0\0\0\0"" > /dev/hidg0 echo -ne ""\0\0\0\0\0\0\0\0"" > /dev/hidg0 echo -ne ""\0\0\x08\0\0\0\0\0"" > /dev/hidg0 echo -ne ""\0\0\0\0\0\0\0\0"" > /dev/hidg0 echo -ne ""\0\0\x04\0\0\0\0\0"" > /dev/hidg0 echo -ne ""\0\0\0\0\0\0\0\0"" > /dev/hidg0 echo -ne ""\x00\0\x05\0\0\0\0\0"" > /dev/hidg0 echo -ne ""\0\0\0\0\0\0\0\0"" > /dev/hidg0

UVC GADGET

UVC_YUV_FORMAT

#!/bin/bash DIR=`dirname $0` UDC_NAME=fe200000.dwc3 GADGET_PATH=/sys/kernel/config/usb_gadget FUNCTION_PATH=${GADGET_PATH}/g/functions/uvc.usb0 FPS=30 FRAME_INTERVAL=333333 export UVC_WIDTH=640 export UVC_HEIGHT=480 echo "UVC_WIDTH $UVC_WIDTH" echo "UVC_HEIGHT $UVC_HEIGHT" BUFFERSIZE=$(($UVC_WIDTH * $UVC_HEIGHT *2)) MAX_BITRATE=$(($BUFFERSIZE * 8 * $FPS)) MIN_BITRATE=$MAX_BITRATE # config mount -t configfs none /sys/kernel/config mkdir -p ${GADGET_PATH}/g mkdir -p ${FUNCTION_PATH}/control/header/h ln -s ${FUNCTION_PATH}/control/header/h ${FUNCTION_PATH}/control/class/fs #ln -s ${FUNCTION_PATH}/control/header/h ${FUNCTION_PATH}/control/class/hs ln -s ${FUNCTION_PATH}/control/header/h ${FUNCTION_PATH}/control/class/ss mkdir -p ${FUNCTION_PATH}/streaming/uncompressed/u/hd mkdir -p ${FUNCTION_PATH}/streaming/header/h #bash -c "echo \"1024\" > ${FUNCTION_PATH}/streaming_maxpacket" bash -c "echo \"3072\" > ${FUNCTION_PATH}/streaming_maxpacket" mkdir -p ${GADGET_PATH}/g/configs/c.1 bash -c "echo \"0x200\" > ${GADGET_PATH}/g/bcdUSB" mkdir ${GADGET_PATH}/g/strings/0x409 mkdir ${GADGET_PATH}/g/configs/c.1/strings/0x409 echo 0x3290 > ${GADGET_PATH}/g/idProduct echo 0x18ec > ${GADGET_PATH}/g/idVendor echo "XILINXTEST" > ${GADGET_PATH}/g/strings/0x409/serialnumber echo "XILINX" > ${GADGET_PATH}/g/strings/0x409/manufacturer echo "XILINX UVC TEST 1.0" > ${GADGET_PATH}/g/strings/0x409/product echo "Conf 1" > ${GADGET_PATH}/g/configs/c.1/strings/0x409/configuration #echo 120 > ${GADGET_PATH}/g/configs/c.1/MaxPower cd /sys/kernel/config/usb_gadget/g/ mkdir -p functions/uvc.usb0/streaming/uncompressed/u/360p cat <<EOF > functions/uvc.usb0/streaming/uncompressed/u/360p/dwFrameInterval 666666 1000000 5000000 EOF # enable ln -s ${FUNCTION_PATH}/streaming/uncompressed/u ${FUNCTION_PATH}/streaming/header/h ln -s ${FUNCTION_PATH}/streaming/header/h ${FUNCTION_PATH}/streaming/class/fs ln -s ${FUNCTION_PATH}/streaming/header/h ${FUNCTION_PATH}/streaming/class/hs ln -s ${FUNCTION_PATH}/streaming/header/h ${FUNCTION_PATH}/streaming/class/ss ln -s ${FUNCTION_PATH} ${GADGET_PATH}/g/configs/c.1 bash -c "echo ${UDC_NAME} > ${GADGET_PATH}/g/UDC"

UVC_MJPEG_FORMAT

/* UVC_MJPEG_FORMAT */ echo "UVC_WIDTH $UVC_WIDTH" echo "UVC_HEIGHT $UVC_HEIGHT" BUFFERSIZE=$(($UVC_WIDTH * $UVC_HEIGHT *2)) MAX_BITRATE=$(($BUFFERSIZE * 8 * $FPS)) MIN_BITRATE=$MAX_BITRATE # config mount -t configfs none /sys/kernel/config mkdir -p ${GADGET_PATH}/g1 mkdir -p ${FUNCTION_PATH}/control/header/h ln -s ${FUNCTION_PATH}/control/header/h ${FUNCTION_PATH}/control/class/fs ln -s ${FUNCTION_PATH}/control/header/h ${FUNCTION_PATH}/control/class/ss mkdir -p ${FUNCTION_PATH}/streaming/mjpeg/m/hd echo ${FRAME_INTERVAL} > ${FUNCTION_PATH}/streaming/mjpeg/m/hd/dwFrameInterval echo ${FRAME_INTERVAL} > ${FUNCTION_PATH}/streaming/mjpeg/m/hd/dwDefaultFrameInterval echo ${MAX_BITRATE} > ${FUNCTION_PATH}/streaming/mjpeg/m/hd/dwMaxBitRate echo ${MAX_BITRATE} > ${FUNCTION_PATH}/streaming/mjpeg/m/hd/dwMinBitRate echo ${UVC_WIDTH} > ${FUNCTION_PATH}/streaming/mjpeg/m/hd/wWidth echo ${UVC_HEIGHT} > ${FUNCTION_PATH}/streaming/mjpeg/m/hd/wHeight echo ${BUFFERSIZE} > ${FUNCTION_PATH}/streaming/mjpeg/m/hd/dwMaxVideoFrameBufferSize mkdir -p ${FUNCTION_PATH}/streaming/header/h sudo bash -c "echo \"1024\" > ${FUNCTION_PATH}/streaming_maxpacket" mkdir -p ${GADGET_PATH}/g1/configs/c1.1 sudo bash -c "echo \"0x200\" > ${GADGET_PATH}/g1/bcdUSB" # enable ln -s ${FUNCTION_PATH}/streaming/mjpeg/m ${FUNCTION_PATH}/streaming/header/h ln -s ${FUNCTION_PATH}/streaming/header/h ${FUNCTION_PATH}/streaming/class/fs ln -s ${FUNCTION_PATH}/streaming/header/h ${FUNCTION_PATH}/streaming/class/hs ln -s ${FUNCTION_PATH} ${GADGET_PATH}/g1/configs/c1.1 sudo bash -c "echo ${UDC_NAME} > ${GADGET_PATH}/g1/UDC"

COMPOSITE GADGET

#!/bin/bash -e modprobe libcomposite mount -t configfs none /sys/kernel/config cd /sys/kernel/config/usb_gadget/ mkdir g && cd g echo 0x1d6b > idVendor # Linux Foundation echo 0x0104 > idProduct # Multifunction Composite Gadget echo 0x0100 > bcdDevice # v1.0.0 echo 0x0200 > bcdUSB # USB 2.0 mkdir -p strings/0x409 echo "xxxxxxxxxxxx" > strings/0x409/serialnumber echo "xilinx" > strings/0x409/manufacturer echo "versal" > strings/0x409/product mkdir -p functions/acm.usb0 # serial mkdir -p functions/ecm.usb0 # network mkdir -p functions/rndis.usb0 # network mkdir -p functions/mass_storage.ms0 # mass storage dd if=/dev/zero of=/tmp/mydev count=256 bs=1M echo /tmp/mydev > functions/mass_storage.ms0/lun.0/file echo 1 > functions/mass_storage.ms0/lun.0/removable mkdir -p configs/c.1 echo 250 > configs/c.1/MaxPower echo 0xE0 > configs/c.1/bmAttributes ln -s functions/rndis.usb0 configs/c.1/ ln -s functions/mass_storage.ms0/ configs/c.1/ #ln -s functions/ecm.usb0 configs/c.1/ ln -s functions/acm.usb0 configs/c.1/ ls /sys/class/udc/ > UDC

AUDIO GADGET

#!/bin/sh CONFIGFS_BASE_PATH="/sys/kernel/config" CONFIGFS_GADGET_PATH=${CONFIGFS_BASE_PATH}"/usb_gadget/g1" GADGET_SERIAL_NUMBER="BlackBoxIreland_1234567890" GADGET_MANUFACTURER="Black Box Software Development Services, Ltd. (Ireland)" GADGET_PRODUCT="BlackBoxTest - HID Audio" GADGET_IDVENDOR=0x0101 GADGET_IDPRODUCT=0x1d6b GADGET_CONFIG_DESCRIPTION="Config 1: BB HID Keyboard" modprobe configfs modprobe libcomposite mount none ${CONFIGFS_BASE_PATH} -t configfs mkdir -p ${CONFIGFS_GADGET_PATH} echo ${GADGET_IDVENDOR} > ${CONFIGFS_GADGET_PATH}/idVendor echo ${GADGET_IDPRODUCT} > ${CONFIGFS_GADGET_PATH}/idProduct echo 0xef > ${CONFIGFS_GADGET_PATH}/bDeviceClass echo 0x02 > ${CONFIGFS_GADGET_PATH}/bDeviceSubClass echo 0x01 > ${CONFIGFS_GADGET_PATH}/bDeviceProtocol mkdir -p ${CONFIGFS_GADGET_PATH}/configs/c.1/ mkdir -p ${CONFIGFS_GADGET_PATH}/functions/uac2.0/ mkdir -p ${CONFIGFS_GADGET_PATH}/strings/0x409 mkdir -p ${CONFIGFS_GADGET_PATH}/configs/c.1/strings/0x409 echo ${GADGET_CONFIG_DESCRIPTION} > ${CONFIGFS_GADGET_PATH}/configs/c.1/strings/0x409/configuration echo 250 > ${CONFIGFS_GADGET_PATH}/configs/c.1/MaxPower echo ${GADGET_SERIAL_NUMBER} > ${CONFIGFS_GADGET_PATH}/strings/0x409/serialnumber echo ${GADGET_MANUFACTURER} > ${CONFIGFS_GADGET_PATH}/strings/0x409/manufacturer echo ${GADGET_PRODUCT} > ${CONFIGFS_GADGET_PATH}/strings/0x409/product ln -s ${CONFIGFS_GADGET_PATH}/functions/uac2.0 ${CONFIGFS_GADGET_PATH}/configs/c.1/ ls /sys/class/udc > ${CONFIGFS_GADGET_PATH}/UDC aplay -v -D hw:2,0 -f S16_LE -r 48000 -c 2 /home/mass_storage/M1F1-int16-AFsp.wav arecord -v -D hw:2,0 -f S16_LE -r 48000 -c 2 ./sampleFromEmeraldDecoder.raw

USB compliance mode test procedure

 For usb compliance mode test, FSBL is used to bring controller out of reset.

Host mode

  1. Enter into Host mode

        a.      Bring the core out of reset
        b.      Set GCTL.PRTCAPDIR = 1

  1. Enter into compliance mode

        a.      Put the host controller into compliance mode using the commands below
                 PORTSC &= 0xFFFEFE1F
                 PORTSC |= 0x10140
        b.      Wait for some time
        c.       Set GUSB3PIPECTL.HstPrtCmpl = 1
        // This will transmit CP0 pattern

  1. Enter into next compliance pattern

        a.      Set GUSB3PIPECTL.HstPrtCmpl = 0
        b.      Set GUSB3PIPECTL.HstPrtCmpl = 1
        // This will transmit the next compliance pattern

Device mode

In device mode SS Compliance mode is normally entered and controlled by the remote link partner.

The SS port link enters compliance after failing the first polling sequence after power on. But this can be forcefully tried using the below steps Set DCTL.RUN_STOP = 0

  1. Set DCTL.RUN_STOP = 0

  2. DCTL. ULSTCHNGREQ = 10

  3. Set  DCTL.RUN_STOP = 1  here the link should go to compliance mode

  4. Once in compliance ,

alternatively write DCTL. ULSTCHNGREQ = 0 & DCTL. ULSTCHNGREQ = 10 to enter into next compliance mode

 

Related content

© Copyright 2019 - 2022 Xilinx Inc. Privacy Policy