使用Android时,我丢失了传入USB数据流的数据,在Windows中读取相同的设备/流时,我不会丢失这些数据。 (我知道Android不是一个实时操作系统,但Windows也不是,Windows也没有问题'跟上'数据。)
我使用内置4K缓冲区的FTDI 2232H芯片以大约3.5MB /秒的速度传输数据。 libusb中的bulk_transfer调用一次可以请求16K,因此Android需要每4ms左右收集一次USB缓冲区的内容。
我尝试过:用Java和C语言编写,将线程(和/或进程)优先级提高到最高,同步和异步例程,我甚至为每个USB读取传递一个单独的缓冲区,所以我甚至都没有必须在连续读取之间复制数据。 (在传输过程中没有垃圾收集。)我只需要缓冲20MB的数据,所以这都是RAM。
尽管如此,Android还没有“绕过”USB数据,有时候读取间隔时间长达12毫秒,导致大量数据丢失。
有没有人有任何想法? DMA?对内核有某种“实时”请求?
答案 0 :(得分:5)
我之前遇到过这种问题。忘记使用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()
。
在这种情况下,设备会明显变慢,但这是实时访问的权衡。