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

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

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

跳至解决方案
864 次查看
VictorLorenzo
Contributor IV

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

0 项奖励
回复
1 解答
584 次查看
VictorLorenzo
Contributor IV

Hi All,

Applying the old method "you're wasting your time anyway so dive inside the full source code tree and master it"... in the CDC class the bulk out EP handler USB_Service_Dic_Bulk_Out() receives the BULK OUT event and calls one application callback with event code USB_APP_DATA_RECEIVED. The handler for this event ends calling the USB_Class_CDC_Recv_Data() function which in turn calls _usb_device_recv_data()... and that function seems to make the magic.

--Victor

在原帖中查看解决方案

0 项奖励
回复
1 回复
585 次查看
VictorLorenzo
Contributor IV

Hi All,

Applying the old method "you're wasting your time anyway so dive inside the full source code tree and master it"... in the CDC class the bulk out EP handler USB_Service_Dic_Bulk_Out() receives the BULK OUT event and calls one application callback with event code USB_APP_DATA_RECEIVED. The handler for this event ends calling the USB_Class_CDC_Recv_Data() function which in turn calls _usb_device_recv_data()... and that function seems to make the magic.

--Victor

0 项奖励
回复