2010-07-27 9 views
6

Tenemos un sistema de hardware con algunos FPGA y un controlador USB FTDI. El hardware transmite datos a través de la transferencia masiva de USB a la PC a alrededor de 5MB/sy el software tiene la tarea de mantenerse sincronizado, verificar el CRC y escribir los datos en un archivo.Solucionando lagunas en los datos USB transmitidos

El chip FTDI tiene un pin 'ocupado' que sube mientras espera que la PC haga su trabajo. Hay una cantidad limitada de almacenamiento en búfer en el FTDI y en otras partes del hardware.

La línea ocupada va por un tiempo más largo de lo que el hardware puede almacenar (50-100ms) por lo que estamos perdiendo datos. Para evitar que tengamos que volver a diseñar el hardware, se me ha pedido que 'solucione' este problema.

Creo que mi código es lo suficientemente rápido, ya que hemos tenido que correr hasta 15 MB/s, por lo que deja un cuello de botella IO en alguna parte. ¿Estamos esperando demasiado de la PC/OS?

Aquí está mi punto de entrada de datos. Ocasionalmente obtenemos un bit o byte caído. Si la suma de comprobación no se computa, me desplazo hasta que lo haga. los datos de byte [] casi siempre son 4k.

void ftdi_OnData(byte[] data) 
    { 
     List<byte> buffer = new List<byte>(data.Length); 
     int index = 0; 

     while ((index + rawFile.Header.PacketLength + 1) < data.Length) 
     { 
      if (CheckSum.CRC16(data, index, rawFile.Header.PacketLength + 2)) // <- packet length + 2 for 16bit checksum 
      { 
       buffer.AddRange(data.SubArray<byte>(index, rawFile.Header.PacketLength));     
       index += rawFile.Header.PacketLength + 2; // <- skip the two checksums, we dont want to save them... 
      } 
      else 
      { 
       index++; // shift through 
      } 
     } 

     rawFile.AddData(buffer.ToArray(), 0, buffer.Count); 
    } 

Respuesta

4

Consejo: no escriba en un archivo .... cola.

Las computadoras modernas tienen múltiples procesadores. Si desea ciertas cosas lo más rápido posible, use múltiples procesadores.

  • Tenga en cuenta el problema con los datos USB, verifique las sumas de comprobación, etc. Pone en cola (SOLO) los resultados en una cola segura para la ejecución de subprocesos.
  • Otro subproceso lee datos de la cola y los escribe en un archivo, posiblemente almacenado en el búfer.

acabado;)

100ms es mucho tiempo para las operaciones decente. Logré gestionar con éxito alrededor de 250.000 paquetes de datos IO por segundo (datos financieros) utilizando C# sin ningún problema.

Básicamente, asegúrese de que sus hilos IO SÓLO hagan eso y utilice su memoria interna como buffer. Especialmente con el hardware en un extremo, el hilo que hace eso SÓLO debe hacer eso, POSIBLEMENTE si es necesario ejecutarse con alta prioridad.

+1

Supongo que una simple prueba sería encender el alcance, comentar la escritura en el archivo y darle una prueba! – Tim

+0

@Tim, esta es la respuesta. La calificación más importante es el requisito de "hilo seguro". Creará un mutex que se comparte entre los dos hilos, bloqueado cada vez que se escribe/lee en la cola. El truco aquí es que en el hilo de escritura de archivos, debe bloquear, copiar un fragmento de datos en un búfer local y luego desbloquearlo. No bloquee más de lo necesario o sus dos hilos no tendrán ninguna ventaja sobre un hilo. –

+1

En realidad yo uso NO mutx - use demasiado tiempo. Uso un Spinlock (nuevo con .net 4.0) porque mi código no tiene otra cosa que sacar algo de la cola o ponerlo;) En la parte superior, si creas nuevas memorias intermedias en cada elemento (como yo lo hago) realmente SOLO bloqueas en insertar/recuperar ... sin operación de copia. – TomTom

0

¿Cómo se ve el código de recepción? ¿Tiene un hilo ejecutándose con alta prioridad responsable únicamente por capturar los datos y pasarlos en la memoria a otro hilo de forma no bloqueante? ¿Ejecutas el proceso en sí mismo con una prioridad elevada?

¿Ha diseñado el resto de su código para evitar las colecciones de basura de segunda generación más costosas? ¿Qué tan grande son los buffers, están en el montón de objetos grandes? ¿Los vuelves a usar eficientemente?

+0

Estoy usando el evento 'datos recibidos' de la biblioteca FTDI. Llama a mi función y la pasa byte []. Suele ser siempre 4k ... Actualizaré la pregunta con un código ... – Tim

2

Para obtener un buen rendimiento de lectura en Windows en USB, generalmente necesita tener varias lecturas asincrónicas (o lecturas muy grandes, que a menudo son menos convenientes) en cola en la pila de dispositivos USB. No estoy muy seguro de qué hacen internamente los controladores/bibliotecas FTDI en este sentido.

Tradicionalmente, he escrito mecanismos con una matriz de strutures OVERLAPPED y una matriz de buffers, y los mantengo en ReadFile tan pronto como están libres. Estuve haciendo más de 40 lecturas de MB/s en USB2 hace unos 5-6 años, por lo que las computadoras modernas sin duda deberían ser capaces de hacer frente.

Es muy importante que usted (o sus controladores/bibliotecas) no entren en un ciclo de "iniciar una lectura, finalizar una lectura, tratar con los datos, iniciar otra lectura", porque encontrará que el bus está inactivo por vastas franjas de tiempo. Un analizador USB le mostraría si esto estaba sucediendo.

Estoy de acuerdo con los demás en que debe salir del hilo de que la lectura está sucediendo lo antes posible: no bloquee el controlador de eventos FTDI por más tiempo que en tomar el búfer en otra cola.

Me gustaría preasignar una cola circular de almacenamientos intermedios, elegir la siguiente libre y arrojar los datos recibidos en ella, luego completar el manejo del evento lo más rápido posible.

Toda esa suma de comprobación y concatenación con su asignación de memoria asistente, recolección de basura, etc., se puede hacer al otro lado de potencialmente 100s de MB de tiempo/espacio de búfer en la PC. Por el momento, puede estar pidiendo efectivamente a su FPGA/buffer de hardware que se adapte al tiempo que le toma hacer todo tipo de cosas pesadas de PC, lo que puede hacerse mucho más tarde.

Sin embargo, soy optimista: si realmente puedes almacenar en memoria intermedia 100ms de datos en el hardware, deberías poder hacer que esto funcione de manera confiable. Ojalá pudiera persuadir a todos mis clientes para que permitan tanto ...

+0

Tenemos aproximadamente 10 ms de memoria intermedia :-) – Tim

+0

Todavía creo que probablemente sobrepases los 10 ms, siempre y cuando no lo hagas detener al lector innecesariamente. ¿Dónde en el Reino Unido estás? –

Cuestiones relacionadas