修改关联文件,双击打开安装崩溃。

This commit is contained in:
边瑞峰 2022-05-31 11:41:28 +08:00
parent 995e01e759
commit 9df31a7b37

View File

@ -16,6 +16,8 @@ from __future__ import print_function
import argparse import argparse
import collections import collections
import inspect import inspect
import json
import os
import re import re
import struct import struct
import sys import sys
@ -24,6 +26,17 @@ import zlib
import usb.core import usb.core
import usb.util import usb.util
import logging
import usb.backend.libusb1 as libusb1
import usb.backend.libusb0 as libusb0
import usb.backend.openusb as openusb
from usb.libloader import *
from PyQt5.QtWidgets import QMessageBox
_LOGGER = logging.getLogger(__name__)
# USB request __TIMEOUT # USB request __TIMEOUT
__TIMEOUT = 4000 __TIMEOUT = 4000
@ -116,11 +129,23 @@ def init(**kwargs):
devices = get_dfu_devices(**kwargs) devices = get_dfu_devices(**kwargs)
if not devices: if not devices:
raise ValueError("No DFU device found") raise ValueError("No DFU device found")
if len(devices) > 1: # if len(devices) > 1:
raise ValueError("Multiple DFU devices found") # raise ValueError("Multiple DFU devices found")
__dev = devices[0]
__dev.set_configuration()
for dev in devices:
try:
__dev = dev
dev.set_configuration()
break
except Exception as err:
print(err)
continue
# __dev = devices[1]
# print("__dev", __dev)
# __dev.set_configuration()
# __dev.get_active_configuration()
# print("__dev.set_configuration", __dev)
# Claim DFU interface # Claim DFU interface
usb.util.claim_interface(__dev, __DFU_INTERFACE) usb.util.claim_interface(__dev, __DFU_INTERFACE)
@ -437,14 +462,99 @@ class FilterDFU(object):
return intf.bInterfaceClass == 0xFE and intf.bInterfaceSubClass == 1 return intf.bInterfaceClass == 0xFE and intf.bInterfaceSubClass == 1
def _load_locate_library_ex(candidates, cygwin_lib, name,
win_cls=None, cygwin_cls=None, others_cls=None,
find_library=None):
"""Locates and loads a library.
Returns: the loaded library
arguments:
* candidates -- candidates list for locate_library()
* cygwin_lib -- name of the cygwin library
* name -- lib identifier (for logging). Defaults to None.
* win_cls -- class that is used to instantiate the library on
win32 platforms. Defaults to None (-> ctypes.CDLL).
* cygwin_cls -- library class for cygwin platforms.
Defaults to None (-> ctypes.CDLL).
* others_cls -- library class for all other platforms.
Defaults to None (-> ctypes.CDLL).
* find_library -- see locate_library(). Defaults to None.
raises:
* NoLibraryCandidatesException
* LibraryNotFoundException
* LibraryNotLoadedException
* LibraryMissingSymbolsException
"""
if sys.platform == 'cygwin':
if cygwin_lib:
loaded_lib = load_library(cygwin_lib, name, cygwin_cls)
else:
raise NoLibraryCandidatesException(name)
elif candidates:
lib = locate_library(candidates, find_library)
if lib:
if sys.platform == 'win32':
loaded_lib = load_library(lib, name, win_cls)
else:
loaded_lib = load_library(lib, name, others_cls)
_LOGGER.info('{}'.format(loaded_lib))
else:
_LOGGER.info('%r could not be found', (name or candidates))
raise LibraryNotFoundException(name)
else:
raise NoLibraryCandidatesException(name)
if loaded_lib is None:
raise LibraryNotLoadedException(name)
else:
return loaded_lib
def _load_library_ex(find_library=None):
return _load_locate_library_ex(
('usb-0.1', 'usb', 'libusb0'),
'cygusb0.dll', 'Libusb 0',
find_library=find_library
)
def _get_backend_ex():
try:
if libusb0._lib is None:
_LOGGER.info('_get_backend_ex(): using backend "%s"' % libusb0.__name__)
libusb0._lib = _load_library_ex()#find_library
libusb0._setup_prototypes(libusb0._lib)
libusb0._lib.usb_init()
return libusb0._LibUSB()
except usb.libloader.LibraryException:
# exception already logged (if any)
_LOGGER.error('Error loading libusb 0.1 backend')
return None
except Exception:
_LOGGER.error('Error loading libusb 0.1 backend')
return None
def my_get_backend_ex():
for m in (libusb1, openusb, libusb0):
backend = m.get_backend()
if backend is not None:
_LOGGER.info('my_get_backend_ex(): using backend "%s"' % m.__name__)
break
elif m == libusb0:
backend = _get_backend_ex()
if backend is not None: break
else:
raise ('No backend available')
return backend
def get_dfu_devices(*args, **kwargs): def get_dfu_devices(*args, **kwargs):
"""Returns a list of USB devices which are currently in DFU mode. """Returns a list of USB devices which are currently in DFU mode.
Additional filters (like idProduct and idVendor) can be passed in Additional filters (like idProduct and idVendor) can be passed in
to refine the search. to refine the search.
""" """
backend = my_get_backend_ex()
# Convert to list for compatibility with newer PyUSB # Convert to list for compatibility with newer PyUSB
return list(usb.core.find(*args, find_all=True, custom_match=FilterDFU(), **kwargs)) return list(usb.core.find(*args, find_all=True, backend=backend, custom_match=FilterDFU(), **kwargs))
def get_memory_layout(device): def get_memory_layout(device):
@ -568,12 +678,12 @@ def main():
# Parse CMD args # Parse CMD args
parser = argparse.ArgumentParser(description="DFU Python Util") parser = argparse.ArgumentParser(description="DFU Python Util")
parser.add_argument( parser.add_argument(
"-l", "--list", help="list available DFU devices", action="store_true", default=False "-l", "--list", help="list available DFU devices", action="store", default=False
) )
# parser.add_argument("--vid", help="USB Vendor ID", type=lambda x: int(x, 0), default=None) # parser.add_argument("--vid", help="USB Vendor ID", type=lambda x: int(x, 0), default=None)
# parser.add_argument("--pid", help="USB Product ID", type=lambda x: int(x, 0), default=None) # parser.add_argument("--pid", help="USB Product ID", type=lambda x: int(x, 0), default=None)
parser.add_argument( parser.add_argument(
"-m", "--mass-erase", help="mass erase device", action="store_true", default=False "-m", "--mass-erase", help="mass erase device", action="store", default=False
) )
# parser.add_argument( # parser.add_argument(
# "-u", "--upload", help="read file from DFU device", dest="path", default=False # "-u", "--upload", help="read file from DFU device", dest="path", default=False
@ -589,9 +699,9 @@ def main():
default="C:\\Users\\User\\Downloads\\stm32loader-master\\max.dfu" default="C:\\Users\\User\\Downloads\\stm32loader-master\\max.dfu"
) )
parser.add_argument("-x", "--exit", help="Exit DFU", action="store_true", default=False) parser.add_argument("-x", "--exit", help="Exit DFU", action="store", default=False)
parser.add_argument( parser.add_argument(
"-v", "--verbose", help="increase output verbosity", action="store_true", default=False "-v", "--verbose", help="increase output verbosity", action="store", default=False
) )
args = parser.parse_args() args = parser.parse_args()
@ -842,11 +952,17 @@ class STM32Dev(ispBase.IspBase, QSerialPort):
class DFUTool(QThread): class DFUTool(QThread):
print("DFUTool(QThread)")
stateCallback = pyqtSignal([str], [Exception]) stateCallback = pyqtSignal([str], [Exception])
progressCallback = pyqtSignal(int, int) progressCallback = pyqtSignal(int, int)
def is_valid_file(self, parser, arg):
if not os.path.exists(arg):
parser.error("The file %s does not exist!" % arg)
else:
return open(arg, 'r') # return an open file handle
def __init__(self, parent, port, speed, filename, callback=None): def __init__(self, parent, port, speed, filename, callback=None):
super(DFUTool, self).__init__() super(DFUTool, self).__init__()
self.parent = parent self.parent = parent
@ -856,65 +972,26 @@ class DFUTool(QThread):
self.callback = callback self.callback = callback
self.isWork = False self.isWork = False
self.finished.connect(self.done) self.finished.connect(self.done)
print("__init__")
global __verbose global __verbose
# Parse CMD args
parser = argparse.ArgumentParser(description="DFU Python Util")
parser.add_argument(
"-l", "--list", help="list available DFU devices", action="store_true", default=False
)
# parser.add_argument("--vid", help="USB Vendor ID", type=lambda x: int(x, 0), default=None)
# parser.add_argument("--pid", help="USB Product ID", type=lambda x: int(x, 0), default=None)
parser.add_argument(
"-m", "--mass-erase", help="mass erase device", action="store_true", default=False
)
# parser.add_argument(
# "-u", "--upload", help="read file from DFU device", dest="path", default=False
# )
parser.add_argument("--vid", help="USB Vendor ID", type=lambda x: int(x, 0), default=0x0483) __verbose = False
parser.add_argument("--pid", help="USB Product ID", type=lambda x: int(x, 0), default=0xdf11)
# parser.add_argument(
# "-u", "--upload", help="read file from DFU device", dest="path", default="C:\\Users\\User\\Documents\\stm32-test\\board-STM32F103-Mini\\usbdfu.bin"
# )
parser.add_argument(
"-u", "--upload", help="read file from DFU device", dest="path",
default=self.filename
)
parser.add_argument("-x", "--exit", help="Exit DFU", action="store_true", default=False) kwargs = {"idVendor": 0x0483, "idProduct": 0xdf11}
parser.add_argument(
"-v", "--verbose", help="increase output verbosity", action="store_true", default=False
)
self.args = parser.parse_args()
__verbose = self.args.verbose
kwargs = {}
if self.args.vid:
kwargs["idVendor"] = self.args.vid
if self.args.pid:
kwargs["idProduct"] = self.args.pid
def w(state): def w(state):
if state is False: if state is False:
print("未找到DFU")
self.stateCallback[Exception].emit(portError(portError.errorOpen, port)) self.stateCallback[Exception].emit(portError(portError.errorOpen, port))
self.stateCallback[str].emit("Done!") self.stateCallback[str].emit("Done!")
self.quit() self.quit()
return return
try: try:
print("找到DFU")
self.thread.exit() self.thread.exit()
init(**kwargs) init(**kwargs)
self.start() self.start()
except Exception as err: except Exception as err:
print("----------------------------======================")
print(err) print(err)
print(1)
self.thread = DFUSearch(self, kwargs=kwargs) self.thread = DFUSearch(self, kwargs=kwargs)
self.thread.searchResults.connect(w) # 异步完成后执行函数w self.thread.searchResults.connect(w) # 异步完成后执行函数w
@ -930,15 +1007,14 @@ class DFUTool(QThread):
print("QMetaObject_Connection") print("QMetaObject_Connection")
def run(self): def run(self):
print("run")
self.isWork = True self.isWork = True
try: try:
print("try")
with open(self.args.path, "rb") as fin: with open(self.filename, "rb") as fin:
dfu_file = fin.read() dfu_file = fin.read()
if dfu_file is None: if dfu_file is None:
print("file is None")
return return
elem = {"addr": 134217728, "size": len(dfu_file), "data": dfu_file} elem = {"addr": 134217728, "size": len(dfu_file), "data": dfu_file}
@ -950,10 +1026,11 @@ class DFUTool(QThread):
else: else:
self.stateCallback[str].emit(self.tr("Programming...")) self.stateCallback[str].emit(self.tr("Programming..."))
write_elements([elem], self.args.mass_erase, progress=self.cl_progress) write_elements([elem], False, progress=self.cl_progress)
exit_dfu() # 退出DFU模式 exit_dfu() # 退出DFU模式
print("exit_dfu")
except Exception as err: except Exception as err:
print(err)
if self.isInterruptionRequested(): if self.isInterruptionRequested():
print("int") print("int")
else: else:
@ -971,7 +1048,7 @@ class DFUTool(QThread):
return True return True
def done(self): def done(self):
print("结束烧录程序")
if self.parent is not None: if self.parent is not None:
if self.isWork: if self.isWork:
self.isWork = False self.isWork = False
@ -1001,14 +1078,12 @@ class DFUSearch(QThread):
def run(self): def run(self):
# 耗时内容 # 耗时内容
print("self.kwargs", self.kwargs)
devices = get_dfu_devices(**self.kwargs) devices = get_dfu_devices(**self.kwargs)
# Waiting 2 seconds before trying again..." # Waiting 2 seconds before trying again..."
attempts = 0 attempts = 0
while not devices: while not devices:
devices = get_dfu_devices(**self.kwargs) devices = get_dfu_devices(**self.kwargs)
attempts += 1 attempts += 1
print("搜索DFU设备", attempts)
if attempts > 20: if attempts > 20:
self.searchResults.emit(False) self.searchResults.emit(False)
self.quit() self.quit()