cancel
Showing results for 
Search instead for 
Did you mean: 

usb otg host lib, where is NAK for bulk-IN?

infoinfo991
Associate III
Posted on February 13, 2014 at 05:31

I am using a STM32F405RG as a USB host. I've implemented the ST USB Host library (version 2.1.0) in a way that supports multiple devices behind a hub. In order to seemingly support unlimited devices (as much as possible, limited by the number of available addresses), I made the choice of opening host channels only when needed, and closing them when they are not.

However, I ran into a small problem. I need to check for NAK in order to know that it's OK to halt and close the host channel so that the next device can use it.

For interrupt-IN endpoints, the NAK arrives, I can check the URB state and it would be URB_NOTREADY when a NAK is received. Great, it works.

But the problem is with bulk-IN endpoints. URB_NOTREADY never arrives. I checked the HC ISR, and it seems that the NAK interrupt does actually occur, and the HC state is actually set to NAK, but the URB state is never updated.

So my solution is to add a few line into usb_hcd_int.c

pcore->host.HC_Status[num] = HC_NAK; // This was in the original code, around line 737 of usb_hcd_int.c in V2.1.0 date 19-March-2012

if (hcchar.b.eptype == EP_TYPE_BULK && pcore->host.URB_State[num] == URB_IDLE) { // I added this line

pcore->host.URB_State[num] = URB_NOTREADY; // I added this line

} // I added this line

This allowed my host channel management to be able to swap channels much faster, because it can detect a NAK instead of waiting for a timeout.

I am wondering, did I find a bug, or was it intentional by design?

I am under the impression that the bulk endpoint is just supposed to keep issuing the IN tokens and the user application is never supposed to really care if a NAK arrives.

But why not set URB_NOTREADY? Even if the tokens are issued non-stop, it would still be nice and less confusing if URB state wasn't URB_IDLE all the time. Idle made me think that the IN token wasn't sent at all, which is how all the other transfer types worked.
0 REPLIES 0