USB CDC: Ayuda con cero paquetes

6

Estoy tratando de entender la necesidad de paquetes Cero en las transmisiones USB-CDC. De lo que deduzco, esto parece tocar algunas áreas grises de la especificación USB o las diferencias en la implementación de los controladores USB del host. Estoy interesado tanto en el comportamiento "correcto" (según la especificación de USB) como en el comportamiento típico en lo que respecta a los hosts USB normales (Linux, Windows, OSX). Cualquier apreciación relevante sería apreciada.

  1. Un ejemplo hipotético de un dispositivo USB sería uno que se transmite a través de un único punto final de USB-CDC, simplemente generando y transmitiendo continuamente de forma infinita los bytes. Para este ejemplo, suponga que la generación de datos es considerablemente más lenta que la transmisión USB-CDC. El enfoque que me gustaría usar es recolectar 64 bytes de datos (tamaño del paquete del dispositivo), y cuando estén listos 64 bytes, transmita un solo paquete. Nunca se enviarán paquetes de cero, nunca se enviarán paquetes cortos. Cualquier sondeo iniciado por el host será NAK cuando no haya un paquete completo listo.

    1. ¿Es esta una forma válida de transmitir datos CDC?

    2. ¿Hay algún host USB que tenga problemas con este enfoque?

    3. Si el dispositivo USB es un dispositivo USB compuesto, y uno de los puntos finales proporcionados es un punto final de CDC como se describe, ¿hay algún cambio en las respuestas de a. y b.?

  2. En el dispositivo de 1., si, en lugar de enviar NAKs cuando no hay nada que enviar, el dispositivo debía enviar un paquete de 0, ¿es probable que aún funcione? ¿Cómo cambia la transmisión general, en términos de cómo la interpreta un emulador de puerto serie y / o el ancho de banda efectivo?

  3. Si el dispositivo, en cambio, transmite unos pocos bytes, espera una respuesta. La longitud de estos "pocos" bytes no se conoce a priori. El host debe poder recibir, procesar y responder a estos pocos bytes; no puede simplemente sentarse en un búfer de hardware / controlador a la espera de que termine toda la transmisión. Supongamos, por el momento, que el receptor USB-CDC por dispositivo funciona de alguna manera y es estable. Todo lo que me interesa es la transmisión de paquetes cero desde el dispositivo.

    1. Si el número de bytes a enviar no es un múltiplo de 64 bytes (tamaño del paquete), entonces simplemente terminar con el paquete 'corto' sería suficiente para marcar el final de la transmisión, ¿sí?

    2. Si el número de bytes que se enviará es un múltiplo de 64 (tamaño de paquete), ¿qué sucede si no se envía un paquete cero después del último paquete transmitido para marcar el final de la transmisión?

2 respuestas

6

Aparentemente, algunos controladores de dispositivos host, como en Windows, usan la indicación de que no tiene más datos inmediatamente para pasar los datos acumulados a la aplicación. Sin eso, Windows aparentemente almacena los datos y pasa a la aplicación solo cuando se alcanza algún límite (parece ser de 64 bytes, pero no está seguro).

El USB toma un paquete de entrada (recibido desde el dispositivo) inferior al completo como indicación de que no hay más datos inmediatos. Esto significa que si no tiene más datos y el paquete IN anterior llenó el búfer, entonces debe enviar un paquete de longitud 0 en respuesta al siguiente token IN. Usted pensaría que NACKing el siguiente token IN indica claramente que no tiene datos inmediatos, pero aparentemente eso no es correcto para USB.

Acabo de encontrarme con este problema de frente. He estado usando mi código PIC 18 USB por muchos años y más de una docena de proyectos sin problemas. Hasta ahora, he utilizado buffers de 64 bytes para los puntos finales de datos de la aplicación. Acabo de hacer otro dispositivo USB, pero esta vez usé un PIC 18 más pequeño donde no podía pagar los tres buffers de 64 bytes para cada punto final. Utilicé buffers de 16 bytes en su lugar.

Este PIC recibía información a través de una conexión en serie y luego la enviaba al host a través de USB. La comunicación a veces se paraliza. Esto se remonta a que sucedió después de que se enviara un paquete completo de 16 bytes, luego no hay más datos disponibles. Windows conservó los 16 bytes sin pasarlos a la aplicación.

Ocultamos temporalmente esto al hacer que la secuencia de datos en serie contenga comandos NULL de vez en cuando, cuando no ocurre nada más. Estos son sólo 1 byte de largo. Si ocurriera el caso anterior, Windows mantendría los 16 bytes. Luego, un paquete vendría en breve conteniendo solo el byte de comando NULL. Dado que no es un paquete completo, Windows considera que al final de los datos inmediatos y libera los 17 bytes acumulados a las aplicaciones.

Cuando regrese la próxima semana, arreglaré mi código PIC 18 USB para enviar un paquete vacío siempre que el paquete anterior esté lleno y no haya nada nuevo que enviar. Entonces se NACK subsiguiente en fichas. Actualmente, NACKs EN tokens siempre que no tenga nada inmediato para enviar.

Como todavía no he realizado el cambio, no puedo asegurar que este fue el problema y que la solución intencional lo soluciona. Sin embargo, la solución ocasional de comando NULL funcionó, y la especificación de USB parece estar de acuerdo en que debe enviar un paquete no completo siempre que no haya más datos inmediatos.

Todavía no entiendo por qué NACKing el siguiente token IN no transmite la misma información, pero aparentemente no lo hace.

Actualizar

Mientras tanto, he arreglado mi pila PIC 18 USB. Ahora envía un paquete de longitud cero si el paquete anterior era de longitud completa, y no hay nada disponible inmediatamente para enviar. Después de los paquetes que no son de longitud completa, que incluyen los paquetes deliberados de longitud cero, que no tienen nada que enviar de inmediato, los tokens de ENTRADA se NACKAN como antes. Creo que esto ahora está siguiendo la letra de la especificación USB. Un analizador USB muestra la secuencia correcta de paquetes según esta interpretación.

Se eliminó el kludge temporal de envío NULL mencionado anteriormente, y todo parece funcionar correctamente.

    
respondido por el Olin Lathrop
3

Así es como el control de flujo de datos se implementa históricamente en CDC. Esto viene del modelo de flujo de datos estándar para tuberías USB, consulte la Sección 5.3.2 "Tuberías" de las Especificaciones de USB 2.0:

"Un cliente de software normalmente solicita transferencias de datos a través de paquetes de solicitud de E / S (IRP) a una canalización y luego espera o recibe una notificación cuando se completan.

[recorte]

Un IRP puede requerir varias cargas útiles de datos para mover los datos del cliente a través del bus. Se espera que las cargas útiles de datos para tal IRP de carga múltiple de datos sean del tamaño máximo de paquete hasta la última carga útil de datos que contenga el resto del IRP general. Vea la descripción de cada tipo de transferencia para más detalles. Para un IRP de este tipo, los paquetes cortos (es decir, menos de las cargas útiles de datos de tamaño máximo) en la entrada que no llenan completamente un búfer de datos de IRP pueden tener uno de los dos significados posibles, dependiendo de las expectativas de un cliente:

• Un cliente puede esperar una cantidad de datos de tamaño variable en un IRP. En este caso, un paquete corto que no llena un búfer de datos IRP se puede usar simplemente como un delimitador dentro de banda para indicar "fin de la unidad de datos". El IRP debe retirarse sin error y el Controlador del host debe avanzar al siguiente IRP.

• Un cliente puede esperar una cantidad de datos de tamaño específico. En este caso, un paquete corto que no llena un búfer de datos IRP es una indicación de un error. El IRP debe retirarse, la tubería debe estar bloqueada y cualquier IRP pendiente asociado con la tubería también debe retirarse.

Debido a que el controlador de host debe comportarse de manera diferente en los dos casos y no puede saber por sí mismo cuál es el modo de comportarse para un IRP determinado; es posible indicar por IRP qué comportamiento desea el cliente.

Un punto final puede informar al host que está ocupado respondiendo con NAK. Los NAK no se utilizan como condición de retiro para devolver un IRP a un cliente de software. Se puede encontrar cualquier número de NAK durante el procesamiento de un IRP determinado. Una respuesta NAK a una transacción no constituye un error y no se cuenta como uno de los tres errores descritos anteriormente. "

    
respondido por el Ale..chenski

Lea otras preguntas en las etiquetas