Skip to content

Commit

Permalink
Merge pull request #101 from antoinevg/antoinevg/fix-windows-libusb1
Browse files Browse the repository at this point in the history
On Windows, create the libusb1 backend explicitly by specifying the installed location of libusb-1.0.dll
  • Loading branch information
mossmann authored Jul 9, 2024
2 parents 3a0e3a2 + f1fb923 commit 87e0fe7
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 12 deletions.
27 changes: 23 additions & 4 deletions apollo_fpga/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def __init__(self, force_offline=False):
device = self._find_device(self.APOLLO_USB_IDS, custom_match=self._device_has_apollo_id)

# If Apollo VID/PID is not found, try to find a gateware VID/PID with a valid Apollo stub
# interface. If found, request the gateware to liberate the USB port. In devices with a
# interface. If found, request the gateware to liberate the USB port. In devices with a
# shared port, this effectively hands off the USB port to Apollo.
if device is None:

Expand All @@ -111,7 +111,7 @@ def __init__(self, force_offline=False):
raise DebuggerNotFound(f"Handoff request failed: {e.strerror}")

# Wait for Apollo to enumerate and try again
time.sleep(2)
time.sleep(2)
device = self._find_device(self.APOLLO_USB_IDS, custom_match=self._device_has_apollo_id)
if device is None:
raise DebuggerNotFound("Handoff was requested, but Apollo is not available")
Expand Down Expand Up @@ -150,10 +150,29 @@ def _request_handoff(cls, device):

@staticmethod
def _find_device(ids, custom_match=None):
import usb.backend.libusb1

# In Windows, we need to specify the libusb library location to create a backend.
if platform.system() == "Windows":
# Determine the path to libusb-1.0.dll.
try:
from importlib_resources import files # <= 3.8
except:
from importlib.resources import files # >= 3.9
libusb_dll = os.path.join(files("usb1"), "libusb-1.0.dll")

# Create a backend by explicitly passing the path to libusb_dll.
backend = usb.backend.libusb1.get_backend(find_library=lambda x: libusb_dll)
else:
# On other systems we can just use the default backend.
backend = usb.backend.libusb1.get_backend()

# Find the device.
for vid, pid in ids:
device = usb.core.find(idVendor=vid, idProduct=pid, custom_match=custom_match)
device = usb.core.find(backend=backend, idVendor=vid, idProduct=pid, custom_match=custom_match)
if device is not None:
return device

return None

@staticmethod
Expand Down Expand Up @@ -282,7 +301,7 @@ def create_jtag_programmer(self, jtag_chain):
def create_jtag_spi(self, jtag_chain):
""" Returns a JTAG-over-SPI connection for the given device. """

# If this is an external programmer, we don't yet know how to create a JTAG-SPI
# If this is an external programmer, we don't yet know how to create a JTAG-SPI
# interface for it. For now, assume we can't.
if self.major == self.EXTERNAL_BOARD_MAJOR:
return None, None
Expand Down
19 changes: 11 additions & 8 deletions apollo_fpga/gateware/flash_bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
class SPIStreamController(Elaboratable):
""" Class that drives a SPI bus with data from input stream packets.
Data received from the device is returned as another packet."""

def __init__(self):
self.period = 4 # powers of two only
self.bus = SPIBus()
Expand All @@ -56,7 +56,7 @@ def elaborate(self, platform):
sck_fall.eq( sck_d & ~self.bus.sck), # falling edge
sck_rise.eq(~sck_d & self.bus.sck), # rising edge
]

# I/O shift registers, bit counter and last flag
shreg_o = Signal(8)
shreg_i = Signal(8)
Expand Down Expand Up @@ -114,7 +114,7 @@ def elaborate(self, platform):
m.next = 'END'
with m.Elif(~self.input.valid):
m.next = 'WAIT'

with m.State("END"):
m.d.comb += [
self.input.ready .eq(0),
Expand All @@ -134,7 +134,7 @@ def elaborate(self, platform):
]

return m


class FlashBridgeRequestHandler(USBRequestHandler):
""" Request handler that can trigger a FPGA reconfiguration. """
Expand Down Expand Up @@ -168,7 +168,7 @@ def elaborate(self, platform):

# Once the receive is complete, respond with an ACK.
with m.If(interface.rx_ready_for_response):
m.d.comb += interface.handshakes_out.ack.eq(1)
m.d.comb += interface.handshakes_out.ack.eq(1)

# If we reach the status stage, send a ZLP.
with m.If(interface.status_requested):
Expand All @@ -181,7 +181,7 @@ def elaborate(self, platform):
class FlashBridgeSubmodule(Elaboratable):
""" Implements gateware for the USB<->SPI bridge. Intended to use as a submodule
See example in FlashBridge """

def __init__(self, endpoint):
# Endpoint number for the in/out stream endpoints
self.endpoint = endpoint
Expand Down Expand Up @@ -354,12 +354,15 @@ class FlashBridgeNotFound(IOError):
class FlashBridgeConnection:
def __init__(self):
# Try to create a connection to our configuration flash bridge.
device = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID, custom_match=self._find_cfg_flash_bridge)
device = ApolloDebugger._find_device(
ids=[(VENDOR_ID, PRODUCT_ID)],
custom_match=self._find_cfg_flash_bridge
)

# If we couldn't find the bridge, bail out.
if device is None:
raise FlashBridgeNotFound("Unable to find device")

self.device = device
self.interface, self.endpoint = self._find_cfg_flash_bridge(device, get_ep=True)

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ classifiers = [
'Topic :: Scientific/Engineering',
]
dependencies = [
"importlib_resources; python_version<'3.9'",
"pyusb>1.1.1",
"pyvcd>=0.2.4",
"prompt-toolkit>3.0.16",
Expand Down

0 comments on commit 87e0fe7

Please sign in to comment.