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
- 1 Basic checks before debugging further
- 2 Guidelines on debugging USB runtime failures
- 2.1 USB Hardware Design
- 2.2 USB driver logs
- 2.3 Dynamic debug
- 2.4 Ftrace
- 2.5 Register dump
- 3 Guidelines to Debug USB PHY issues (ULPI PHY validation)
- 4 USB Register Dumps for all the USB modes
- 5 USB Gadget scripts
- 5.1 MASS STORAGE
- 5.2 RNDIS Gadget
- 5.3 HID gadget
- 5.4 UVC GADGET
- 5.5 COMPOSITE GADGET
- 5.6 AUDIO GADGET
- 6 USB compliance mode test procedure
- 6.1 Host mode
- 6.2 Device mode
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:
Kernel boot log -- Check the kernel boot logs is there any suspicious logs (dumps) are there or not.
Kernel Config -- Check the corresponding kernel configs for USB mode : Versal Linux USB Device Driver Examples
Device Tree -- Check the corresponding Device tree changes for USB mode : Versal Linux USB Device Driver Examples
Check the USB jumper settings -- Check the corresponding USB mode jumper settings : Versal Linux USB Device Driver Examples
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
ZynqMP - https://www.xilinx.com/support/documentation/user_guides/ug583-ultrascale-pcb-design.pdf#USB 2.0
Versal - https://www.xilinx.com/support/documentation/user_guides/ug863-versal-pcb-design.pdf#USB 2.0
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
REGADDR = 0x00 (Vendor ID offset of the ULPI phy)
REGWR = 0 (Since we are reading the vendor id)
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 |
---|---|
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
Ensure that the ULPI phy RESETN pin got RESET toggle sequence before proceeding with the below steps
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.
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.
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
Some Phys like TIUSB1210 may require ULPI regs OTG CTRL.DrvVbusExternal andOTG CTRL.DrvVbus to operate properly
Check if CPEN ping is getting driven properly
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,
Check USB ref clock = 250MHz
Check GT lane config
Probe ref clock = 26MHz
Check vbus status
Read GCTRL register for operation mode, got connect event , TD config, SOF is fine(not ok timer issue),
read error register.Read the port states PORTSC_20(0xFE200420)
Get the USB phy dump.
USB phy details.
USB hot-plug is working or not
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
Enter into Host mode
a. Bring the core out of reset
b. Set GCTL.PRTCAPDIR = 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
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
Set DCTL.RUN_STOP = 0
DCTL. ULSTCHNGREQ = 10
Set DCTL.RUN_STOP = 1 here the link should go to compliance mode
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