ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python – USB – sync vs async vs semi-async

2019-07-10 12:07:15  阅读:242  来源: 互联网

标签:python ctypes usb libusb


更新:

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

事实证明速度问题是由于Python的GIL造成的.有一种方法可以微调其行为.
sys.setcheckinterval(间隔)

将间隔设置为零(默认值为100)可以解决慢速问题.现在剩下的就是找出造成另一个问题的原因(并非所有像素都被填充).这个没有任何意义. usbmon显示所有通信正在进行中. libusb的调试消息传递没有任何异常.我想我需要拿usbmon的输出并比较同步和异步. usbmon显示的数据看起来似乎一目了然(第一个字节应该是0x96或0x95).

如下面原始问题中所述,S.Lott,它适用于USB LCD控制器. drv_send有三种不同版本,即传出端点方法.我已经解释了下面的差异.如果我概述异步USB操作,它可能会有所帮助.请注意,同步USB操作的工作方式相同,只是它是同步完成的.

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

>分配:分配一个libusb_transfer(这是self.transfer)
>填充:使用有关您希望执行的传输的信息填充libusb_transfer实例(libusb_fill_bulk_transfer)
>提交:请libusb提交转移(libusb_submit_transfer)
>完成处理:检查libusb_transfer结构中的传输结果(libusb_handle_events和libusb_handle_events_timeout)
>解除分配:清理资源(下面未显示)

原始问题:

我有三个不同的版本.一个是完全同步的,一个是半异步的,最后一个是完全异步的.不同之处在于同步完全填充了我用预期像素控制的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

这是半异步版本:

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)
        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

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

这是完全异步版本. device_poll本身就是一个线程.

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

解决方法:

好的,我不知道我是否帮助你.你有一些带LCD的设备,你有一些固件来处理USB请求.在PC端你正在使用PyUSB包装libUsb.

如果您正在尝试速度问题,请尝试限制您正在转移的数据.不要传输整个原始数据,只能传输更改的像素.

第二,你有没有通过使用一些USB分析软件测量转移的速度,如果你没有钱硬盘usb分析仪可能尝试软件版本.我从未使用过那种分析仪,但我认为它们提供的数据并不是很可靠.

第三,看看哪些设备真的在做,也许这是你的数据传输的瓶颈.

我今天没有多少时间准确地回答你的问题,所以我稍后会再回过头来.

我正在看这个帖子已经有一段时间了,周围有一个死寂,所以我试着节省一些时间,看看更深.今天也许今天晚些时候还没多久.不幸的是,我不是python专家,但我知道一些关于C,C,Windows和大多数USB的东西.但我认为这可能是LCD设备问题,您使用的是什么,因为如果传输工作正常,并且数据被设备接收,则指出这是设备问题.

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

端点大小是PICO LCD USB控制器使用的Hardvare缓冲区的大小.我不确定它对你来说是什么,但我猜测当你发送ENdpoint大小消息时,下一次masage应该是0字节长度.也许有问题.
关于测试,我假设您已经看过编程发送的数据.
第二件事可能是数据被覆盖,或者没有足够快地恢复.说覆盖我的意思是LCD无法看到数据结束,并将一次传输与另一次传输混合.

我不确定USB mon能够显示什么,但根据USB标准在端点大小包len之后,应该有0个len数据包发送,表明这是传输结束.

标签:python,ctypes,usb,libusb
来源: https://codeday.me/bug/20190710/1423824.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有