through - otg audio android
Android: pérdida de datos USB entrantes(de alta velocidad) (1)
Cuando uso Android, estoy perdiendo datos en una transmisión de datos USB entrante que no pierdo cuando leo el mismo dispositivo / transmisión en Windows. (Sé que Android no es un sistema operativo en tiempo real, pero tampoco lo es Windows, y Windows no tiene problemas para "mantenerse al día" con los datos).
Tengo datos a unos 3,5MB / seg con un chip FTDI 2232H que tiene un buffer 4K integrado. Las llamadas bulk_transfer en libusb pueden solicitar 16K a la vez, por lo que Android necesita recolectar el contenido del buffer USB cada 4ms o menos.
Lo he intentado: escribir en Java y en C, elevar la prioridad del subproceso (y / o proceso) a sus rutinas más altas, sincronizadas y asíncronas, e incluso paso un búfer por separado para cada lectura USB, así que ni siquiera tengo que copiar datos entre sucesivas lecturas. (No hay recogida de basura durante la transferencia). Solo necesito almacenar 20 MB de datos, por lo que todo depende de la memoria RAM.
Aún así, Android no está "pasando por alto" los datos USB, a veces esperando hasta 12 ms entre lecturas, lo que hace que se pierda un montón de datos.
¿Alguien tiene alguna idea? DMA? ¿Algún tipo de solicitud en "tiempo real" al kernel?
He encontrado este tipo de problema antes. Olvídese de usar Java, en el fondo está haciendo innumerables cosas que impiden el acceso en tiempo real, por ejemplo, recolección de basura, procesamiento de subprocesos. Olvídese también de utilizar la programación basada en eventos, incluso en subprocesos de alta prioridad, puede tomar mucho tiempo antes de que se procese el evento y puede perder datos.
La forma en que lo arreglé fue para escribir código "antipático". Usó C o ensamblaje, y escribió una función de sondeo como esta (en pseudocódigo tipo C):
#define PAUSE 2 /* Check twice as often as the packet rate */
#define TIMEOUT (500 / PAUSE) /* Abort if half a second of no data */
/* Provide handle, data buffer and size of buffer
Returns TRUE if full buffer read, FALSE if not, data unread in size
*/
BOOL real_time_read(HANDLE handle, BYTE *data, size_t *size)
{
BOOL result = FALSE;
int timeout = TIMEOUT;
set_thread_priority(REALTIME);
while (is_handle_valid(handle))
{
if (is_data_pending(handle))
{
size_t count = get_data(handle, data, size);
data += count;
*size -= count;
if (!*size)
{
result = TRUE;
break;
}
}
else if (!--timeout)
break;
/* Give a tiny time slice to other processes */
usleep(PAUSE);
}
return result;
}
Usted mencionó que probó C, por lo que debería ser sencillo convertir esto en funciones reales. Evite la tentación de utilizar funciones de conveniencia, lo más cerca posible del metal. Por ejemplo, si una función O / S Read()
a su vez llama a read()
que a su vez llama a _read()
, quiere usar _read()
. El dispositivo será notablemente más lento mientras esto sucede, pero esa es la compensación del acceso en tiempo real.