35 votes

Android - Perte de données USB entrantes (haute vitesse)

Lors de l'utilisation d'Android, je suis à la perte de données sur une entrée d'USB de flux de données que je ne perds pas lors de la lecture du même appareil/stream dans Windows. (Je sais que Android n'est pas un système d'exploitation temps réel, mais ce n'est Windows, et Windows est ne pas avoir de problème de "keeping up" avec les données.)

J'ai des données à environ 3,5 MO/sec à l'aide d'un FTDI 2232H puce qui a un construit en 4K de mémoire tampon. Le bulk_transfer appels en libusb pouvez demander de 16K à un moment, Android doit retirer le contenu de la clé de tampon toutes les 4 ms ou plus.

J'ai essayé: écrit en Java et en C, en augmentant le fil (et/ou processus), la priorité la plus élevée, de synchronisation et de async routines, et j'ai même passer distincte de la mémoire tampon pour chaque USB lire donc je n'ai même pas à copier des données entre des lectures successives. (Il n'y a pas de collecte des ordures pendant le transfert). J'ai seulement besoin de tampon de 20 mo de données, il est donc tout à la RAM.

Encore, Android est "de ne pas se déplacer" à l'USB de données, parfois, attendre aussi longtemps que 12ms entre les lectures, provoquant un tas de perte de données.

Quelqu'un aurait-il des idées? DMA? Une sorte de "temps réel" demande au noyau?

5voto

Yimin Rong Points 568

J'ai rencontré ce genre de problème avant. Oubliez l'utilisation de Java, dans le fond, c'est de faire nombre incalculable de choses qui empêchent l'accès en temps réel, par exemple, collecte des ordures, le thread de traitement. Oubliez aussi l'aide de la programmation événementielle, même dans des threads de priorité élevée, il peut prendre un certain temps avant que l'événement est traité, et vous pouvez perdre des données.

La façon dont je le fixe, il était d'écrire "hostile" code! Utilisé C ou de l'assemblée, et a écrit un bureau de vote de la fonction comme ceci (C comme des pseudo-code):

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

Vous avez mentionné que vous essayé de C, alors il devrait être simple de convertir cette de fonctions réelles. Éviter la tentation d'utiliser les fonctions de confort, vous voulez aussi proche du métal que possible. E. g. si un O/S fonction Read() appelle à son tour read() qui appelle à son tour _read(), vous voulez être à l'aide de _read(). L'appareil sera beaucoup plus lent, tout ce qui se passe, mais c'est la contrepartie de l'accès en temps réel.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X