MQXLITE USB stack not able to reconnect properly

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

MQXLITE USB stack not able to reconnect properly

1,864 Views
stefanburstrom
Contributor I

Hi!
I am having a weird problem with the MQXLITE+Processor Exprt USB stack. I have a device using the CDC stack to emulate a serial port. After reset, the device will connect fine with my host and show up as a serial port. But if I unplug the device and reconnect it again, it wont come back as a recongnized USB device any longer. I have been looking at the USB trace after the reconnect and the device seem to be failing sometime shortly after receving the initial GET_DESCRIPTOR(0) request. The device receives the setup packet correctly and responds with an ACK, but it does not respond to the subsequent IN tokens from the host. (During a successful enumeration, I see my device respond with a NACK packet on the first attempt from the host and then with a valid response. During the failed transfer, the device does not respond at all to the IN token).

To pinpoint the problem further I have run an experiment where I disable the D+ pullup shortly and then reenable it. The same problem occurs, the device disappears from the host and when it reappears again, the host tries to reenumerate the device but the enumeration fails during the GET_DESCRIPTOR call.

Has anyone seen something similar in the past? Any thoughts on where to start looking for the problem?

I have based my code on the virtual_com.c example code and the only initialization of the USB stack is the call to

error = USB_Class_CDC_Init(CONTROLLER_ID,USB_App_Callback, NULL,USB_Notify_Callback);

unless I have missed any initialization needed. (Which I doubt, given that the connection works the first time)

My hardware is a K20 MCU

Thanks!

Stefan Burstrom

Labels (2)
0 Kudos
Reply
7 Replies

1,436 Views
mjbcswitzerland
Specialist V

Stefan

Check the mask of your K20 and the errata 5928 (if applicable) - this states that the USBRESET bit in USB0_USBTRC0 does not operate as expected in all cases and so may have an influence on subsequent enumerations.

Personally I have used the uTasker USB stack [http://www.utasker.com/docs/uTasker/USB_User_Guide.PDF ] in CDC mode on devices with this errata and haven't found any problems (without the workaround) but it may be that this is just luck, depending on how it is exactly used.

There are some K20 USB binaries here: µTasker Test Software and Demos that you could load to see whether there is a difference - I never had re-enumeration difficulties with them (yet) but perhaps there is an influence on your particular HW (?)

Regards

Mark

0 Kudos
Reply

1,436 Views
stefanburstrom
Contributor I

Thanks Mark!

I have been looking through the code and USB0_USBTRC0 is only reset during startup so I am not sure if this errata is applicable here :smileysad: I have been carefully inserting USB bus reset events (timed from the startup of the device) and if I reset the bus just after the initial GET_DESCRIPTOR, the 2nd time the device is enumerated, it comes up fine. But as soon as I let the furst enumeration phase past the SET_ADDRESSS phase before restarting the bus, the stack is stuck without responding to the enumeration packets.

/Stefan

0 Kudos
Reply

1,436 Views
stefanburstrom
Contributor I

Hi again!

I managed to track down the problem! It turns out to be a fairly nasty bug in the Processor Expert USB stack! During the call to SET_ADDRESS, the usb_dci.c implementation installs a callback that sets the address in the hardware once the SET_ADDRESS call is complete. (I assume that this is using the callback to ensure that the hardware write is done after the device has acknowledged the SET_ADDRESS request on address 0). Now comes the interesting part. The callback function is never uninstalled. Ie, on every completed ep0 request, the USB_DCI_SetAddressCallback function is called!! The is not really a problem as the address to be used is stored in EPDataTDPtr[0].ParamPtr. Ie, the hardware register is updated with the same bus address for every request that appears on ep0. A little inefficient perhaps, but things still work. The real problem occurs when the bus is reenumerated. As the callback is still in place (for some reason, those fields are not initialized for ep0) the first call to GET_DESCRIPTOR will also trigger the callback which now sets the device address to the same address that was used previously. Obviously this does not work as the host is expecting the device to respond on address 0 for the first GET_DESCRIPTOR request.

To properly address this problem, I think that 2 changes need to be made:

* Clear the callback once the USB_DCI_SetAddressCallback has completed its job

* Clear the callback during the initialization of ep0 to make sure that no spurious items are left in case something is interrupting the SET_ADDRESS transfer before the transfer is completed.

What is the appropriate forum to report this bug?

regards,

Stefan

0 Kudos
Reply

1,436 Views
CarlosCasillas
NXP Employee
NXP Employee

Hi Stefan,

Have you verified if the issue also happens using the PEx + MQX Lite projects included on Freescale USB Stack v4.1.1? They are available at the following path after installing the stack:

  C:\Freescale\Freescale USB Stack v4.1.1\ProcessorExpert\Examples\Device\CDC\

I just tested the USB_CDC_DEVICE_MQX_Lite_MK53N512_PEx example on a TWR-K53N512 board, and it was always enumerated properly (it is still powered during the disconnection/connection).


Hope this will be useful for you
Best regards!
/Carlos

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

0 Kudos
Reply

1,436 Views
stefanburstrom
Contributor I

Hi Carlos!

Which download contains the C:\Freescale\Freescale USB Stack v4.1.1 branch of the code? I ran out of space on my machine a while ago and deleted a bunch of files so I might have deleted this code. I am only using the code that is generated from CodeWarrior when I am setting up a MQXLITE project. (I am running CW 10.5 right now, but I am currently installing 10.6 to see if this makes a difference)

I did check the code that comes with the full release of MQX (C:\Freescale\Freescale_MQX_4_1\usb...) and the implementation of SET_ADDRESS is significantly different so I dont think that the problem exists in the full stack.

Fwiw, my code started to work once I patched the implementation of SET_ADDRESS, so I am quite sure that the problem exists in at least one variant of the code. I dont have a problem with the stack any longer, but I thought that you might be interested in getting this fixed for future customers. I'd be happy to provide you with a patch for review by your engineering team.

Best,

Stefan

0 Kudos
Reply

1,436 Views
CarlosCasillas
NXP Employee
NXP Employee

Hi Stefan,

The mentioned path is accessible after installing the Freescale USB Stack v4.1.1, which could be downloaded from the following link:

www.freescale.com/medicalusb

A package of USB components are also included on the same installation, and they could be imported. These components are available at the following path:

C:\Freescale\Freescale USB Stack v4.1.1\ProcessorExpert\Components\


Hope this will be useful for you
Best regards!
/Carlos

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

0 Kudos
Reply

1,436 Views
mjbcswitzerland
Specialist V

Stefan

I don't know who manages the PE stuff but I expect some Freescale people will pick it up from here.

In device mode there is no need for a call-back to set the address since this can be done with a local variable as follows:

- ucAddress initialised to zero and set to 0 on every USB reset
- on each USB reset also set ADDR (the HW register) to 0

- each time there is an acknowledged TX transaction set ADDR = ucAddress; (this is in fact more efficient than having an if (needs to be  change) {write it and doesn't disturb since it is simply setting 0 all the time until an address has been received})
- when a REQUEST SET ADDRESS is received form the host the variable ucAddress is set accordingly and then it is automatically updated at the correct time.

Regards

Mark

0 Kudos
Reply