STM32 USB - ¿Transmisión retrasada cuando la longitud de la carga útil = 256 (o 512, o 768...) bytes?

Estoy implementando comunicaciones USB en un STM32F105, utilizando la Biblioteca USB v2.1.0 de ST . Se comunica como un puerto COM virtual de clase CDC ("VCP"). Estoy usando el PHY de velocidad completa integrado.

Comencé con el proyecto de ejemplo VCP de ST, que es un convertidor de serie a USB. Lo tengo funcionando bien, excepto por un problema que sospecho que puede ser un error en el código de su biblioteca.

Su controlador USB expone un búfer circular y un puntero de búfer. Se supone que la aplicación debe colocar datos en este búfer, lo cual es detectado por el controlador y se actúa en consecuencia. Aquí está la función para llenar el búfer:

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;
 }

Esto funciona para enviar hasta (al menos) 1024 bytes de datos, excepto si la longitud de los datos es un múltiplo par de 256 bytes. En otras palabras, puedo usar esta función para enviar 255 o 257 bytes muy bien (o incluso 1023), pero si intento enviar 256 bytes falla. O 512, o 768, etc.

El modo de falla es que no se envía ningún dato a través de USB hasta que haya pasado un total de 4096 bytes a su búfer, y luego todo se transmite a la vez. Cuando funciona correctamente, por supuesto, los datos se transfieren inmediatamente.

Hay una lista de errores conocidos aquí . Los he incorporado, pero no ha solucionado este problema.

¿Alguien sabe alguna solución? Preferiría no depurar el código del controlador de ST...

Veo que el enlace original a la lista de errores conocidos murió cuando ST cambió el software del foro. (¡Es increíble pensar cuántos enlaces en Internet se deben haber roto cuando hicieron eso! :-( ). Sin embargo, si puedes recordar cómo era esa lista, creo que encontré el enlace equivalente en su nuevo foro: community.st.com/message/59785 Si esa es la misma información, te dejaré que la agregues a tu pregunta como quieras :-)
¡Excelente, @SamGibson! Eso es, de hecho, de lo que estaba hablando. No pude volver a encontrarlo después de que ST cambiara las cosas. He actualizado la pregunta. Muchas gracias :)

Respuestas (1)

excepto si la longitud de los datos es un múltiplo par de 256 bytes

Son 64 bytes en realidad (MaxPacketSize). Las transferencias masivas USB "finalizan" con transferencias que no son MaxPacketSize, normalmente de 64 bytes de longitud. Si su transferencia es un múltiplo entero de eso, envía un paquete cero después de los datos. Esto señala el final de la transferencia a las pilas de software USB superiores, que devolverán sus datos de inmediato.

La mayoría del código de ejemplo de VCP omite esto por simplicidad.

¡Ah, excelente, gracias! Eso es exactamente lo que estaba buscando.
Una pregunta de seguimiento rápida, si no le importa: ¿la creación de paquetes cero generalmente se implementa en la capa de aplicación o en la capa de clase CDC?
@bitsmack, sugeriría la capa CDC, su aplicación debe ser independiente del transporte, por lo que la necesidad de conocer los detalles de las capas inferiores es un mal olor.
@Colin__s ¡Gracias por tu sugerencia! Así es como terminé haciéndolo, por un razonamiento similar. Por supuesto, si actualizo a una biblioteca USB más nueva, tendré que volver a evaluar (y posiblemente volver a aplicar) la solución...