Android - потеря входящей (высокоскоростной) USB-данных - PullRequest
34 голосов
/ 23 февраля 2012

При использовании Android я теряю данные на входящем потоке данных USB, которые не теряю при чтении того же устройства / потока в Windows.(Я знаю, что Android - это не ОС реального времени, но и Windows, и у Windows нет проблем с тем, чтобы не отставать от данных.)

Я получаю данные со скоростью около 3,5 МБ / сиспользуя чип FTDI 2232H, который имеет встроенный буфер 4K.Вызовы bulk_transfer в libusb могут запрашивать 16 Кбайт за раз, поэтому Android необходимо собирать содержимое буфера USB каждые 4 мс или около того.

Я пробовал: писать на Java и в C, поднимать поток (и / или процесс) приоритет по отношению к его наивысшей процедуре синхронизации и асинхронности, и я даже передаю отдельный буфер для каждого чтения USB, поэтому мне даже не нужно копировать данные между последовательными чтениями.(Во время передачи не происходит сборка мусора.) Мне нужно только буферизовать 20 МБ данных, поэтому все это в ОЗУ.

Тем не менее, Android «не находит» данные USB, иногда ожидаетдо 12 мс между чтениями, что приводит к потере данных.

У кого-нибудь есть идеи?DMA?Какой-то запрос в реальном времени к ядру?

1 Ответ

5 голосов
/ 26 января 2013

Я сталкивался с такой проблемой раньше. Забудьте об использовании Java, в фоновом режиме он делает неописуемое количество вещей, которые препятствуют доступу в реальном времени, например, сборка мусора, обработка резьбы. Также не забудьте использовать программирование, управляемое событиями, даже в потоках с высоким приоритетом, обработка события может занять много времени, и вы можете потерять данные.

То, как я исправил это, было написать «недружественный» код! Использовал C или сборку и написал такую ​​функцию опроса (в псевдокоде, подобном 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;
}

Вы упомянули, что пытались использовать C, поэтому преобразование этого в реальные функции должно быть простым. Избегайте соблазна использовать удобные функции, вы хотите максимально приблизиться к металлу. Например. если функция O / S Read() в свою очередь вызывает read(), которая в свою очередь вызывает _read(), вы хотите использовать _read(). Устройство будет работать заметно медленнее, но это компромисс в режиме реального времени.

...