Подтвердить что ты не робот

Android - потеря USB-данных (hi-speed)

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

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

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

Тем не менее, Android не "обходит" данные USB, иногда дожидается до 12 мс между чтением, в результате чего теряется куча данных.

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

4b9b3361

Ответ 1

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

То, как я исправил это, было написать "недружественный" код! Использовал C или сборку и написал такую ​​функцию опроса (в псевдокоде C-like):

#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(). Устройство будет заметно медленнее, пока это происходит, но это компромисс в режиме реального времени.