AnsweredAssumed Answered

MQX USB Kinetis Driver Bug and... Why can't I receive output from host controller?

Question asked by VictorLorenzo on Oct 18, 2013
Latest reply on Oct 20, 2013 by VictorLorenzo

Hello,

 

I'm developing a new class driver for a CCID device (Kinetis K20DN512VLK10) but can't manage to find why the low level driver only reports reception of the first bulk-out message from the host and NAKs all the rest.

 

QUESTIONS:::: Has someone experienced this before? Does any one have any idea why or what could cause the silicon IP to NAK all (but the first) OUT transactions from the host on the bulk-out endpoint?

 

Here is a USB analyser capture showing this situation. The transaction marked in blue color is the first command received in the bulk-out endpoint, I receive it, process it and return the SlotStatus message using the bulk-in endpoint. The following 234 NAKed IN transactions are OK and correspond to requests to the Interrupt-in endpoint (nothing changed inside the device so nothing is reported).

 

The problem is with the (323.902) NAKed OUT transactions shown at the end. That is not supposed to hapend, the controller (silicon IP on the Kinetis microcontroller) is automatically NAKing the transactions without reporting the data reception. No error is reported either (see more comment under the figure).

 

NAKs-01.png

 

While tracking down the situation we found one potential bug in the Kinetis low level USB driver. In the function named _usb_device_usbfs_service_err_intr(), file: khci_dev_main.c, there are hardware error situations that could trigger the callback for the service USB_SERVICE_ERROR for errors not included in the mask. In this case the USB_SERVICE_ERROR service is called indicating a 0x00 error code. It can be replicated by configuring the Kinetis CPU clock for 100MHz instead of 96MHz in the BSP so the USB is driven at 50MHz instead of 48MHz and CRC5/CRC16 errors are reported. This code corrects the issue:

if (device_error)

{

    /* Initialize the event strucutre to be passed to the upper layer*/

    event.handle = (_usb_device_handle)state_ptr;

    event.ep_num = ep_num;

    event.setup = FALSE;

    event.direction = (boolean)(stat >> 3 & 1);

    event.buffer_ptr = (uchar*)&device_error;

    event.len = ZERO_LENGTH;

 

    /* Invoke Service Call */

    (void)_usb_device_call_service(USB_SERVICE_ERROR,&event);

}

 

Thanks a lot in advance,

--Victor

Outcomes