LDD_USB times out with LDD_USB_TRANSFER_ERROR_BUS_TIMEOUT on first command

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LDD_USB times out with LDD_USB_TRANSFER_ERROR_BUS_TIMEOUT on first command

Jump to solution
1,330 Views
jeremygordon
Contributor II

Hi,

I'm using a custom K20DX256 based board and am trying to use the LDD_USB interface generated by processor expert to implement a simple USB host.

My device successfully generates a reset recovery event identifying as a high speed device and the device physically powers up but I'm getting stuck trying to query the device descriptor. I always get a LDD_USB_TRANSFER_ERROR_BUS_TIMEOUT.

I have tried a few different USB devices with no difference.

I'm assuming that getting past USB device reset means that the electrical level stuff is working (it's a very basic board with 30 ohm resistors in serial connecting a USB micro and the K20 DP/DN pins, with matched length on the DP/DN differential pair data traces).

Any ideas?

Thanks!

Jeremy

void USB1_OnHostResetRecovery(LDD_TUserData *UserDataPtr, LDD_USB_TBusSpeed CurrentSpeed)

{

  bus_speed = CurrentSpeed;

  _lwevent_set(&reset_recovery, 1);

}

void Task1_task(uint32_t task_init_data)

{

  // initialize the reset recovery event

  _lwevent_create(&reset_recovery, 0);

  _lwevent_clear(&reset_recovery, 1);

  // init and enable the USB host

  LDD_TDeviceData* pUSB1 = USB1_Init(NULL);

  if( pUSB1 == NULL ) {

  SEGGER_RTT_printf(0, "error: failed to init USB1.\n");

  }

  _mqx_uint error;

  if( (error = USB1_Enable(pUSB1)) != ERR_OK ) {

  SEGGER_RTT_printf(0, "error: unable to enable USB1. (0x%x)\n", error);

  }

  // wait indefinitely for the device to be plugged in

  _lwevent_wait_for(&reset_recovery, 1, TRUE, 0);

  LDD_USB_Host_TPipeHandle *defaultPipeHandle;

  LDD_USB_Host_TPipeDescr defaultPipeParams;

  memset(&defaultPipeParams, 0, sizeof(defaultPipeParams));

  // the default address

  defaultPipeParams.DevAddress = 0;

  defaultPipeParams.DevSpeed = bus_speed;

  defaultPipeParams.MaxPacketSize = 64;

  defaultPipeParams.EpDir = LDD_USB_DIR_OUT;

  // the default endpoint

  defaultPipeParams.EpNumber = 0;

  defaultPipeParams.TransferType = LDD_USB_CONTROL;

  if( (error = USB1_HostOpenPipe(pUSB1, &defaultPipeParams, &defaultPipeHandle)) != ERR_OK ) {

  SEGGER_RTT_printf(0, "error: failed to open the default endpoint on USB1 (%x).\n", error);

  }

  LDD_USB_TSDP transferSetupData;

  transferSetupData.bmRequestType = 0x80;

  transferSetupData.bRequest = LDD_USB_REQ_GET_DESCRIPTOR;

  transferSetupData.wValue = 0x0100;

  transferSetupData.wIndex = 0x0000;

  transferSetupData.wLength = 18;

  LDD_USB_Host_TTD transferDescriptor;

  unsigned char descriptor[18];

  memset(&transferDescriptor, 0, sizeof(transferDescriptor));

  transferDescriptor.SDPPrt = &transferSetupData;

  transferDescriptor.BufferPtr = descriptor;

  transferDescriptor.BufferSize = 18;

  //transferDescriptor.CallbackFnPtr = &GetDescriptorDoneCB;

  LDD_USB_Host_TTransferHandle *transferHandle;

  if( (error = USB1_HostSendSetup(pUSB1, defaultPipeHandle, &transferDescriptor, &transferHandle)) != ERR_OK ) {

  SEGGER_RTT_printf(0, "error: failed to send the GET_DESCRIPTOR query on USB1 (%x).\n", error);

  }

  while(1) {

  LDD_USB_TTransferState state = USB1_HostGetTransferStatus(pUSB1, transferHandle);

  if( state < LDD_USB_TRANSFER_QUEUED ) {

  SEGGER_RTT_printf(0, "error: transfer state is (%x).\n", state);

  break;

  }

  }

Labels (2)
Tags (1)
0 Kudos
1 Solution
951 Views
jeremygordon
Contributor II

Hi,

Thanks very much for your reply Kan. I think the good advice from your post is to try a known good sample.

Separate from the advice of trying a known good sample, as per my original post, I'm don't want to use the Freescale USB stack but instead want to create my own implementation starting from the LDD_USB driver. The device I am connecting to is very simple and I don't need the overhead of the Freescale USB stack, but instead just need to implement some really basic bulk transfers, which the LDD_USB driver is perfect for. If I was trying to use a mass storage device or other more complicated USB class, I would use the Freescale USB stack.

The good news is I figured out what my problem was, and it was a hardware issue.

In my custom PCB design, I had supplied the MK20DX256VLH7 chip with 3.3v on the VDD and VBAT pins: 3, 21, 30 and 48.

I'm powering the MX20DX256VLH7 from a 3.3v regulator from a LiPo battery, and have a 5v boost circuit and a LiPo charging circuit so my intention was to keep things simple vis-a-vis the MX20DX256VLH7 and not use any of its built in voltage regulation features. I know it has an internal LDO to create 3.3v from the USB bus' 5v which is great in the case of a USB device, but I'm implementing a USB host, so this is less useful for me.

The issue was I had left VOUT33 (pin 7) floating in my design. Once I tied VOUT33 to VDD, everything magically worked!

Frustrating, but my 10 day tour of the electrical and signal layers of USB (and acquisition of a USB analyzer) has been a valuable learning experience :smileyhappy:

Hopefully this is helpful for others in the future.

Best Regards,

Jeremy

View solution in original post

0 Kudos
6 Replies
951 Views
Kan_Li
NXP TechSupport
NXP TechSupport

Hi Jeremy,

What is the part number of K20DX256, is it a 50MHz part or something else? Please kindly help to clarify.

Thanks for your patience!


Have a great day,
Kan

NXP Technical Support
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
951 Views
jeremygordon
Contributor II

Hi! Thank you for your response, any suggestions would be very appreciated!

I'm using a MK20DX256VLH7 (the 72MHz part).

I'm not really interested in using the USB stack, just LDD_USB. I purchased a USB protocol analyzer (the Packet-Master USB500 AG USB Analyser/Generator), but similar to what I see using my Logic 16 Pro logic analyzer's digital and analog traces from my posts above, the USB500 isn't able make much sense of what it is seeing on the bus. It is not interpreting the SE0 with intermittent J/K seen in my posts above as a reset (although it works fine tracing other USB hosts accessing the same set of test USB peripherals).

I have tried several different USB peripherals: a thumb drive (a high speed device), a PS4 controller (a high speed USB device), the SEGGER J-Link (a full speed device). The high speed devices attempt to transmit a few chirps but they don't look right (as per the posted traces) and the USB500 sees them as corrupt.

Even with the full speed device, I see don't see SE0 maintained for ~50ms continuously, I see SE0 intermixed with J/K which AFAIK should not be happening for a full speed device (as opposed to a high speed device attempting to handshake with J/K chirps).

For example, below is a capture using the USB500 of a full speed USB peripheral with the LDD_USB host implementation. Note the length of the resets are very short and there are several of them (about ~4us instead of the expected continuous ~50us). The "red" for the duration indicates an "out of spec" duration for the reset condition.

Screen Shot 2016-01-08 at 12.27.05 AM.png

Under the debugger, I notice that LDD_USB does appear to be correctly disabling SOF during reset, which is the only thing I could imagine that would be attempting to manipulate the USB_P and USB_N lines away from SE0 during reset for a full speed peripheral. Tracing through the LDD_USB implementation (USB1.c) in the debugger everything looks as I would expect.

As is evident from my posts above, I am using MQXLite, currently just a single task which blocks on _lwevent_wait_for() waiting for the USB1_OnHostResetRecovery() callback/event. Is it possible MQXLite is somehow interfering with the LDD_USB?

The system clock / clock configuration settings I'm using are:

Screen Shot 2016-01-08 at 12.13.13 AM.png

Screen Shot 2016-01-08 at 12.13.29 AM.png

The clock path for LDD_USB is:

Screen Shot 2016-01-08 at 12.15.57 AM.png

My dev board layout is very simple / naieve and looks as below, where the USB_P and USB_N signals are meandered to be within 1% length of each other. I added the (pointless) via on USB_N so that both traces would be as similar as possible. If it's not clear, those are 33 ohm resistors in serial on the USB_P and USB_N lines.

Screen Shot 2016-01-08 at 12.21.28 AM.png

Thanks for reading!

0 Kudos
951 Views
Kan_Li
NXP TechSupport
NXP TechSupport

Hi Jeremy,

Thanks for the information! but in my understanding, to get any USB application working, at least there should be a USB stack running on that device, and for the MK20DX256VLH7, there is MSD Host demo for that part, you may find it in the folder of "C:\Freescale\Freescale USB Stack v4.1.1\Source\Host\examples\msd\iar_ew\kinetis_k20_72MHz", if you have installed USB stack ver 4.1.1, downloadable from the following link : USB Stack v4.1.1 NXP bare metal (no OS) USB Stack

and seems you are using 16MHz crystal on your board, right? if so, you may change the ref clock as shown below:

pastedImage_1.png

I think with that demo, you may check if your board could work with any msd device so that you may find if your issue is related with the hardware or software.

Hope that helps,


Have a great day,
Kan

NXP Technical Support
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
952 Views
jeremygordon
Contributor II

Hi,

Thanks very much for your reply Kan. I think the good advice from your post is to try a known good sample.

Separate from the advice of trying a known good sample, as per my original post, I'm don't want to use the Freescale USB stack but instead want to create my own implementation starting from the LDD_USB driver. The device I am connecting to is very simple and I don't need the overhead of the Freescale USB stack, but instead just need to implement some really basic bulk transfers, which the LDD_USB driver is perfect for. If I was trying to use a mass storage device or other more complicated USB class, I would use the Freescale USB stack.

The good news is I figured out what my problem was, and it was a hardware issue.

In my custom PCB design, I had supplied the MK20DX256VLH7 chip with 3.3v on the VDD and VBAT pins: 3, 21, 30 and 48.

I'm powering the MX20DX256VLH7 from a 3.3v regulator from a LiPo battery, and have a 5v boost circuit and a LiPo charging circuit so my intention was to keep things simple vis-a-vis the MX20DX256VLH7 and not use any of its built in voltage regulation features. I know it has an internal LDO to create 3.3v from the USB bus' 5v which is great in the case of a USB device, but I'm implementing a USB host, so this is less useful for me.

The issue was I had left VOUT33 (pin 7) floating in my design. Once I tied VOUT33 to VDD, everything magically worked!

Frustrating, but my 10 day tour of the electrical and signal layers of USB (and acquisition of a USB analyzer) has been a valuable learning experience :smileyhappy:

Hopefully this is helpful for others in the future.

Best Regards,

Jeremy

0 Kudos
951 Views
jeremygordon
Contributor II

Ok, so some more data. If I *just* perform the USB1_Init() and USB1_Enable() calls, here is what my signal capture looks like after reset (with my device plugged in).

I would have expected to see a prolonged SE0 for reset (~50ms) but I'm not seeing that on the trace.

Any ideas?

Here is 7 seconds of mixed signal capture, notice the protocol decode in the lower right panel.

At the high level this is ~4 seconds of D+ held high with D- low indicating a full speed device, followed by ~0.5s of data (attempted reset?) followed by a repeating pattern for ~2s (some kind of idle?).

Screen Shot 2016-01-03 at 1.45.17 PM.png

Zoomed in on the 50ms of data (attempted reset?). Is it expected that SE0 would be alternated with J or K? Or is that indicating a problem with my physical circuit board?

Screen Shot 2016-01-03 at 1.46.00 PM.png

Thanks!

0 Kudos
951 Views
jeremygordon
Contributor II

Ok, so I'm guessing the 50ms of SE0 is reset, and the J/K spikes are "J/K chirps" that is the device attempting to initiate a high speed negotiation. So that makes sense. The host is not responding to the negotiation because of course the MK20DX256 only supports low speed and full speed, but not high speeds:

Screen Shot 2016-01-03 at 8.29.15 PM.png

After the reset, I get SE1 for 0.5ms with a valid SOF packet followed by 0.3ms of SE1 again. I thought SE1 was supposed to be an invalid bus condition? Is there something I'm missing about seeing SE1?

Screen Shot 2016-01-03 at 8.29.50 PM.png

This is then followed by what looks like packets every 1ms that the logic analyzer won't decode because the voltage level looks too low. They look like the right length for SOF packets for keep alive, but I'm not sure why the voltage is lower than the earlier packet:

Screen Shot 2016-01-03 at 8.42.56 PM.png

In any event, as per my original post, the transfer still fails with a LDD_USB_TRANSFER_ERROR_BUS_TIMEOUT.

Help or pointers from any USB gurus would be much appreciated!

Thanks!

Jeremy

0 Kudos