Esempio n. 1
0
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)
Esempio n. 2
0
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)
Esempio n. 3
0
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)
Esempio n. 4
0
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)