Skip to content

Commit

Permalink
On Windows, create the libusb1 backend explicitly by specifying the i…
Browse files Browse the repository at this point in the history
…nstalled location of libusb-1.0.dll
  • Loading branch information
antoinevg committed Jul 9, 2024
1 parent 3a0e3a2 commit 7cb0abb
Show file tree
Hide file tree
Showing 2 changed files with 34 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

0 comments on commit 7cb0abb

Please sign in to comment.