USB isochronous EP stuck

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

USB isochronous EP stuck

1,307 Views
mstumbra
Contributor II

Hi

I have LPC54608 Dev Board and implementing USB async Audio device using SDK v2.2.0

Device have 2 audio streaming interfaces, one for playback, second for recording from line in of board

If I play music from PC everything seems to work fine for hours.

But when I enable recording interface(start recording on PC side), after ~20-300 seconds music playback stops.

I am debugging this problem currently, but your advises may be helpful.

Here is what I have found for now:

  • Via hardware USB sniffer found out that actually audio data packets actually continue to be sent to isochronous OUT EP. PC even don't knows that something goes wrong;
  • USB Interrupt for incoming audio packet not generated anymore after such fault(all other, including packet sent interrupt flag generated as should);
  • Music stop and start again(actually performs set interface=0 and set interface=1 packets) makes playback work again  until next same fault;
  • All subsequent calls to USB_DeviceAudioRecv after such faults always returns by
    if (audioHandle->streamOutPipeBusy)
        {
            return kStatus_USB_Busy;
        }
  • isBusy also set in:
    
    deviceHandle->endpointCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy
  • And final and most interesting: disabling of USB double buffering fixes the problem(usb_device_lpcip3511.h)
    #define USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE (0u)

To sum up, everything works like sometime I miss call to USB_DeviceAudioRecv, but as can be seen by busy states it is always called as it should. I think as problem somewhere in USB stack, as when double buffering enabled there is added interrupt disabling and re-enabling when buffer switching made.

Hope for your advices

Thank you!

Labels (2)
Tags (2)
0 Kudos
2 Replies

935 Views
mstumbra
Contributor II
After further dubugging I have found that when EP stuck lpc3511IpState->epCommandStatusList 
of isochronous OUT EP doesn't have "Active" bit set. Nor buffer 1, nor buffer 2.
That's why interrupts are not generated anymore.
Another question how stack falled to this state. 
Because HW should generate interrupt, once it clears "A" bit.

I have a strong filling that it is related to interrupt disabling and re-enabling in
USB_DeviceLpc3511IpTransaction with double buffering enabled.
static usb_status_t USB_DeviceLpc3511IpTransaction(usb_device_lpc3511ip_state_struct_t *lpc3511IpState,
                                                   usb_device_lpc3511ip_endpoint_state_struct_t *epState,
                                                   uint8_t endpointIndex)
{
    usb_status_t status = kStatus_USB_Error;
    /* 1. transfer size is 0; 2. All are primed */
    if ((epState->transferLength <= epState->transferPrimedLength) && (epState->transferLength != 0))
    {
        return kStatus_USB_Success;
    }
#if (defined USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE) && (USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE)
    //NOTE: here may be problem
    uint32_t interruptMask;
    if ((endpointIndex >> 1U) != USB_CONTROL_ENDPOINT)
    {
        /* disable endpoint interrupts */
        interruptMask = lpc3511IpState->registerBase->INTEN;
        lpc3511IpState->registerBase->INTEN = 0;
        /* lpc3511IpState->registerBase->INTEN &= (uint32_t)(~(USB_LPC3511IP_MAX_PHY_ENDPOINT_MASK)); */
        do
        {
            status = USB_DeviceLpc3511IpGetActualBufferAndPrime(lpc3511IpState, epState, endpointIndex, 1U);
            if (status != kStatus_USB_Success)
            {
                break;
            }
        } while ((epState->transferLength > epState->transferPrimedLength) &&
                 (epState->stateUnion.stateBitField.doubleBufferBusy < 2));
        /* enable endpoint interrupt again */
        /* lpc3511IpState->registerBase->INTEN |= (uint32_t)(USB_LPC3511IP_MAX_PHY_ENDPOINT_MASK); */
        lpc3511IpState->registerBase->INTEN = interruptMask;
    }
    else
#endif
    {
        status = USB_DeviceLpc3511IpGetActualBufferAndPrime(lpc3511IpState, epState, endpointIndex, 0U);
    }
    return status;
}

Any suggestions?
0 Kudos

935 Views
mstumbra
Contributor II

Finally I get know, that Interrupts disabling and reenabling causes this problem

interruptMask = lpc3511IpState->registerBase->INTEN;

lpc3511IpState->registerBase->INTEN = 0;

...

lpc3511IpState->registerBase->INTEN = interruptMask;

If enable this code for single buffer configuration it will also cause same problem.

For now I tried to remove this lines, as single buffering scheme does not use it, and my code worked without EP stuck for 2 hours.

Question to NXP

  • For what purpose interrupt disabling added to double buffer scheme?
  • Why it is not used in single buffer scheme?
  • Why it leads to miss of input packet interrupt? In my understanding disabled interrupt means that bit in status register should be able to be set by HW by incoming packet and it will still generate interrupt immediatly after set of corresponding INTEN bit.
0 Kudos