def openocd_setup(options): '-> (adapter, dap_info, mcu_info, openocd_rpc)' if options.adapter_usb_vid_pid is not None: # VID:PID (hexadecimal) try: (usb_vid, usb_pid) = options.adapter_usb_vid_pid.split(':') (usb_vid, usb_pid) = (int(usb_vid, base=16), int(usb_pid, base=16)) except (IndexError, ValueError): raise OpenOcdSetupError('%r is not a valid USB VID:PID' % (options.adapter_usb_vid_pid,)) try: adapter = easierocd.usb.adapter_by_usb_vid_pid((usb_vid, usb_pid)) except AdapterNotFound: raise OpenOcdSetupError("Can't find adapter with specified VID:PID") except AdapterNotSupported: raise OpenOcdSetupError('Specified adapter is not supported') except MultipleAdaptersMatchCriteria as e: raise OpenOcdSetupError(('More than one adapter has the specified USB VID:PID (%s)!\n' % (options.adapter_usb_vid_pid,)) + e.args[0]) elif options.adapter_usb_serial is not None: # support non-ASCII USB serial numbers with "\xFF" syntax try: serial = options.adapter_usb_serial.encode('ascii').decode('unicode-escape') except ValueError: raise OpenOcdSetupError('%r is not a valid USB serial number' % (options.adapter_usb_serial,)) try: adapter = easierocd.usb.adapter_by_usb_serial(serial) except AdapterNotFound: raise OpenOcdSetupError("Can't find adapter with specified serial number") except AdapterNotSupported: raise OpenOcdSetupError('Specified adapter is not supported') except MultipleAdaptersMatchCriteria as e: raise OpenOcdSetupError(('More than one adapter has the specified USB serial number (%s)!\n' % (options.adapter_usb_serial,)) + e.args[0]) elif options.adapter_usb_bus_addr is not None: # BUS:DEV (decimal) try: (bus_num, addr_num) = options.adapter_usb_bus_addr.split(':') (bus_num, addr_num) = (int(bus_num), int(addr_num)) except (IndexError, ValueError): raise OpenOcdSetupError('%r is not a valid USB BUS:ADDR specifier' % (options.adapter_usb_bus_addr,)) try: adapter = easierocd.usb.adapter_by_usb_bus_addr((bus_num, addr_num)) except AdapterNotFound: raise OpenOcdSetupError("Can't find adapter with specified bus and device number") except AdapterNotSupported: raise OpenOcdSetupError('Specified adapter is not supported') else: adapters = easierocd.usb.connected_debug_adapters() if not adapters: raise OpenOcdSetupError('no supported debug adapters found') if len(adapters) == 1: adapter = adapters[0] else: if options.non_interactive is False: try: adapter = interactive_choose_adapter(options, adapters) except EOFError: raise OpenOcdSetupError('Exiting due to user action') else: raise OpenOcdSetupError("Multiple supported debug adapters exist. " "Use command line options or environment variables to choose one from:\n" + multiple_adapter_msg(adapters)) # The debug adapter to be used is fixed after this point # Doing pid file and tmux session cleanups here is bit hackish adapters = easierocd.usb.connected_debug_adapters() pid_files_cleanup(adapters) tmux_sessions_cleanup(adapters) # If multiple debug adapters have the same serial number as the choosen one # raise MultipleAdaptersMatchCriteria here adapter_serial_number = getattr(adapter[1], 'serial_number') if adapter_serial_number is not None: try: easierocd.usb.adapter_by_usb_serial(adapter_serial_number) except (MultipleAdaptersMatchCriteria) as e: if adapter[0]['name'] == 'St-Link/V2-1': msg = 'http://www.st.com/web/en/catalog/tools/PF260217' else: msg = 'http://www.st.com/web/en/catalog/tools/PF258194' raise OpenOcdSetupError('Your ST-Link debug adapter has a known bug where the USB serial number changes after first use ' 'that makes it impossible to use multiple ST-Links on the same machine.\n' 'Please upgrade ST-Link\'s firmware from: ' + msg) (o, openocd_newly_started_or_not) = openocd_rpc_for_adapter(adapter) logging.debug('openocd_newly_started_or_not: %d' % (openocd_newly_started_or_not,)) openocd_connnection_unusable = False openocd_initialized = o.initialized() if not openocd_initialized: openocd_connnection_unusable = True target_names = [] if not openocd_connnection_unusable: target_names = o.target_names() if not target_names: openocd_connnection_unusable = True elif not target_names or 'EASIEROCD_DETECT.cpu' in target_names: openocd_connnection_unusable = True # Mostly for USB cable or SWD/JTAG wire unplugs poll_info = None if not openocd_connnection_unusable: try: # OpenOCD's poll() detects the CPU state poll_info = o.poll() except TargetCommunicationError: logging.debug('openocd_setup: poll: OpenOcdCortexMDetectError') openocd_connnection_unusable = True dap_info = None if not openocd_connnection_unusable: assert(poll_info is not None) mdetect = OpenOcdCortexMDetect(options, adapter, o) try: dap_info = mdetect.detect_dap() except OpenOcdCortexMDetectError: logging.debug('openocd_setup: detect_dap: OpenOcdCortexMDetectError') openocd_connnection_unusable = True mcu_info = None if not openocd_connnection_unusable: assert(dap_info is not None) try: mcu_info = mdetect.detect_mcu(dap_info) except OpenOcdCortexMDetectError: logging.debug('openocd_setup: detect_mcu: OpenOcdCortexMDetectError') openocd_connnection_unusable = True logging.debug('target_names: %r, poll_info: %r, dap_info: %r, mcu_info: %r' % (target_names, poll_info, dap_info, mcu_info)) if openocd_connnection_unusable: logging.debug('Restarting OpenOCD to re-do all the config including probing') o.openocd_shutdown() waitpid_ignore_echild(o.pid) (o, openocd_newly_started_or_not) = openocd_rpc_for_adapter(adapter) do_intrusive_probe = True else: do_intrusive_probe = False if not do_intrusive_probe: assert(poll_info is not None) assert(dap_info is not None) assert(mcu_info is not None) logging.debug('Reusing OpenOCD daemon config, skipping probe') return (adapter, dap_info, mcu_info, o) else: # hard coding assumption that ARM Cortex-M is debug target logging.debug('Attempting OpenOCD intrusive Cotex-M probe') (dap_info, mcu_info, o) = intrusive_cortex_m_probe_and_setup(options, adapter, o) return (adapter, dap_info, mcu_info, o)
def openocd_setup(options): '-> (adapter, dap_info, mcu_info, openocd_rpc)' if options.adapter_usb_vid_pid is not None: # VID:PID (hexadecimal) try: (usb_vid, usb_pid) = options.adapter_usb_vid_pid.split(':') (usb_vid, usb_pid) = (int(usb_vid, base=16), int(usb_pid, base=16)) except (IndexError, ValueError): raise OpenOcdSetupError('%r is not a valid USB VID:PID' % (options.adapter_usb_vid_pid, )) try: adapter = easierocd.usb.adapter_by_usb_vid_pid((usb_vid, usb_pid)) except AdapterNotFound: raise OpenOcdSetupError( "Can't find adapter with specified VID:PID") except AdapterNotSupported: raise OpenOcdSetupError('Specified adapter is not supported') except MultipleAdaptersMatchCriteria as e: raise OpenOcdSetupError(( 'More than one adapter has the specified USB VID:PID (%s)!\n' % (options.adapter_usb_vid_pid, )) + e.args[0]) elif options.adapter_usb_serial is not None: # support non-ASCII USB serial numbers with "\xFF" syntax try: serial = options.adapter_usb_serial.encode('ascii').decode( 'unicode-escape') except ValueError: raise OpenOcdSetupError('%r is not a valid USB serial number' % (options.adapter_usb_serial, )) try: adapter = easierocd.usb.adapter_by_usb_serial(serial) except AdapterNotFound: raise OpenOcdSetupError( "Can't find adapter with specified serial number") except AdapterNotSupported: raise OpenOcdSetupError('Specified adapter is not supported') except MultipleAdaptersMatchCriteria as e: raise OpenOcdSetupError(( 'More than one adapter has the specified USB serial number (%s)!\n' % (options.adapter_usb_serial, )) + e.args[0]) elif options.adapter_usb_bus_addr is not None: # BUS:DEV (decimal) try: (bus_num, addr_num) = options.adapter_usb_bus_addr.split(':') (bus_num, addr_num) = (int(bus_num), int(addr_num)) except (IndexError, ValueError): raise OpenOcdSetupError( '%r is not a valid USB BUS:ADDR specifier' % (options.adapter_usb_bus_addr, )) try: adapter = easierocd.usb.adapter_by_usb_bus_addr( (bus_num, addr_num)) except AdapterNotFound: raise OpenOcdSetupError( "Can't find adapter with specified bus and device number") except AdapterNotSupported: raise OpenOcdSetupError('Specified adapter is not supported') else: adapters = easierocd.usb.connected_debug_adapters() if not adapters: raise OpenOcdSetupError('no supported debug adapters found') if len(adapters) == 1: adapter = adapters[0] else: if options.non_interactive is False: try: adapter = interactive_choose_adapter(options, adapters) except EOFError: raise OpenOcdSetupError('Exiting due to user action') else: raise OpenOcdSetupError( "Multiple supported debug adapters exist. " "Use command line options or environment variables to choose one from:\n" + multiple_adapter_msg(adapters)) # The debug adapter to be used is fixed after this point # Doing pid file and tmux session cleanups here is bit hackish adapters = easierocd.usb.connected_debug_adapters() pid_files_cleanup(adapters) tmux_sessions_cleanup(adapters) # If multiple debug adapters have the same serial number as the choosen one # raise MultipleAdaptersMatchCriteria here adapter_serial_number = getattr(adapter[1], 'serial_number') if adapter_serial_number is not None: try: easierocd.usb.adapter_by_usb_serial(adapter_serial_number) except (MultipleAdaptersMatchCriteria) as e: if adapter[0]['name'] == 'St-Link/V2-1': msg = 'http://www.st.com/web/en/catalog/tools/PF260217' else: msg = 'http://www.st.com/web/en/catalog/tools/PF258194' raise OpenOcdSetupError( 'Your ST-Link debug adapter has a known bug where the USB serial number changes after first use ' 'that makes it impossible to use multiple ST-Links on the same machine.\n' 'Please upgrade ST-Link\'s firmware from: ' + msg) (o, openocd_newly_started_or_not) = openocd_rpc_for_adapter(adapter) logging.debug('openocd_newly_started_or_not: %d' % (openocd_newly_started_or_not, )) openocd_connnection_unusable = False openocd_initialized = o.initialized() if not openocd_initialized: openocd_connnection_unusable = True target_names = [] if not openocd_connnection_unusable: target_names = o.target_names() if not target_names: openocd_connnection_unusable = True elif not target_names or 'EASIEROCD_DETECT.cpu' in target_names: openocd_connnection_unusable = True # Mostly for USB cable or SWD/JTAG wire unplugs poll_info = None if not openocd_connnection_unusable: try: # OpenOCD's poll() detects the CPU state poll_info = o.poll() except TargetCommunicationError: logging.debug('openocd_setup: poll: OpenOcdCortexMDetectError') openocd_connnection_unusable = True dap_info = None if not openocd_connnection_unusable: assert (poll_info is not None) mdetect = OpenOcdCortexMDetect(options, adapter, o) try: dap_info = mdetect.detect_dap() except OpenOcdCortexMDetectError: logging.debug( 'openocd_setup: detect_dap: OpenOcdCortexMDetectError') openocd_connnection_unusable = True mcu_info = None if not openocd_connnection_unusable: assert (dap_info is not None) try: mcu_info = mdetect.detect_mcu(dap_info) except OpenOcdCortexMDetectError: logging.debug( 'openocd_setup: detect_mcu: OpenOcdCortexMDetectError') openocd_connnection_unusable = True logging.debug( 'target_names: %r, poll_info: %r, dap_info: %r, mcu_info: %r' % (target_names, poll_info, dap_info, mcu_info)) if openocd_connnection_unusable: logging.debug( 'Restarting OpenOCD to re-do all the config including probing') o.openocd_shutdown() waitpid_ignore_echild(o.pid) (o, openocd_newly_started_or_not) = openocd_rpc_for_adapter(adapter) do_intrusive_probe = True else: do_intrusive_probe = False if not do_intrusive_probe: assert (poll_info is not None) assert (dap_info is not None) assert (mcu_info is not None) logging.debug('Reusing OpenOCD daemon config, skipping probe') return (adapter, dap_info, mcu_info, o) else: # hard coding assumption that ARM Cortex-M is debug target logging.debug('Attempting OpenOCD intrusive Cotex-M probe') (dap_info, mcu_info, o) = intrusive_cortex_m_probe_and_setup(options, adapter, o) return (adapter, dap_info, mcu_info, o)
def intrusive_cortex_m_probe_and_setup(options, adapter, openocd_rpc): '-> (dap_info, mcu_info, openocd_rpc)' o = openocd_rpc mdetect = OpenOcdCortexMDetect(options, adapter, o) # Try SWD first (read IDCODE), if that fails falllback to JTAG # Use adapter_info and querying the adapters (e.g. cmsis-dap INFO_ID_CAPS command) # to know whether the adapter supports SWD/JTAG openocd_transport = 'swd' try: adapter = mdetect.openocd_init_for_detection(openocd_transport) except (OpenOcdOpenFailedDuringInit,) as e: raise CortexMProbeFatalError("can't open adapter: %r" % (e.args[0],)) except (AdapterDoesntSupportTransport, OpenOcdDoesntSupportTransportForAdapter): try_jtag = True except (ConnectionError): # protocol or connection error assert(o.pid is not None) kill_ignore_echild(o.pid, signal.SIGTERM) subprocess.call(['tmux', 'kill-session', '-t', tmux_session_name_for_adapter(adapter)]) time.sleep(0.01) (o, openocd_newly_started_or_not) = openocd_rpc_for_adapter(adapter) mdetect = OpenOcdCortexMDetect(options, adapter, o) adapter = mdetect.openocd_init_for_detection(openocd_transport) # OpenOCD limits 'flash bank' to config stage # So declare_flash_bank is called afer openocd_init_for_detection() and before openocd_init_for_cortex_m() try: o.reset_halt() except OpenOcdResetError as e: raise CortexMProbeFatalError("Can't reset target CPU. Check your debug connection wiring, " "target power and hardware reset signal wiring.") dap_info = None try: dap_info = mdetect.detect_dap() except OpenOcdCortexMDetectError as e: try: voltage = o.target_voltage() except OpenOcdCommandNotSupportedError: if voltage <= 1.5: raise CortexMProbeFatalError('target voltage %f is too low. Check your debug connection wiring' % (voltage,)) try_jtag = True else: try_jtag = False if try_jtag: openocd_transport = 'jtag' try: adapter = mdetect.openocd_init_for_detection(openocd_transport) except (AdapterDoesntSupportTransport, OpenOcdDoesntSupportTransportForAdapter): dap_info = None else: # protocol or connection error assert(o.pid is not None) kill_ignore_echild(o.pid, signal.SIGTERM) subprocess.call(['tmux', 'kill-session', '-t', tmux_session_name_for_adapter(adapter)]) adapter = mdetect.openocd_init_for_detection(openocd_transport) o.reset_init() try: dap_info = mdetect.detect_dap() except OpenOcdCortexMDetectError: dap_info = None if dap_info is None: raise CortexMProbeFatalError('failed to detect ARM Debug Access Port') logging.info('dap_info: %r' % (HexDict(dap_info),)) # mcu_info: silicon vendor, MCU family, make, revision etc try: mcu_info = mdetect.detect_mcu(dap_info) except OpenOcdCortexMDetectError: o.openocd_shutdown() waitpid_ignore_echild(o.pid) raise logging.info('mcu_info: %r' % (HexDict(mcu_info),)) # Don't attempt to 'init' OpenOCD twice, shutdown then re-launch instead o.openocd_shutdown() waitpid_ignore_echild(o.pid) (o, openocd_newly_started_or_not) = openocd_rpc_for_adapter(adapter) mdetect = OpenOcdCortexMDetect(options, adapter, o) mdetect.openocd_init_for_cortex_m(openocd_transport, dap_info, mcu_info) # OpenOCD gdbserver is up after 'init' return (dap_info, mcu_info, o)
def intrusive_cortex_m_probe_and_setup(options, adapter, openocd_rpc): '-> (dap_info, mcu_info, openocd_rpc)' o = openocd_rpc mdetect = OpenOcdCortexMDetect(options, adapter, o) # Try SWD first (read IDCODE), if that fails falllback to JTAG # Use adapter_info and querying the adapters (e.g. cmsis-dap INFO_ID_CAPS command) # to know whether the adapter supports SWD/JTAG openocd_transport = 'swd' try: adapter = mdetect.openocd_init_for_detection(openocd_transport) except (OpenOcdOpenFailedDuringInit, ) as e: raise CortexMProbeFatalError("can't open adapter: %r" % (e.args[0], )) except (AdapterDoesntSupportTransport, OpenOcdDoesntSupportTransportForAdapter): try_jtag = True except (ConnectionError): # protocol or connection error assert (o.pid is not None) kill_ignore_echild(o.pid, signal.SIGTERM) subprocess.call([ 'tmux', 'kill-session', '-t', tmux_session_name_for_adapter(adapter) ]) time.sleep(0.01) (o, openocd_newly_started_or_not) = openocd_rpc_for_adapter(adapter) mdetect = OpenOcdCortexMDetect(options, adapter, o) adapter = mdetect.openocd_init_for_detection(openocd_transport) # OpenOCD limits 'flash bank' to config stage # So declare_flash_bank is called afer openocd_init_for_detection() and before openocd_init_for_cortex_m() try: o.reset_halt() except OpenOcdResetError as e: raise CortexMProbeFatalError( "Can't reset target CPU. Check your debug connection wiring, " "target power and hardware reset signal wiring.") dap_info = None try: dap_info = mdetect.detect_dap() except OpenOcdCortexMDetectError as e: try: voltage = o.target_voltage() except OpenOcdCommandNotSupportedError: if voltage <= 1.5: raise CortexMProbeFatalError( 'target voltage %f is too low. Check your debug connection wiring' % (voltage, )) try_jtag = True else: try_jtag = False if try_jtag: openocd_transport = 'jtag' try: adapter = mdetect.openocd_init_for_detection(openocd_transport) except (AdapterDoesntSupportTransport, OpenOcdDoesntSupportTransportForAdapter): dap_info = None else: # protocol or connection error assert (o.pid is not None) kill_ignore_echild(o.pid, signal.SIGTERM) subprocess.call([ 'tmux', 'kill-session', '-t', tmux_session_name_for_adapter(adapter) ]) adapter = mdetect.openocd_init_for_detection(openocd_transport) o.reset_init() try: dap_info = mdetect.detect_dap() except OpenOcdCortexMDetectError: dap_info = None if dap_info is None: raise CortexMProbeFatalError('failed to detect ARM Debug Access Port') logging.info('dap_info: %r' % (HexDict(dap_info), )) # mcu_info: silicon vendor, MCU family, make, revision etc try: mcu_info = mdetect.detect_mcu(dap_info) except OpenOcdCortexMDetectError: o.openocd_shutdown() waitpid_ignore_echild(o.pid) raise logging.info('mcu_info: %r' % (HexDict(mcu_info), )) # Don't attempt to 'init' OpenOCD twice, shutdown then re-launch instead o.openocd_shutdown() waitpid_ignore_echild(o.pid) (o, openocd_newly_started_or_not) = openocd_rpc_for_adapter(adapter) mdetect = OpenOcdCortexMDetect(options, adapter, o) mdetect.openocd_init_for_cortex_m(openocd_transport, dap_info, mcu_info) # OpenOCD gdbserver is up after 'init' return (dap_info, mcu_info, o)