def wait_for_boot():
    deadline = time.monotonic() + BOOT_TIMEOUT

    def handle_serial_port_hanging():
        fatal('DRWATSON HAS DETECTED A PROBLEM WITH THE CONNECTED HARDWARE AND NEEDS TO TERMINATE.\n'
              'A serial port operation has timed out. This usually indicates a problem with the connected '
              'hardware or its drivers. Please disconnect all USB devices currently connected to this computer, '
              "then connect them back and restart DrWatson. If you're using a virtual machine, please reboot it.",
              use_abort=True)

    with BackgroundDelay(BOOT_TIMEOUT * 5, handle_serial_port_hanging):
        with open_serial_port(DEBUGGER_PORT_CLI_GLOB, timeout=BOOT_TIMEOUT) as p:
            try:
                for line in p:
                    if b'zubax gnss' in line.lower() and b'bootloader' not in line.lower():
                        logging.info('Boot detected, waiting a few seconds...')
                        time.sleep(4)
                        return
                    logger.info('Debug UART output: %s', line)
                    if time.monotonic() > deadline:
                        break
            except serial.serialutil.SerialException:
                raise
            except IOError:
                logging.info('Boot error', exc_info=True)
            finally:
                p.flushInput()

    warning("The device did not emit a correct boot message via CLI, but we're going "
            "to continue anyway. Possible reasons for this warning:\n"
            '1. The device could not boot properly (however it was flashed successfully).\n'
            '2. The debug connector is not soldered properly.\n'
            '3. The serial port is opened by another application.\n'
            '4. Either the USB-UART adapter or the VM are malfunctioning. Try reconnecting '
            'the adapter (disconnect from USB and from the device!) or reboot the VM.')
def wait_for_boot():
    deadline = time.monotonic() + BOOT_TIMEOUT

    def handle_serial_port_hanging():
        fatal(
            'DRWATSON HAS DETECTED A PROBLEM WITH CONNECTED HARDWARE AND NEEDS TO TERMINATE.\n'
            'A serial port operation has timed out. This usually indicates a problem with the connected '
            'hardware or its drivers. Please disconnect all USB devices currently connected to this computer, '
            "then connect them back and restart Drwatson. If you're using a virtual machine, please reboot it.",
            use_abort=True)

    with BackgroundDelay(BOOT_TIMEOUT * 5, handle_serial_port_hanging):
        with open_serial_port(DEBUGGER_PORT_CLI_GLOB,
                              timeout=BOOT_TIMEOUT) as p:
            try:
                for line in p:
                    if b'Zubax GNSS' in line:
                        return
                    logger.info('Debug UART output: %s', line)
                    if time.monotonic() > deadline:
                        break
            except IOError:
                logging.info('Boot error', exc_info=True)
            finally:
                p.flushInput()

    warning(
        "The board did not report to CLI with a correct boot message, but we're going "
        "to continue anyway. Possible reasons for this warning:\n"
        '1. The board could not boot properly (however it was flashed successfully).\n'
        '2. The debug connector is not soldered properly.\n'
        '3. The serial port is open by another application.\n'
        '4. Either USB-UART adapter or VM are malfunctioning. Try to re-connect the '
        'adapter (disconnect from USB and from the board!) or reboot the VM.')
def wait_for_boot():
    deadline = time.monotonic() + BOOT_TIMEOUT

    def handle_serial_port_hanging():
        fatal(
            "DRWATSON HAS DETECTED A PROBLEM WITH CONNECTED HARDWARE AND NEEDS TO TERMINATE.\n"
            "A serial port operation has timed out. This usually indicates a problem with the connected "
            "hardware or its drivers. Please disconnect all USB devices currently connected to this computer, "
            "then connect them back and restart Drwatson. If you're using a virtual machine, please reboot it.",
            use_abort=True,
        )

    with BackgroundDelay(BOOT_TIMEOUT * 5, handle_serial_port_hanging):
        with open_serial_port(DEBUGGER_PORT_CLI_GLOB, timeout=BOOT_TIMEOUT) as p:
            try:
                for line in p:
                    if b"Zubax GNSS" in line:
                        return
                    logger.info("Debug UART output: %s", line)
                    if time.monotonic() > deadline:
                        break
            except IOError:
                logging.info("Boot error", exc_info=True)
            finally:
                p.flushInput()

    warning(
        "The board did not report to CLI with a correct boot message, but we're going "
        "to continue anyway. Possible reasons for this warning:\n"
        "1. The board could not boot properly (however it was flashed successfully).\n"
        "2. The debug connector is not soldered properly.\n"
        "3. The serial port is open by another application.\n"
        "4. Either USB-UART adapter or VM are malfunctioning. Try to re-connect the "
        "adapter (disconnect from USB and from the board!) or reboot the VM."
    )
Exemple #4
0
 def test_serial_port(glob, name):
     try:
         with open_serial_port(glob):
             info('%s port is OK', name)
             return True
     except Exception:
         error('%s port is not working', name)
         return False
 def test_serial_port(glob, name):
     try:
         with open_serial_port(DEBUGGER_PORT_GDB_GLOB):
             info("%s port is OK", name)
             return True
     except Exception:
         error("%s port is not working", name)
         return False
Exemple #6
0
def wait_for_boot():
    def handle_serial_port_hanging():
        fatal('DRWATSON HAS DETECTED A PROBLEM WITH CONNECTED HARDWARE AND NEEDS TO TERMINATE.\n'
              'A serial port operation has timed out. This usually indicates a problem with the connected '
              'hardware or its drivers. Please disconnect all USB devices currently connected to this computer, '
              "then connect them back and restart Drwatson. If you're using a virtual machine, please reboot it.",
              use_abort=True)

    with BackgroundDelay(BOOT_TIMEOUT * 5, handle_serial_port_hanging):
        with open_serial_port(DEBUGGER_PORT_CLI_GLOB) as p:
            try:
                serial_cli = SerialCLI(p)
                boot_deadline = time.monotonic() + BOOT_TIMEOUT
                boot_notification_received = False
                failure_notification_received = False

                while boot_deadline > time.monotonic():
                    timed_out, line = serial_cli.read_line(END_OF_BOOT_LOG_TIMEOUT)

                    if not timed_out:
                        cli_logger.info(repr(line))

                        if PRODUCT_NAME.lower() in line.lower() and 'bootloader' not in line.lower():
                            info('Boot confirmed')
                            boot_notification_received = True

                        if 'error' in line.lower() or 'fail' in line.lower():
                            failure_notification_received = True
                            error('Boot error: %r', line)
                    else:
                        if failure_notification_received:
                            abort('Device failed to start up normally; see the log for details')

                        if boot_notification_received:
                            return

            except IOError:
                logging.info('Boot error', exc_info=True)
            finally:
                p.flushInput()

    abort("The device did not report to CLI with a correct boot message. Possible reasons for this error:\n"
          '1. The device could not boot properly (however it was flashed successfully).\n'
          '2. The debug connector is not soldered properly.\n'
          '3. The serial port is open by another application.\n'
          '4. Either USB-UART adapter or VM are malfunctioning. Try to re-connect the '
          'adapter (disconnect from USB and from the device!) or reboot the VM.')
Exemple #7
0
def process_one_device(set_device_info):
    out = input('1. Connect DroneCode Probe to the debug connector.\n'
                '2. Connect CAN to the first CAN1 connector on the device; terminate the other CAN1 connector.\n'
                '4. Connect an appropriate power supply (see the hardware specs for requirements).\n'
                '   Make sure the motor leads are NOT CONNECTED to anything.\n'
                '5. If you want to skip firmware upload, type F.\n'
                '6. Press ENTER.')

    skip_fw_upload = 'f' in out.lower()
    if not skip_fw_upload:
        info('Loading the firmware')
        with CLIWaitCursor():
            load_firmware_via_gdb(firmware_data,
                                  toolchain_prefix=TOOLCHAIN_PREFIX,
                                  load_offset=FLASH_OFFSET,
                                  gdb_port=glob_one(DEBUGGER_PORT_GDB_GLOB),
                                  gdb_monitor_scan_command='swdp_scan')
    else:
        info('Firmware upload skipped, rebooting the device')
        with open_serial_port(DEBUGGER_PORT_CLI_GLOB) as io:
            SerialCLI(io, 0.1).write_line_and_read_output_lines_until_timeout('reboot')

    info('Waiting for the device to boot...')
    wait_for_boot()

    with open_serial_port(DEBUGGER_PORT_CLI_GLOB) as io:
        info('Identifying the connected device...')
        cli = SerialCLI(io, 0.1)
        cli.flush_input(0.5)

        zubax_id = read_zubax_id(cli)
        unique_id = b64decode(zubax_id['hw_unique_id'])
        product_id = zubax_id['product_id']
        set_device_info(product_id, unique_id)

        with BackgroundCLIListener(io, lambda line: cli_logger.info(repr(line))):
            input('Connect a motor WITHOUT ANY LOAD ATTACHED to the ESC, then press ENTER.\n'
                  'CAUTION: THE MOTOR WILL SPIN')
            test_uavcan()

        try:
            # Using first command to get rid of any garbage lingering in the buffers
            cli.write_line_and_read_output_lines_until_timeout('systime')
        except Exception:
            pass

        # Getting the signature
        info('Requesting signature for unique ID %s', binascii.hexlify(unique_id).decode())
        gensign_response = licensing_api.generate_signature(unique_id, PRODUCT_NAME)
        if gensign_response.new:
            info('New signature has been generated')
        else:
            info('This particular device has been signed earlier, reusing existing signature')
        base64_signature = b64encode(gensign_response.signature).decode()
        logger.info('Generated signature in Base64: %s', base64_signature)

        # Installing the signature; this may fail if the device has been signed earlier - the failure will be ignored
        out = cli.write_line_and_read_output_lines_until_timeout('zubax_id %s', base64_signature)
        logger.debug('Signature installation response (may fail, which is OK): %r', out)

        # Reading the signature back and verifying it
        installed_signature = read_zubax_id(cli)['hw_signature']
        logger.info('Installed signature in Base64: %s', installed_signature)
        enforce(b64decode(installed_signature) == gensign_response.signature,
                'Written signature does not match the generated signature')

        info('Signature has been installed and verified')
Exemple #8
0
def process_one_device(set_device_info):
    out = input(
        '1. Connect DroneCode Probe to the debug connector\n'
        '2. Connect CAN to the first CAN1 connector on the device; terminate the other CAN1 connector\n'
        '3. Connect USB to the device, and make sure that no other Zubax GNSS is connected\n'
        '4. If you want to skip firmware upload, type F\n'
        '5. Press ENTER')

    skip_fw_upload = 'f' in out.lower()
    if not skip_fw_upload:
        info('Loading the firmware')
        with CLIWaitCursor():
            load_firmware(firmware_data)
        info('Waiting for the device to boot...')
        wait_for_boot()
    else:
        info('Firmware upload skipped')

    info('Identifying the connected device...')
    with open_serial_port(USB_CDC_ACM_GLOB, wait_for_port=5) as io:
        logger.info('USB CLI is on %r', io.port)
        zubax_id = SerialCLI(io, 0.1).read_zubax_id()
        product_id = zubax_id['product_id']
        unique_id = b64decode(zubax_id['hw_unique_id'])
        set_device_info(product_id, unique_id)

    info('Testing UAVCAN interface...')
    test_uavcan()

    info('Connecting via USB...')
    with open_serial_port(USB_CDC_ACM_GLOB, wait_for_port=5) as io:
        logger.info('USB CLI is on %r', io.port)
        cli = SerialCLI(io, 0.1)

        enforce(unique_id == b64decode(cli.read_zubax_id()['hw_unique_id']),
                'UID changed!')

        try:
            # Using first command to get rid of any garbage lingering in the buffers
            cli.write_line_and_read_output_lines_until_timeout('systime')
        except Exception:
            pass

        # Getting the signature
        info('Requesting signature for unique ID %s',
             binascii.hexlify(unique_id).decode())
        gensign_response = licensing_api.generate_signature(
            unique_id, PRODUCT_NAME)
        if gensign_response.new:
            info('New signature has been generated')
        else:
            info(
                'This particular device has been signed earlier, reusing existing signature'
            )
        base64_signature = b64encode(gensign_response.signature).decode()
        logger.info('Generated signature in Base64: %s', base64_signature)

        # Installing the signature; this may fail if the device has been signed earlier - the failure will be ignored
        out = cli.write_line_and_read_output_lines_until_timeout(
            'signature %s', base64_signature)
        logger.debug(
            'Signature installation response (may fail, which is OK): %r', out)

        # Reading the signature back and verifying it
        out = cli.write_line_and_read_output_lines_until_timeout('signature')
        enforce(
            len(out) == 1,
            'Could not read the signature back. Returned lines: %r', out)
        logger.info('Installed signature in Base64: %s', out[0])
        enforce(
            b64decode(out[0]) == gensign_response.signature,
            'Written signature does not match the generated signature')

        info('Signature has been installed and verified')
def process_one_device(set_device_info):
    out = input('1. Connect DroneCode Probe to the debug connector.\n'
                '2. Connect CAN to the first CAN1 connector on the device; terminate the other CAN1 connector.\n'
                '3. Connect USB to the device, and make sure that no other Zubax GNSS is connected.\n'
                '4. If you want to skip firmware upload, type F.\n'
                '5. Press ENTER.')

    skip_fw_upload = 'f' in out.lower()
    if not skip_fw_upload:
        info('Loading the firmware')
        with CLIWaitCursor():
            load_firmware(firmware_data)
        info('Waiting for the device to boot...')
        wait_for_boot()
    else:
        info('Firmware upload skipped')

    info('Identifying the connected device...')
    with open_serial_port(USB_CDC_ACM_GLOB, wait_for_port=5) as io:
        logger.info('USB CLI is on %r', io.port)
        zubax_id = SerialCLI(io, 0.1).read_zubax_id()
        product_id = zubax_id['product_id']
        unique_id = b64decode(zubax_id['hw_unique_id'])
        set_device_info(product_id, unique_id)

    info('Testing the UAVCAN interface...')
    test_uavcan()

    info('Connecting via USB...')
    with open_serial_port(USB_CDC_ACM_GLOB, wait_for_port=5) as io:
        logger.info('USB CLI is on %r', io.port)
        cli = SerialCLI(io, 0.1)

        enforce(unique_id == b64decode(cli.read_zubax_id()['hw_unique_id']), 'UID changed!')

        try:
            # Using first command to get rid of any garbage lingering in the buffers
            cli.write_line_and_read_output_lines_until_timeout('systime')
        except Exception:
            pass

        # Getting the signature
        info('Requesting signature for unique ID %s', binascii.hexlify(unique_id).decode())
        gensign_response = licensing_api.generate_signature(unique_id, PRODUCT_NAME)
        if gensign_response.new:
            info('New signature has been generated')
        else:
            info('This particular device was signed earlier, reusing the existing signature')
        base64_signature = b64encode(gensign_response.signature).decode()
        logger.info('Generated signature in Base64: %s', base64_signature)

        # Installing the signature; this may fail if the device has been signed earlier - the failure will be ignored
        out = cli.write_line_and_read_output_lines_until_timeout('signature %s', base64_signature)
        logger.debug('Signature installation response (may fail, which is OK): %r', out)

        # Reading the signature back and verifying it
        out = cli.write_line_and_read_output_lines_until_timeout('signature')
        enforce(len(out) == 1, 'Could not read the signature back. Returned lines: %r', out)
        logger.info('Installed signature in Base64: %s', out[0])
        enforce(b64decode(out[0]) == gensign_response.signature,
                'Written signature does not match the generated signature')

        info('Signature has been installed and verified')
def process_one_device():
    out = input(
        "1. Connect DroneCode Probe to the debug connector\n"
        "2. Connect CAN to the first CAN1 connector on the device; terminate the other CAN1 connector\n"
        "3. Connect USB to the device, and make sure that no other Zubax GNSS is connected\n"
        "4. If you want to skip firmware upload, type F\n"
        "5. Press ENTER"
    )

    skip_fw_upload = "f" in out.lower()
    if not skip_fw_upload:
        info("Loading the firmware")
        with CLIWaitCursor():
            load_firmware(firmware_data)
        info("Waiting for the board to boot...")
        wait_for_boot()
    else:
        info("Firmware upload skipped")

    info("Testing UAVCAN interface...")
    test_uavcan()

    input(
        "Now we're going to test USB. If this application is running on a virtual "
        "machine, make sure that the corresponsing USB device is made available for "
        "the VM, then press ENTER."
    )
    info("Connecting via USB...")
    with open_serial_port(USB_CDC_ACM_GLOB) as io:
        logger.info("USB CLI is on %r", io.port)
        cli = SerialCLI(io, 0.1)
        cli.flush_input(0.5)

        try:
            # Using first command to get rid of any garbage lingering in the buffers
            cli.write_line_and_read_output_lines_until_timeout("systime")
        except Exception:
            pass

        zubax_id = cli.write_line_and_read_output_lines_until_timeout("zubax_id")
        zubax_id = yaml.load("\n".join(zubax_id))
        logger.info("Zubax ID: %r", zubax_id)

        unique_id = b64decode(zubax_id["hw_unique_id"])

        # Getting the signature
        info("Requesting signature for unique ID %s", binascii.hexlify(unique_id).decode())
        gensign_response = licensing_api.generate_signature(unique_id, PRODUCT_NAME)
        if gensign_response.new:
            info("New signature has been generated")
        else:
            info("This particular device has been signed earlier, reusing existing signature")
        base64_signature = b64encode(gensign_response.signature).decode()
        logger.info("Generated signature in Base64: %s", base64_signature)

        # Installing the signature; this may fail if the device has been signed earlier - the failure will be ignored
        out = cli.write_line_and_read_output_lines_until_timeout("signature %s", base64_signature)
        logger.debug("Signature installation response (may fail, which is OK): %r", out)

        # Reading the signature back and verifying it
        out = cli.write_line_and_read_output_lines_until_timeout("signature")
        enforce(len(out) == 1, "Could not read the signature back. Returned lines: %r", out)
        logger.info("Installed signature in Base64: %s", out[0])
        enforce(
            b64decode(out[0]) == gensign_response.signature, "Written signature does not match the generated signature"
        )

        info("Signature has been installed and verified")