3
\$\begingroup\$

I am implementing USB communications on a STM32F105, using ST's USB Library v2.1.0. It communicates as a CDC class Virtual COM Port ("VCP"). I'm using the embedded Full Speed PHY.

I've started with ST's VCP example project, which is a serial-to-USB converter. I have it working well except for one issue that I suspect may be a bug in their library code.

Their USB driver exposes a circular buffer and buffer pointer. The application is supposed to put data into this buffer, which gets noticed by the driver and is acted upon. Here is the function to populate the buffer:

uint16_t VCP_DataTx (uint8_t* Buf, uint32_t Len)
{
    uint32_t i;
    for (i=0; i<Len; i++)
    {
        APP_Rx_Buffer[APP_Rx_ptr_in] = Buf[i];
        APP_Rx_ptr_in++;

        /* To avoid buffer overflow */
        if(APP_Rx_ptr_in == APP_RX_DATA_SIZE)
        {
            APP_Rx_ptr_in = 0;
        }
    }
    return USBD_OK;
 }

This works to send up to (at least) 1024 bytes of data, except if the data length is an even multiple of 256 bytes. In other words, I can use this function to send 255 or 257 bytes just fine (or even 1023), but if I try to send 256 bytes it fails. Or 512, or 768, etc.

The failure mode is that no data is sent over USB until there has been a total of 4096 bytes passed into their buffer, and then it all gets transmitted at once. When it's working correctly, of course, the data gets transferred immediately.

There is a list of known bugs here. I've incorporated them, but it hasn't fixed this problem.

Does anyone know a solution? I would prefer not to debug ST's driver code...

\$\endgroup\$
  • \$\begingroup\$ I see that the original link to the list of known bugs died when ST changed their forum software. (It's amazing to think of how many links all over the internet must have been broken when they did that! :-( ). However, if you can remember what that list looked like, I think that I found the equivalent link on their new forum: community.st.com/message/59785 If that is the same information, then I'll leave it up to you to add it to your question however you want to do that :-) \$\endgroup\$ – SamGibson Sep 14 '17 at 20:44
  • 1
    \$\begingroup\$ Excellent, @SamGibson! That is, indeed, what I was talking about. I couldn't find it again after ST changed things. I've updated the question. Thanks a lot :) \$\endgroup\$ – bitsmack Sep 14 '17 at 20:50
10
\$\begingroup\$

except if the data length is an even multiple of 256 bytes

Its 64 bytes actually (MaxPacketSize). USB bulk transfers "end" with transfers that are not MaxPacketSize - normally 64 bytes long. If your transfer is an integer multiple of that, you send a zero packet after the data. This signals the transfer end to upper USB software stacks, which will return your data at once.

Most VCP example code omits this for simplicity.

\$\endgroup\$
  • \$\begingroup\$ Ah, excellent, thank you! That is exactly what I was looking for. \$\endgroup\$ – bitsmack May 15 '15 at 6:24
  • \$\begingroup\$ A quick follow-up question, if you don't mind: Is the zero packet creation generally implemented in the application layer or the CDC class layer? \$\endgroup\$ – bitsmack May 17 '15 at 5:59
  • 1
    \$\begingroup\$ @bitsmack I would suggest the CDC layer, your application should be transport agnostic, so it needing to know details of the lower layers is a bad smell. \$\endgroup\$ – Colin Jun 14 '17 at 19:39
  • \$\begingroup\$ @Colin__s Thanks for your suggestion! That's how I ended up doing it, for similar reasoning. Of course, if I update to a newer USB library I'll have to reassess (and possibly reapply) the fix... \$\endgroup\$ – bitsmack Jun 14 '17 at 20:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.