I'm migrating a production jig driver application from using multiple calls to an nrfjprog binary to the pynrfjprog library instead. It's gone almost perfectly, but I have a problem I can't figure out: after I've done all the steps--erased, reflashed, and reset the target device--I can't clean up the connection by closing the connection to the target device, or to the J-Link (emu), or to the DLL API in Python. It just hangs forever if I try. The only thing that works instead is killing the process and restarting it.
I'm running a virtualenv (managed by pipenv) of Python 3.11.4 on a Macbook Pro (macOS Sonoma 14.1), with pynrfjprog v10.23.2 (the latest as of this post). I'm flashing a u-blox BMD-340 module built around an nRF52840 chip. I have no issues whatsoever flashing it with other means.
I originally thought the problem was related to some threading that I had in my code, but I pared it down to something as simple as possible, and it still happens. Here's the code that I'm testing with:
import logging logging.basicConfig(format='%(asctime)s - %(name)s/%(levelname)s - %(message)s', level=logging.INFO) logging.info("Loading nrfjprog integration module...") from pynrfjprog import LowLevel nrf_api = LowLevel.API("NRF52") logging.info("Opening connection to nrfjprog API") nrf_api.open() logging.info("Opening connection to J-Link probe") nrf_api.connect_to_emu_without_snr() emu_snr = nrf_api.read_connected_emu_snr() logging.info("Probe connection established, SNR " + str(emu_snr)) nrf_api.connect_to_device() device_info = nrf_api.read_device_info() logging.info("Connected to target device: " + str(device_info)) logging.info("Disconnecting from target device") nrf_api.disconnect_from_device() logging.info("Closing connection to J-Link probe") nrf_api.disconnect_from_emu() logging.info("Closing connection to nrfjprog API") nrf_api.close() logging.info("All nrfjprog connections closed") exit(0)
When I run this, the output stops before the disconnection from the target device completes. This shows a limited stack trace for where it's stuck after I press Ctrl+C:
JeffMBP:minijig jrowberg$ pipenv run python ./minijig.py 2023-12-29 15:46:03,579 - root/INFO - Loading nrfjprog integration module... 2023-12-29 15:46:03,657 - root/INFO - Opening connection to nrfjprog API 2023-12-29 15:46:03,685 - root/INFO - Opening connection to J-Link probe 2023-12-29 15:46:04,060 - root/INFO - Probe connection established, SNR 820101513 2023-12-29 15:46:04,369 - root/INFO - Connected to target device: (<DeviceVersion.NRF52840_xxAA_REV2: 86523907>, <DeviceName.NRF52840: 86523904>, <DeviceMemory.AA: 1>, <DeviceRevision.REV2: 21>) 2023-12-29 15:46:04,369 - root/INFO - Disconnecting from target device ^CTraceback (most recent call last): File "/Users/jrowberg/minijig/./minijig.py", line 20, in <module> nrf_api.disconnect_from_device() File "/Users/jrowberg/.local/share/virtualenvs/minijig-F0vOpSJS/lib/python3.11/site-packages/pynrfjprog/LowLevel.py", line 719, in disconnect_from_device result = self._lib.NRFJPROG_disconnect_from_device_inst(self._handle) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ KeyboardInterrupt
If I comment out the call to nrf_api.disconnect_from_device()
, then it hangs inside the disconnect_from_emu()
call instead. If I comment that out, then it hangs inside the nrf_api
object's close()
call instead. If I comment all of the clean-up out entirely and let the app attempt to deal with it, like a neanderthal, then the final build-in exit()
call never returns, and a Ctrl+C reveals it's still stuck inside self._lib.NRFJPROG_close_dll_inst(ctypes.byref(self._handle))
.
How can I fix this? Needing to kill and restart the jig driver script after every device goes through it kinda defeats the purpose.