lwIPDemo_Rowley_ARM7 – USB CDC send problem

Hello there, I’m working on a project based on the lwIPDemo_Rowley_ARM7 project. I needed to implement a CDC device which receives commands via USB and sends responses corresponding to the received commands. The basic functionality of the usbCDCTask() is still the same as in the original demo and basically data transfer works. But I noticed some strange behaviour recently: After a few  incoming requests (the EP1 FDR is read 30 times, most requests are somewhere between 64 and 128 bytes in length) and sending responses (the EP2 FDR is written 34 times), the next IN transfer does not take place. The 35th time the EP2 FDR is written and TXPTREADY is set, the data seems not to arrive at the host, although later the TXPKTREADY bit is cleared (which indicates, that the device received an IN token and all data was sent to the host). But in the usbSniff-Logs the package was nowhere to be found and the communication software on the host did not receive any response at all. Since the application on the microcontroller should only really send anything if a request was made, the communication between host and device hangs there. After a bit of experimenting I found out, that if I set TXPKTREADY in every iteration of the task loop after it was reset, the data will be sent eventually, but this seems like an ugly hack. Does anyone have an idea what the problem could be? The relevant part of the code from the USB task is the following:
if (eDriverState == eREADY_TO_SEND && ucControlLineState && eApplicationMode != eEMAC) {
            // All EPs have been set up and the ControlLineState is active.
            if (!(AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_2] & AT91C_UDP_TXPKTRDY)) {
                if (xSendQueueData.ulByteCount || xQueuePeek(xParserSendQueue, &xSendQueueData, 0)) {
                    /* There is no unsent buffered data & Got some bytes to transmit. */
                    vUsartPrintf("(send %p) ==============>>n", xSendQueueData.sBuffer);
                    for (ulByte = 0; ulByte < usbDATA_ENDPOINT_SIZE && xSendQueueData.ulByteCount; ulByte++) {
                        AT91C_BASE_UDP->UDP_FDR[usbEND_POINT_2] = *(xSendQueueData.sBuffer);
//                      if (xSendQueueData.xAddress != eAddrBinary) {
//                          vUsartPutChar(*(xSendQueueData.sBuffer));
//                      }
                        xSendQueueData.sBuffer++;
                        xSendQueueData.ulByteCount--;
                    }
//                  vUsartPutChar('n');
                    if (!xSendQueueData.ulByteCount) {
                        /* Packet completely transferred, remove item from queue and clear QueueData */
                        vUsartPuts("Packet completely transferredn");
                        xQueueReceive(xParserSendQueue, &xSendQueueData, 0);
                        xSendQueueData.sBuffer = 0;
                        xSendQueueData.ulByteCount = 0;
                    }
                }
                // For some reason the endpoint has to be marked ready anyway, if not a packet may not be transferred
                // at some point...
                AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_2] |= AT91C_UDP_TXPKTRDY;
            }

lwIPDemo_Rowley_ARM7 – USB CDC send problem

Sorry for the malformed code, here it is again, this time hopefully a bit more readable…
if (eDriverState == eREADY_TO_SEND && ucControlLineState && eApplicationMode != eEMAC) {
    // All EPs have been set up and the ControlLineState is active.
    if (!(AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_2] & AT91C_UDP_TXPKTRDY)) {
        if (xSendQueueData.ulByteCount || xQueuePeek(xParserSendQueue, &xSendQueueData, 0)) {
            /* There is no unsent buffered data & Got some bytes to transmit. */
            vUsartPrintf("(send %p) ==============>>n", xSendQueueData.sBuffer);
            for (ulByte = 0; ulByte < usbDATA_ENDPOINT_SIZE && xSendQueueData.ulByteCount; ulByte++) {
                AT91C_BASE_UDP->UDP_FDR[usbEND_POINT_2] = *(xSendQueueData.sBuffer);
//              if (xSendQueueData.xAddress != eAddrBinary) {
//                  vUsartPutChar(*(xSendQueueData.sBuffer));
//              }
                xSendQueueData.sBuffer++;
                xSendQueueData.ulByteCount--;
            }
//          vUsartPutChar('n');
            if (!xSendQueueData.ulByteCount) {
                /* Packet completely transferred, remove item from queue and clear QueueData */
                vUsartPuts("Packet completely transferredn");
                xQueueReceive(xParserSendQueue, &xSendQueueData, 0);
                xSendQueueData.sBuffer = 0;
                xSendQueueData.ulByteCount = 0;
            }
        }
        // For some reason the endpoint has to be marked ready anyway, if not a packet may not be transferred
        // at some point...
        AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_2] |= AT91C_UDP_TXPKTRDY;
    }
    ...
}

lwIPDemo_Rowley_ARM7 – USB CDC send problem

Just to clarify: the problem I described occurs when the last instruction
AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_2] |= AT91C_UDP_TXPKTRDY; 
is inside the if clause right before the last curly bracket. Like this:
                xSendQueueData.ulByteCount = 0;
            }
        AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_2] |= AT91C_UDP_TXPKTRDY;
        }
    }
    ...
}
The snipped I posted first actually works, but indicates available data even if there actually should be no data available because it should already have been transferred to the host…