ardupilot/libraries/AP_HAL_F4Light/support/tools/dfuse-tool.py

149 lines
5.8 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
import dfuse
import usb.core
import usb.util
import argparse
import sys
def find_device(args):
usbdev = usb.core.find(idVendor=args.vid, idProduct=args.pid)
if usbdev is not None:
dfu = dfuse.DfuDevice(usbdev)
for _,alt in dfu.alternates():
if alt.configuration == args.cfg and alt.bInterfaceNumber == args.intf and alt.bAlternateSetting == args.alt:
dfu.set_alternate(alt)
status = dfu.get_status()
if status[1] == dfuse.DfuState.DFU_ERROR:
print("Error cleared: %r" % (status,))
dfu.clear_status() # Clear left-over errors
return dfu
raise ValueError('No DfuSe compatible device found, check device information options (see --help)')
def list_dfu(args):
usbdev = usb.core.find(idVendor=args.vid, idProduct=args.pid)
if usbdev is None:
raise ValueError('No STM32 DfuSe device found.')
dfu = dfuse.DfuDevice(usbdev)
for name, alt in dfu.alternates():
print ("Device: [%.4x:%.4x] Cfg: %d Intf: %d Alt: %d '%s'" % ( \
alt.device.idVendor, \
alt.device.idProduct, \
alt.configuration, \
alt.bInterfaceNumber, \
alt.bAlternateSetting, \
name))
def leave_dfu(args):
dfu = find_device(args)
dfu.leave()
status = dfu.get_status()
if status[0] > 0:
raise RuntimeError("An error occured. Status: %r" % status)
def erase(args):
dfu = find_device(args)
print ("Erasing. Please wait this might be long ...")
dfu.erase(args.erase)
status = dfu.wait_while_state(dfuse.DfuState.DFU_DOWNLOAD_BUSY)
if status[1] != dfuse.DfuState.DFU_DOWNLOAD_IDLE:
raise RuntimeError("An error occured. Device Status: %r" % status)
print ("Done !")
def flash(args):
dfufile = args.flash[0]
dfu = find_device(args)
if (dfufile.devInfo['vid'] != dfu.dev.idVendor or dfufile.devInfo['pid'] != dfu.dev.idProduct) and not args.force:
raise ValueError("Vendor/Product id mismatch: [%.4x:%.4x] (file) [%.4x:%.4x] (device). Trying running with --force" % ( \
dfufile.devInfo['vid'], \
dfufile.devInfo['vid'], \
dfu.dev.idVendor, \
dfu.dev.idProduct))
targets = [t for t in dfufile.targets if t['alternate'] == dfu.intf.bAlternateSetting]
if len(targets) == 0:
raise ValueError("No file target matches the device. Check the --alt setting")
print ("Flashing. Please wait this might be long ...")
for t in targets:
print ("Found target %r" % t['name'])
for idx, image in enumerate(t['elements']):
print("Flashing image %d at 0x%.8X" % (idx, image['address']))
print("Erasing ...")
dfu.erase(image['address'])
status = dfu.wait_while_state(dfuse.DfuState.DFU_DOWNLOAD_BUSY)
if status[1] != dfuse.DfuState.DFU_DOWNLOAD_IDLE:
raise RuntimeError("An error occured. Device Status: %r" % status)
print("Flashing ...")
transfer_size = 1024
dfu.set_address(image['address'])
status = dfu.wait_while_state(dfuse.DfuState.DFU_DOWNLOAD_BUSY)
if status[1] != dfuse.DfuState.DFU_DOWNLOAD_IDLE:
raise RuntimeError("An error occured. Device Status: %r" % status)
data = image['data']
blocks = [data[i:i + transfer_size] for i in range(0, len(data), transfer_size)]
for blocknum, block in enumerate(blocks):
print("Flashing block %r" % blocknum)
dfu.write(blocknum, block)
status = dfu.wait_while_state(dfuse.DfuState.DFU_DOWNLOAD_BUSY)
if status[1] != dfuse.DfuState.DFU_DOWNLOAD_IDLE:
raise RuntimeError("An error occured. Device Status: %r" % status)
print("Done")
return
status = dfu.wait_while_state(dfuse.DfuState.DFU_DOWNLOAD_BUSY)
if status[1] != dfuse.DfuState.DFU_IDLE and status[1] != dfuse.DfuState.DFU_DOWNLOAD_IDLE:
raise RuntimeError("An error occured. Status: %r" % status)
print ("Done !")
parser = argparse.ArgumentParser(description="DfuSe flashing util for STM32")
action = parser.add_mutually_exclusive_group(required = True)
action.add_argument('--list', action='store_true', help='List available DfuSe interfaces')
action.add_argument('--leave', action='store_true', help='Leave DFU mode')
action.add_argument('--flash', nargs=1, action='store', help='Flash a DfuSe file', metavar='FILE', type=dfuse.DfuFile)
action.add_argument('--erase', action='store', help='Erase page at ADDRESS (must be page aligned)', metavar=('ADDRESS'), type=int)
devinfo = parser.add_argument_group('Device information')
devinfo.add_argument('--vid', action='store', type=int, default=0x0483, help='Device\'s USB vendor id, defaults to 0x0483')
devinfo.add_argument('--pid', action='store', type=int, default=0xdf11, help='Device\'s USB product id, defaults to 0xdf11')
devinfo.add_argument('--cfg', action='store', type=int, default=0, help='Device\'s configuration number, default to 0')
devinfo.add_argument('--intf', action='store', type=int, default=0, help='Device\'s interface number, defaults to 0')
devinfo.add_argument('--alt', action='store', type=int, default=0, help='Device\'s alternate setting number, defaults to 0')
others = parser.add_argument_group('Other Options')
others.add_argument('--force', '-f', action='store_true', help='Bypass sanity checks')
args = parser.parse_args()
#try:
if args.list:
list_dfu(args)
elif args.leave:
leave_dfu(args)
elif args.erase is not None:
erase(args)
elif args.flash is not None:
flash(args)
#except Exception as e:
# print(e, file=sys.stderr)
# sys.exit(-1)