KDS3.1 + KSDK1.3 USB HID interrupt out endpoint causes enumeration errors (k22f)

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

KDS3.1 + KSDK1.3 USB HID interrupt out endpoint causes enumeration errors (k22f)

3,494 Views
thcooke77
Contributor III

I have been struggling with USB HID generic + MSD drivers for the K22F for months, and believe I have tracked it down to the composite drivers.

 

Some background:

I had a previous thread USB Generic HID+MSD Composite enumeration problems ) in which I had thought that I had tracked down the issues of using semi-hosting for print debugging within the USB drivers was causing the enumeration to fail. It turns out that disabling semi-hosting only fixed the enumeration issues for a specific type of USB controller (

Renesas Electronics USB 3.0 Host Controller). Enumeration always fails using other USB controllers like Intel.

 

Projects Demonstrating the problem:

I have 3 projects attached that demonstrate when it works, or fails. (for the Freedom K22F board). These were all created with Processor Expert, then disabling it by renaming the '.pe' file to '.pe.bak'. This was done because I need to use a HID descriptor which is not supported by PE. (Note: this descriptor is ported from a Microchip processor and works perfectly so I know the descriptor is compliant)

  1. usb_hidonly_inouteps_works.zip
    1. This is an HID generic only example. This project works with both Interrupt in and out endpoints. So a base HID only custom project works fine on all computers.
  2. usb_msd_hidineponly_works.zip
    1. This is an HID generic + MSD ram drive composite example. This project works but only has an Interrupt in endpoint for the HID,
  3. usb_msd_hidinouteps_fail.zip
    1. This is an HID generic + MSD ram drive composite example. This project does not work with both an Interrupt in and out endpoint for the HID,

 

It always fails with the 3rd project on Intel USB Controllers (Win7 64bit), or on any apple computers. If you use software USB analyzer, it always fails at the URB_FUNCTION_SELECT_CONFIGURATION phase. It will try this three times and then timeout.

 

@Mark Butcher found using a hardware USB analyzer:

Your problem is that when the host sends a SetConfiguration (interface 1) your device is responding with a zero data paket (correct) but is it responding with a DATA0 packet, rather than a DATA1 packet and the host rejects this because it is incorrect.

After 5s or so of waiting (the device doesn't send anything else) the host restets the connection and tries again. The same repeats after the reset but sometimes also the SetAddress fails with the device returning malformed frames back - this again causes reset and it goes on forever like this (randomly failing on the SetAddress or the SetInterface).

 

What I don't know now is how to debug what is going on, where and how it sends it as a DATA0 packet, etc. I am hoping that these three demonstration projects can be used to point me in the right direction.

 

Thanks,

Terry Cooke

Original Attachment has been moved to: usb_msd_hidouteponly_works.zip

Original Attachment has been moved to: usb_msd_hidinoutep_fail.zip

Original Attachment has been moved to: usb_hidonly_inouteps_works.zip

Labels (1)
17 Replies

2,009 Views
lh_dan
Contributor III

I had the same issue with the USB Stack in MQX 4.1.0 which is discussed here - MQX USBHS - Control Endpoint Zero Length Termination

This is definitely an issue on the device side of the USB stack that has been around for awhile. It will be great if an update corrects this.

-Dan

0 Kudos

2,009 Views
isaacavila
NXP Employee
NXP Employee

Hi All,

The new SDK 2.0 is now available for downloading, you can download it on: Software Development Kit for Kinetis MCUs|NXP.

I hope this can help you!!!

Best Regards,

Isaac Avila

2,009 Views
seanbolton
Contributor III

Thanks for the notification Isaac

I just had a quick try of building the new SDK 2.0 via the online tool, but for my processor I cannot select 2.0 (only 1.3).

Is the new SDK available for all processor variants?  Mine is MK10DX256xxx10  family.

regards

Sean

0 Kudos

2,009 Views
isaacavila
NXP Employee
NXP Employee

Hello Sean,

Unfortunately no all MCUs are available for this release, only the newest and some other of previous releases are available for now, like this version was a new design of drivers and stack, we pretend to add some MCUs soon.

Sorry for this inconvenience.

Edit: You can see this post for more information: Introducing Kinetis SDK v2

Best Regards,

Isaac

0 Kudos

2,009 Views
seanbolton
Contributor III

Hi Isaac

Thanks for the update and link to the page with the rollout plans, that is

helpful.

regards

Sean

On Wed, Feb 3, 2016 at 6:16 PM, isaacavila <admin@community.freescale.com>

0 Kudos

2,009 Views
mjbcswitzerland
Specialist V

Hi All

I just checked the uTasker USB stack's handling of endpoint 0 queue transmissions:

if ((tx_queue->usCompleteMessage % tx_queue->usMax_frame_length) == 0) { // if the transmitted data length was divisible by the frame length
    if (tx_queue->usLimitLength != tx_queue->usCompleteMessage)) {
        FNSEND_ZERO_DATA(ptrUSB_HW, iEndpoint);      // send/queue a zero frame to terminate status stage
    }
}

That means that it will queue a zero data packet when the complete tx length is divisible by the endpoint length (eg. 64/64 as in the discussed problem case) but not if the host has specified that it wanted this length.

This simple check has proven suitable in many products using USB-MSD and HID, whereby it is to be noted that such a composite's configuration descriptor happens to be always 64 bytes in size so is not an exception of some kind. Therefore I would suggest than anyone who can locate the tx queue in the Freescale stack can add an equivalent check to simply skip adding the zero data packet to the buffer descriptor in the first place to solve the issues.

- usCompleteMessage is the length of the configuration descriptor (64 in this case)

- usMax_frame_length is 64 bytes (endpoint size), but could be 8, which I think also causes the present Freescale stack to fail, but for a slightly different reason since the queued zero data happens to be correct but the following exchange on the bus errors.

- usLimitLength is the size that the host specified to be returned (64 bytes in the issue case)

This seems more practical than waiting for new library releases which may be incompatible or introduce different issues etc.

Regards

Mark

P.S: USB-MSD and KBOOT (HID) composite for K22 also has a 64 byte configuration descriptor and has been used by the uTasker project on all Kinetis parts with USB without any issues since 2014 - it can be tested as comparison at:

http://www.utasker.com/kinetis/FRDM-K22F.html (or for most other Freescale boards at http://www.utasker.com/kinetis.html )

0 Kudos

2,009 Views
isaacavila
NXP Employee
NXP Employee

Hello Terry,

USB team analyzed the USB transactions' log and could see that this is a host issue rather than stack. Device descriptor is 64-byte length and our full speed max packet size is 64 bytes too, from the USB spec, an additional zero lenght packet (ZLP) is needed to end the transfer. You can check this log (taken from your example) and in the first GetDescriptor(Configuration) transaction, descriptor is 64-bytes and after this 64 bytes, there is another zero length data (ZLP) from the device. In this case, the host sends the IN packet so transfer is finished correctly.

ZLP transaction.jpg

However, in the error case, after 64 bytes data are sent to the host, the host didn't send out the IN packet and host began the SetConfiguration command instead, while device still has the zero length packet to send (with proper DATA toggle value) so the first response to SetConfiguration command is the zero length packet. You can check this issue in same capture but in the transaction where host fails:

Host fails.jpg

This error is not seen in your msd_hid_inedponit_only because descritpor is 57-byte length instead of 64. I am also attaching the USB capture taken by using Ellisys' analyzer.

I hope this can help you,

Best Regards,

Isaac

----------------------------------------------------------------------------------------------------------------------------------------

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

----------------------------------------------------------------------------------------------------------------------------------------

0 Kudos

2,009 Views
dlschaeffer
Contributor II

isaacavila,

I'm having the exact same issue. Adding a dummy endpoint, per Terry​, fixes the enumeration error but this really isn't an acceptable solution. Does NXP plan on fixing the root cause? We've wasted close to two man weeks on this issue already.

0 Kudos

2,009 Views
isaacavila
NXP Employee
NXP Employee

Hello All,

As mjbcswitzerland​ already said, both conditions are issues (1- If host has specified the exact number of descriptor, like 64 in error case, no additional ZLP is needed and 2- A new setup received before the previous setup finished will end the previous setup process) and therefore, these are issues presented in KSDK 1.3, however, USB team expressed that in next KSDK release (KSDK 2.0, coming soon) the first issue is already fixed so you won't need to add a dummy endpoint in order to modify the descriptor size.

Sorry for all inconvenience it may cause and thanks a lot to mjbcswitzerland​ to add this useful information!

Best Regards,

Isaac Avila

0 Kudos

2,009 Views
dlschaeffer
Contributor II

Isaac,

I ported the KSDK2.0 KS22F release to the K22F and still had some issue with generic HID and MSD. The USB stack in KSDK 2.0 is significantly different than the existing stack. I think it is much improved, but I would prefer not to have to update all my code to work with the new API.

Also, when will KSDK2.0 be release for the K22F?

Regards,

Daniel Schaeffer

0 Kudos

2,009 Views
isaacavila
NXP Employee
NXP Employee

Hello Daniel,

Yes, in fact, there are several changes in different stacks and drivers, and it was planned to be released on next week, however, there are still making some tests and checking documentation that may cause to move some days.

I suggest to move to KSDK 2.0 as soon as it is released, due this version has some improvements and structure is a little easier to use.

I hope this can help you,

Best Regards,

Isaac

0 Kudos

2,009 Views
seanbolton
Contributor III

Hi Issac

I have been experiencing similar issues to those discussed in this thread when I am creating a USB HID device for K20 processor.

Please see my post on this USB Driver Issues on K20 with KDS/KSK demo code

Basically if I try to add a second endpoint to the descriptors for the demo HID code then the USB comms fails during initialisation.  One endpoint works fine.

This problem is really holding up our new product development as we need a working USB interface to progress.  It would be great if you or the NXP/Freescale team could take a look at my issue and possibly suggest a workaround or fix.

I saw you expect a release of KSDK 2.0.0 soon with many revisions to drivers and stacks, including USB.  I would be very happy to try a beta release of this if available and see if it helps my USB problem.

Thank you

regards

Sean

0 Kudos

2,009 Views
isaacavila
NXP Employee
NXP Employee

Hello Daniel,

I've already discussed this topic to USB team and I am waiting for their response! I'll let you know as soon as i got any response from them!

Best regards,

Isaac

0 Kudos

2,009 Views
thcooke77
Contributor III

Wow a universal host bug....

It seems to me that the best way is just to add a second dummy Interrupt-In endpoint to the Hid. This makes the descriptor > 64 bytes, and fixes the problem. This dummy endpoint will never be used, but any other modifications would just be patching out of spec hosts and most likely cause other problems.

I have tested it and it works great. I attached the working version in case someone else tries to do the same thing.

Thank you everyone, if anyone has a better method than just fudging the descriptor with a dummy endpoint so that the descriptor is not exactly 64 bytes I'll look watch for replies.

Terry Cooke

0 Kudos

2,009 Views
mjbcswitzerland
Specialist V

Hi Terry

The correct method to handle this is to remove the queued zero data frame when a SETUP is received.

USB specifies that a DATA 1 is returned after a SETUP is received, irrespective of what the host previously did.

Furthermore, the Get Configuration specifically requested 64 byte of data when it performed the Get Configuration descriptor and so already knows that 64 are going to be received, which also overrides any need to request a terminating frame (which is only necessary to distinguish the end of data when its size is not known).

This is therefore definitely not a host error in any way but something that can and does occur in normal operation.

Therefore a workaround by avoiding the length will mostly work - unless the host happens to specifically request 64 bytes [or a multiple of whatever endpoint size is being used - could also be multiple of 8s in some cases] (which is could still do); often the host requests only parts of the data and this is frequently repeated a number of times [with varying lengths] because there may be various SW modues on the host "independently" requesting such information for their own use).

There are two water-tight solutions:

- either request all PC manufacturers to modify their host code to always request a terminator so that your device will not fail

- or correct the problem in the stack

Or a 99.999% solution is to work around it and keep your fingers crossed that no host happens to specifically request 64 byte of data in the furture and have to update devices in the field to get around it.

Regards

Mark

2,009 Views
bobpaddock
Senior Contributor III

Remove the USB_BD_DTS's.  See if things work then.

That disables the USB data toggle handshake.

If it works it proves the problem is in the data toggling.

This is only for testing.  Shipping a product with DTS disable is not the best thing to do.

0 Kudos

2,009 Views
mjbcswitzerland
Specialist V

Hi Terry

I can confirm that your configuation that fails has the already observed data toggle error.

This is a rather basic driver function so it is is surpising that it can be affected by the configuration but it is consistently wrong so expect that if you report it to the KSDK developers they will be able to fix it quite quickly. The Tx control endpoint is quite simple (compared to the Rx which could have some much more subtle and nastier bugs if not tested - as this usage case doesn't seem to have been - and you move on to more complex composites).

If you prefer to fix it yourself I believe that this is the line of code which you need to concentrate on, in khci_dev.c (when ep_num == 0):

    //BD_CTRL_TX(ep_num, state_ptr->ep_info[ep_num].tx_buf_odd) =
    //    USB_LONG_LE_TO_HOST((uint32_t)(USB_BD_BC(buf_num_bytes) |
    //        USB_BD_OWN | USB_BD_DTS | USB_BD_DATA01(state_ptr->ep_info[ep_num].tx_data0)));
    usb_hal_khci_bdt_set_control((uint32_t )bdt, ep_num, USB_SEND, state_ptr->ep_info[ep_num].tx_buf_odd,
        USB_LONG_LE_TO_HOST(USB_BD_BC(buf_num_bytes) | USB_BD_OWN | USB_BD_DTS | USB_BD_DATA01(state_ptr->ep_info
[ep_num].tx_data0)));

The line of code is not incorrect in itself but the handling of tx_data0 (the data toggle) and/or tx_buf_odd gets corrupted or incorrectly handled somewhere else in the stack. It may be due to race states or task switching due to different callbacks so also playing with various other system settings and priorities may make it go aways or come back again at some time when you though things were OK again.

Debugging with the debugger is not possible with USB device (the host will reset before you can step any code) so you will need to add some non-intrusive monitoring functions to collect infomation that could be relevant to what has happended (eg. a buffer collecting data concerning when and why the buffers/toggles were changed). It helps to have a HW USB analyser with some logic analyser type strobe inputs to help work out the driver/interrupt timing synchronisation with the bus activity in case it proves to be due to race states in the code (due to the multiple class call-backs and possible task switching during the set configuration sequence).

Regards

Mark

0 Kudos