Whenever the FPGA is taken offline, stop allowing it to take over the shared USB port. This prevents a later FPGA configuration from taking over the port before it is explicitly allowed to do so.
This fixes a bug introduced in #50 in which a port handoff could be inappropriately deferred from one FPGA configuration (which does not request the port) to a later configuration (which does request the port):
$ blinky.py
$ bulk_speed_test.py (modified to use CONTROL)
INFO | __init__ | Building and uploading gateware to attached Cynthion r1.3...
Traceback (most recent call last):
File "/home/mossmann/src/apollo/apollo_fpga/ecp5.py", line 467, in configure
status = self._read_status()
^^^^^^^^^^^^^^^^^^^
File "/home/mossmann/src/apollo/apollo_fpga/ecp5.py", line 515, in _read_status
status_bytes = self._execute_command(self.Opcode.LSC_READ_STATUS, self.STATUS_REGISTER_LENGTH,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/mossmann/src/apollo/apollo_fpga/ecp5.py", line 988, in _execute_command
response = self.chain.shift_data(tdi=data, length=length, state_after='DRPAUSE')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/mossmann/src/apollo/apollo_fpga/jtag.py", line 479, in shift_data
response = self._shift_while_in_state('DRSHIFT', tdi=tdi, length=length, ignore_response=ignore_response,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/mossmann/src/apollo/apollo_fpga/jtag.py", line 422, in _shift_while_in_state
self._ensure_in_state(state)
File "/home/mossmann/src/apollo/apollo_fpga/jtag.py", line 386, in _ensure_in_state
self.debugger.out_request(REQUEST_JTAG_GO_TO_STATE, value=state_number)
File "/home/mossmann/src/apollo/apollo_fpga/__init__.py", line 272, in out_request
return self.device.ctrl_transfer(request_type, number, value, index, data, timeout=timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/mossmann/src/cynthion/cynthion/python/venv/lib/python3.11/site-packages/usb/core.py", line 1082, in ctrl_transfer
ret = self._ctx.backend.ctrl_transfer(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/mossmann/src/cynthion/cynthion/python/venv/lib/python3.11/site-packages/usb/backend/libusb1.py", line 893, in ctrl_transfer
ret = _check(self.lib.libusb_control_transfer(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/mossmann/src/cynthion/cynthion/python/venv/lib/python3.11/site-packages/usb/backend/libusb1.py", line 604, in _check
raise USBError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBError: [Errno 32] Pipe error
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/mossmann/src/cynthion/cynthion/python/venv/lib/python3.11/site-packages/cynthion/gateware/platform/core.py", line 79, in toolchain_program
programmer.configure(bitstream)
File "/home/mossmann/src/apollo/apollo_fpga/ecp5.py", line 472, in configure
self.chain.debugger.set_led_pattern(self.chain.debugger.LED_PATTERN_IDLE)
File "/home/mossmann/src/apollo/apollo_fpga/__init__.py", line 285, in set_led_pattern
self.out_request(self.REQUEST_SET_LED_PATTERN, number)
File "/home/mossmann/src/apollo/apollo_fpga/__init__.py", line 272, in out_request
return self.device.ctrl_transfer(request_type, number, value, index, data, timeout=timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/mossmann/src/cynthion/cynthion/python/venv/lib/python3.11/site-packages/usb/core.py", line 1082, in ctrl_transfer
ret = self._ctx.backend.ctrl_transfer(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/mossmann/src/cynthion/cynthion/python/venv/lib/python3.11/site-packages/usb/backend/libusb1.py", line 893, in ctrl_transfer
ret = _check(self.lib.libusb_control_transfer(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/mossmann/src/cynthion/cynthion/python/venv/lib/python3.11/site-packages/usb/backend/libusb1.py", line 604, in _check
raise USBError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBError: [Errno 32] Pipe error
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/mossmann/src/luna/bulk_speed_test.py", line 166, in <module>
device = top_level_cli(SpeedTestDevice,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/mossmann/src/luna/luna/__init__.py", line 113, in top_level_cli
products = platform.build(fragment,
^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/mossmann/src/cynthion/cynthion/python/venv/lib/python3.11/site-packages/amaranth/build/plat.py", line 113, in build
self.toolchain_program(products, name, **(program_opts or {}))
File "/home/mossmann/src/cynthion/cynthion/python/venv/lib/python3.11/site-packages/cynthion/gateware/platform/core.py", line 77, in toolchain_program
with debugger.jtag as jtag:
File "/home/mossmann/src/apollo/apollo_fpga/jtag.py", line 216, in __exit__
self.debugger.out_request(REQUEST_JTAG_STOP)
File "/home/mossmann/src/apollo/apollo_fpga/__init__.py", line 272, in out_request
return self.device.ctrl_transfer(request_type, number, value, index, data, timeout=timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/mossmann/src/cynthion/cynthion/python/venv/lib/python3.11/site-packages/usb/core.py", line 1082, in ctrl_transfer
ret = self._ctx.backend.ctrl_transfer(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/mossmann/src/cynthion/cynthion/python/venv/lib/python3.11/site-packages/usb/backend/libusb1.py", line 893, in ctrl_transfer
ret = _check(self.lib.libusb_control_transfer(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/mossmann/src/cynthion/cynthion/python/venv/lib/python3.11/site-packages/usb/backend/libusb1.py", line 604, in _check
raise USBError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBError: [Errno 32] Pipe error
Whenever the FPGA is taken offline, stop allowing it to take over the shared USB port. This prevents a later FPGA configuration from taking over the port before it is explicitly allowed to do so.
This fixes a bug introduced in #50 in which a port handoff could be inappropriately deferred from one FPGA configuration (which does not request the port) to a later configuration (which does request the port):