From 494ae3e27ee0cd8e9b3ef21fcdce96108b49ba02 Mon Sep 17 00:00:00 2001 From: Nemanja Stojoski Date: Wed, 18 Jun 2025 22:31:28 +0200 Subject: [PATCH] [GS] Fix UF2 Upload This fixes a couple of issues with the UF2 upload scripts. --- ground_station/dfu_reboot.py | 42 +++++++++++++++++---------------- ground_station/platformio.ini | 4 ++-- ground_station/uf2_loader.py | 23 +++++++++++------- ground_station/upload_script.py | 12 ++++++---- 4 files changed, 46 insertions(+), 35 deletions(-) diff --git a/ground_station/dfu_reboot.py b/ground_station/dfu_reboot.py index d8bee169..dafeeba0 100644 --- a/ground_station/dfu_reboot.py +++ b/ground_station/dfu_reboot.py @@ -21,26 +21,28 @@ class DFU_Reboot: def __init__(self): - pass + self.backend = usb.backend.libusb1.get_backend() + if self.backend is None: + print("Warning: libusb backend not found; falling back to PyUSB default") + self.backend = None - def listDeviced(self): + def listDevices(self): deviceList = [] - busses = usb.busses() - for bus in busses: - devices = bus.devices - for dev in devices: - if dev != None: - try: - deviceInfo = {"dev":dev.dev, - "vid":dev.idVendor, - "pid":dev.idProduct, - "ser":dev.dev.serial_number, - "manufacturer":dev.dev.manufacturer, - "product":dev.dev.product} - deviceList.append(deviceInfo) - except: - pass - deviceList = sorted(deviceList, key=lambda x: x['ser']) # Sort list by increasing Serial number + devices = usb.core.find(find_all=True, backend=self.backend) + for dev in devices or []: + try: + deviceInfo = { + "dev": dev, + "vid": dev.idVendor, + "pid": dev.idProduct, + "ser": getattr(dev, "serial_number", None), + "manufacturer": getattr(dev, "manufacturer", None), + "product": getattr(dev, "product", None), + } + deviceList.append(deviceInfo) + except Exception: + pass + deviceList.sort(key=lambda x: x["ser"] or "") return deviceList def reboot(self, devices): @@ -68,6 +70,6 @@ def reboot(self, devices): if __name__ == "__main__": dfu = DFU_Reboot() - devices = dfu.listDeviced() - print(devices) + devices = dfu.listDevices() + print(f"devices: {devices}") # print(dfu.reboot(devices)) diff --git a/ground_station/platformio.ini b/ground_station/platformio.ini index 46a56b72..d8523dff 100644 --- a/ground_station/platformio.ini +++ b/ground_station/platformio.ini @@ -88,8 +88,8 @@ extra_scripts = upload_protocol = custom upload_flags = ${env:ground_station.build_flags} ; Pass build flags as argument to python script - COMPARE_SERIAL_NUMBER=false ; Download only to devices with specified USB Serial Number, otherwise to all connected devices - USE_SERIAL_NUMBER_LIST=false ; Overwrite single USB Serial Number (USB_SERIAL) with list of accepted Serial Numbers + COMPARE_SERIAL_NUMBER=true ; Download only to devices with specified USB Serial Number, otherwise to all connected devices + USE_SERIAL_NUMBER_LIST=true ; Overwrite single USB Serial Number (USB_SERIAL) with list of accepted Serial Numbers SERIAL_NUMBER_LIST=["0", "1", "2"] ; List of specific USB Serial Numbers to program and open COM-Port (if enabled) ENABLE_AUTOMATIC_CONSOLE=false ; Enables automatic opening of serial ports COMPARE_VID_PID_CONSOLE=true ; Open only COM-Ports with same VID/PID as specified above (USB_VID, USB_PID) diff --git a/ground_station/uf2_loader.py b/ground_station/uf2_loader.py index 71389ec1..d183dae2 100644 --- a/ground_station/uf2_loader.py +++ b/ground_station/uf2_loader.py @@ -32,7 +32,7 @@ def __init__(self, family ="ESP32S2", startAddr=0): self.UF2_MAGIC_END = 0x0AB16F30 # Ditto self.SEARCH_PATH = "esp32-firmware-update/*.bin" - self.INFO_FILE = "/INFO_UF2.TXT" + self.INFO_FILE = "INFO_UF2.TXT" self.appstartaddr = startAddr self.familyid = 0x0 @@ -185,13 +185,18 @@ def to_str(self, b): def get_drives(self): drives = [] if sys.platform == "win32": - r = subprocess.check_output(["wmic", "PATH", "Win32_LogicalDisk", - "get", "DeviceID,", "VolumeName,", - "FileSystem,", "DriveType"]) - for line in self.to_str(r).split('\n'): - words = re.split('\s+', line) - if len(words) >= 3 and words[1] == "2" and words[2] == "FAT": - drives.append(words[0]) + try: + r = subprocess.check_output( + ["wmic", "logicaldisk", "get", "DeviceID,FileSystem,DriveType"], + universal_newlines=True + ) + for line in r.splitlines(): + if "FAT" in line and "2" in line: + match = re.match(r"^\s*([A-Z]:)", line) + if match: + drives.append(match.group(1) + "\\") + except Exception as e: + print("WMIC drive check failed:", e) else: rootpath = "/media" if sys.platform == "darwin": @@ -206,7 +211,7 @@ def get_drives(self): def has_info(d): try: - return os.path.isfile(d + self.INFO_FILE) + return os.path.isfile(os.path.join(d, self.INFO_FILE)) except: return False diff --git a/ground_station/upload_script.py b/ground_station/upload_script.py index 62650528..9fabb699 100644 --- a/ground_station/upload_script.py +++ b/ground_station/upload_script.py @@ -16,7 +16,6 @@ import ast import time -import glob import shutil import subprocess from packet_installer import installPackages @@ -85,11 +84,16 @@ def getParameterString(keyword): availableDrives = loader.get_drives() if not availableDrives: - devices = dfu.listDeviced() + devices = dfu.listDevices() + filtered_devices = [] for d in devices: - if(d['ser'] == "0000000000000001"): - devices.remove(d) + if d['ser'] == "0000000000000001": print("Removed fake device: ['0000000000000001']") + elif d['ser'] is None: + print("Removed 'None' device") + else: + filtered_devices.append(d) + devices = filtered_devices if not devices: return ['No devices found for entering bootloader, check if "libusb-win32" driver has been installed for "TinyUSB DFU_RT (Interface 1)"'] if(compare_Serial):