Skip to content
Snippets Groups Projects
Commit 4f25a8b6 authored by Damien George's avatar Damien George
Browse files

tools/pydfu.py: Improve DFU reset, and auto-detect USB transfer size.

A DFU device must be in the idle state before it can be programmed, and
this requires either clearing the status or aborting, depending on its
current state.  Code is added to do this.  And the USB transfer size is now
automatically detected so devices with a size less than 2048 bytes work
correctly.
parent 5c34c2ff
No related branches found
No related tags found
No related merge requests found
...@@ -14,6 +14,7 @@ See document UM0391 for a dscription of the DFuse file. ...@@ -14,6 +14,7 @@ See document UM0391 for a dscription of the DFuse file.
from __future__ import print_function from __future__ import print_function
import argparse import argparse
import collections
import re import re
import struct import struct
import sys import sys
...@@ -56,6 +57,9 @@ _DFU_DESCRIPTOR_TYPE = 0x21 ...@@ -56,6 +57,9 @@ _DFU_DESCRIPTOR_TYPE = 0x21
# USB device handle # USB device handle
__dev = None __dev = None
# Configuration descriptor of the device
__cfg_descr = None
__verbose = None __verbose = None
# USB DFU interface # USB DFU interface
...@@ -76,9 +80,18 @@ else: ...@@ -76,9 +80,18 @@ else:
return usb.util.get_string(dev, index) return usb.util.get_string(dev, index)
def find_dfu_cfg_descr(descr):
if len(descr) == 9 and descr[0] == 9 and descr[1] == _DFU_DESCRIPTOR_TYPE:
nt = collections.namedtuple('CfgDescr',
['bLength', 'bDescriptorType', 'bmAttributes',
'wDetachTimeOut', 'wTransferSize', 'bcdDFUVersion'])
return nt(*struct.unpack('<BBBHHH', bytes(descr)))
return None
def init(): def init():
"""Initializes the found DFU device so that we can program it.""" """Initializes the found DFU device so that we can program it."""
global __dev global __dev, __cfg_descr
devices = get_dfu_devices(idVendor=__VID, idProduct=__PID) devices = get_dfu_devices(idVendor=__VID, idProduct=__PID)
if not devices: if not devices:
raise ValueError('No DFU device found') raise ValueError('No DFU device found')
...@@ -90,10 +103,34 @@ def init(): ...@@ -90,10 +103,34 @@ def init():
# Claim DFU interface # Claim DFU interface
usb.util.claim_interface(__dev, __DFU_INTERFACE) usb.util.claim_interface(__dev, __DFU_INTERFACE)
# Clear status # Find the DFU configuration descriptor, either in the device or interfaces
__cfg_descr = None
for cfg in __dev.configurations():
__cfg_descr = find_dfu_cfg_descr(cfg.extra_descriptors)
if __cfg_descr:
break
for itf in cfg.interfaces():
__cfg_descr = find_dfu_cfg_descr(itf.extra_descriptors)
if __cfg_descr:
break
# Get device into idle state
for attempt in range(4):
status = get_status()
if status == __DFU_STATE_DFU_IDLE:
break
elif (status == __DFU_STATE_DFU_DOWNLOAD_IDLE
or status == __DFU_STATE_DFU_UPLOAD_IDLE):
abort_request()
else:
clr_status() clr_status()
def abort_request():
"""Sends an abort request."""
__dev.ctrl_transfer(0x21, __DFU_ABORT, 0, __DFU_INTERFACE, None, __TIMEOUT)
def clr_status(): def clr_status():
"""Clears any error status (perhaps left over from a previous session).""" """Clears any error status (perhaps left over from a previous session)."""
__dev.ctrl_transfer(0x21, __DFU_CLRSTATUS, 0, __DFU_INTERFACE, __dev.ctrl_transfer(0x21, __DFU_CLRSTATUS, 0, __DFU_INTERFACE,
...@@ -180,9 +217,7 @@ def write_memory(addr, buf, progress=None, progress_addr=0, progress_size=0): ...@@ -180,9 +217,7 @@ def write_memory(addr, buf, progress=None, progress_addr=0, progress_size=0):
set_address(xfer_base+xfer_bytes) set_address(xfer_base+xfer_bytes)
# Send DNLOAD with fw data # Send DNLOAD with fw data
# the "2048" is the DFU transfer size supported by the ST DFU bootloader chunk = min(__cfg_descr.wTransferSize, xfer_total-xfer_bytes)
# TODO: this number should be extracted from the USB config descriptor
chunk = min(2048, xfer_total-xfer_bytes)
__dev.ctrl_transfer(0x21, __DFU_DNLOAD, 2, __DFU_INTERFACE, __dev.ctrl_transfer(0x21, __DFU_DNLOAD, 2, __DFU_INTERFACE,
buf[xfer_bytes:xfer_bytes + chunk], __TIMEOUT) buf[xfer_bytes:xfer_bytes + chunk], __TIMEOUT)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment