USB同步vs异步vs semiasyn

2024-05-16 12:19:34 发布

您现在位置:Python中文网/ 问答频道 /正文

更新:

我写了一个异步C版本,它可以正常工作。在

原来速度问题是由于Python的GIL造成的。有一种方法可以微调它的行为。 系统设置检查间隔(间隔)

将“间隔”设置为零(默认值为100)可修复低速问题。现在剩下的就是找出是什么导致了另一个问题(不是所有像素都被填充)。这个没有任何意义。usbmon显示所有通讯都通过了。libusb的调试消息没有任何异常。我想我需要获取usbmon的输出并比较sync和async。usbmon显示的数据乍一看似乎是正确的(第一个字节应该是0x96或0x95)。在

正如下面第一个问题,S.Lott所说,这是一个USB液晶控制器。有三种不同版本的drv_send,即传出端点方法。我已经解释了下面的区别。如果我概述一下异步USB操作可能会有帮助。请注意,同步USB操作的工作方式是相同的,只是同步进行。在

我们可以将异步I/O视为一个5步过程:

  1. 分配:分配一个libusb_传输(这是自我转移)在
  2. 填充:使用要执行的传输的相关信息填充libusb_transfer实例(libusb_fill_bulk_transfer)
  3. 提交:要求libusb提交传输(libusb_submit_transfer)
  4. 完成处理:检查libusb_传输结构中的传输结果(libusb_handle_events和libusb_handle_events_timeout)
  5. 释放:清理资源(未在下面显示)

原题:

我有三个不同的版本。一个是完全同步的,一个是半异步的,最后一个是完全异步的。不同之处在于,synchronous用预期的像素完全填充了我控制的LCD显示屏,而且速度非常快。半异步版本只填充显示的一部分,,但它仍然非常快。异步版本的速度非常慢,只占显示的一部分。我很困惑为什么像素没有完全填充,以及为什么异步版本非常慢。有什么线索吗?在

这是完全同步的版本:

def drv_send(self, data):
    if not self.Connected():
        return

    self.drv_locked = True
    buffer = ''
    for c in data:
        buffer = buffer + chr(c)
    length = len(buffer)
    out_buffer = cast(buffer, POINTER(c_ubyte))
    libusb_fill_bulk_transfer(self.transfer, self.handle, LIBUSB_ENDPOINT_OUT + 1, out_buffer, length, self.cb_send_transfer, None, 0)
    lib.libusb_submit_transfer(self.transfer)
    while self.drv_locked:
        r = lib.libusb_handle_events(None)
        if r < 0:
            if r == LIBUSB_ERROR_INTERRUPTED:
                continue
            lib.libusb_cancel_transfer(transfer)
            while self.drv_locked:
                if lib.libusb_handle_events(None) < 0:
                    break

    self.count += 1

以下是半异步版本:

^{pr2}$

这是完全异步的版本。设备轮询本身在线程中。在

def device_poll(self):
    while self.Connected():
        tv = TIMEVAL(1, 0)
        r = lib.libusb_handle_events_timeout(None, byref(tv))
        if r < 0:
            break

def drv_send(self, data):
    if not self.Connected():
        return

    def f(d):
        self.drv_locked = True
        buffer = ''
        for c in data:
            buffer = buffer + chr(c)
        length = len(buffer)
        out_buffer = cast(buffer, POINTER(c_ubyte))
        libusb_fill_bulk_transfer(self.transfer, self.handle, LIBUSB_ENDPOINT_OUT + 1, out_buffer, length, self.cb_send_transfer, None, 0)
        lib.libusb_submit_transfer(self.transfer)
        self.count += 1

    self.command_queue.put(Command(f, data))

这里是排队的地方。它是gobject超时的回调。在

def command_worker(self):
    if self.drv_locked: # or time.time() - self.command_time < self.command_rate:
        return True
    try:
        tmp = self.command_queue.get_nowait()
    except Queue.Empty:
        return True
    tmp.func(*tmp.args)
    self.command_time = time.time()
    return True

这是传输回拨。它只是将锁定状态改回false,表示操作已完成。在

def cb_send_transfer(self, transfer):
    if transfer[0].status.value != LIBUSB_TRANSFER_COMPLETED:
        error("%s: transfer status %d" % (self.name, transfer.status))
    print "cb_send_transfer", self.count
    self.drv_locked = False

Tags: self版本sendiftimelibdefbuffer
1条回答
网友
1楼 · 发布于 2024-05-16 12:19:34

好吧,我不知道我是否理解你的意思。你有一些带LCD的设备,上面有一些固件来处理USB请求。在PC端,您使用的是包装libUsb的PyUSB。在

一些建议如果你正在经历速度问题,试着限制你正在传输的数据。不要传输整个原始数据,可能只传输改变的像素。在

第二,你有没有用一些USB分析仪软件测量传输速度,如果你没有钱买hardvare USB analyzer,可以试试软件版本。我从来没有用过这种分析仪,但我认为它们提供的数据不太可靠。在

第三,看看设备到底在做什么,也许这就是数据传输的瓶颈。在

我今天没有太多时间回答你的问题,所以我稍后再谈这个问题。在

我看这条线有一段时间了,周围一片死寂,所以我试着抽出一些时间来深入观察。今天时间不多也许今天晚些时候。不幸的是,我不是Python专家,但我知道一些关于C、C++、Windows和大多数USB的东西。但我认为这可能是液晶设备的问题,你在用什么,因为如果传输工作正常,数据被设备接收到,那就是设备问题。在

我看了一下你的代码,你能做些测试吗,只发送1个字节,8个字节,和端点大小的字节长度传输。看看它在USB mon上的样子?在

端点大小是PICO LCD USB控制器使用的硬件缓冲区的大小。我不知道这是什么为您的,但我猜测,当您发送端点大小的消息,下一个masage应该是0字节的长度。也许有问题。 关于测试,我想你已经看到了你编程发送的数据。 第二件事可能是数据被覆盖,或者接收速度不够快。我说overwriten是指液晶显示器看不到数据的结尾,并且混用了一个传输和另一个传输。在

我不确定usbmon能显示什么,但根据USB标准,在端点大小包len之后,应该有0 len的包数据发送,说明是传输结束。在

相关问题 更多 >