Ejemplo n.º 1
0
def process_one_device(set_device_info):
    execute_shell_command('ifconfig %s down && ifconfig %s up', args.iface,
                          args.iface)

    if not args.only_sign:
        # Flashing firmware without signature
        with closing(bootloader.BootloaderInterface(args.iface)) as bli:
            input('\n'.join([
                '1. Set PIO0_3 low, PIO0_1 low (J4 closed, J3 open)',
                '2. Power on the device and connect it to CAN bus',
                '3. Press ENTER'
            ]))

            with CLIWaitCursor():
                load_and_start_firmware(bli, firmware_base)

        # Testing the device
        input('\n'.join([
            '1. Make sure that LED indicators are blinking',
            '2. Test button operation', '3. Press ENTER'
        ]))

    # Installing signature
    with closing(bootloader.BootloaderInterface(args.iface)) as bli:
        info("Now we're going to sign the device")
        input('\n'.join([
            '1. Set PIO0_3 low, PIO0_1 low (J4 closed, J3 open)',
            '2. Reset the device (e.g. cycle power)', '3. Press ENTER'
        ]))

        with CLIWaitCursor():
            info('Reading unique ID...')
            unique_id = bli.read_unique_id()
            set_device_info(PRODUCT_NAME, unique_id)

            info('Requesting signature for unique ID %s',
                 ' '.join(['%02x' % x for x in unique_id]))
            gensign_response = api.generate_signature(unique_id, PRODUCT_NAME)

            info(
                'Signature has been generated successfully [%s], patching the firmware...',
                ['existing', 'NEW'][gensign_response.new])
            firmware_with_signature = firmware_base.ljust(
                SIGNATURE_OFFSET, b'\xFF') + gensign_response.signature

            load_and_start_firmware(bli, firmware_with_signature)
Ejemplo n.º 2
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')
Ejemplo n.º 3
0
        info('CAN interface is OK')
    except Exception:
        logging.debug('CAN check error', exc_info=True)
        error('CAN interface is not working')
        ok = False

    if not ok:
        fatal('Required interfaces are not available. Please check your hardware configuration. '
              'If this application is running on a virtual machine, make sure that hardware '
              'sharing is configured correctly.')

check_interfaces()

licensing_api = make_api_context_with_user_provided_credentials()

with CLIWaitCursor():
    print('Please wait...')
    if args.firmware:
        firmware_data = download(args.firmware)
    else:
        firmware_data = download_newest(DEFAULT_FIRMWARE_GLOB)
    assert 30 < (len(firmware_data) / 1024) <= 240, 'Invalid firmware size'


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.')
Ejemplo n.º 4
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')
Ejemplo n.º 5
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 CAN connector on the Babel; leave the other CAN connector empty.\n'
        '3. Connect USB to the Micro USB port on the Babel.\n'
        '4. If you want to skip firmware upload, type F now.\n'
        '5. Press ENTER.')

    skip_fw_upload = 'f' in out.lower()
    if not skip_fw_upload:
        info('Loading the firmware')
        with CLIWaitCursor():
            try:
                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')
            except Exception as ex:
                logging.info('Firmware load error', exc_info=True)
                fatal(
                    'Could not load firmware; check the debug connector; error: %r',
                    ex)
    else:
        info('Firmware upload skipped')

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

    with closing(
            drwatson.can.SLCAN(get_target_serial_port_symlink(),
                               bitrate=CAN_BITRATE,
                               default_timeout=1)) as drv_target:
        info('Reading Zubax ID...')
        zubax_id = read_zubax_id(drv_target)
        unique_id = b64decode(zubax_id['hw_unique_id'])
        product_id = zubax_id['product_id']
        assert PRODUCT_NAME == product_id
        set_device_info(product_id, unique_id)

        info('Configuring the adapter...')

        drv_target.execute_cli_command(
            'cfg set can.terminator_on 1')  # Terminator ON

        logger.info('Adapter state:\n%s',
                    drv_target.execute_cli_command('stat'))

        with closing(uavcan.driver.make_driver(
                args.iface, bitrate=CAN_BITRATE)) as drv_test:
            random_frames = [
                make_random_can_frame() for _ in range(NUM_TEST_FRAMES)
            ]

            # If we're using another Zubax Babel as a CAN adapter, this command will disable its CAN power output.
            # Otherwise the command will silently fail. The CAN power output must be disabled because it interferes
            # with the power supply delivery testing.
            try:
                drv_test.execute_cli_command('cfg set can.power_on 0',
                                             lambda _: None)
            except Exception as ex:
                logger.debug('CAN adapter CLI command failed: %s', ex)

            info('Testing CAN bus exchange: target --> test')
            for idx, rf in enumerate(random_frames):
                drv_target.send(rf.id, rf.data, rf.extended)
                received = drv_test.receive(1)
                enforce(received is not None,
                        'Timeout when trying to receive frame %d', idx + 1)
                enforce(
                    received.extended == rf.extended
                    and received.data == rf.data and received.id == rf.id,
                    'Received frame %d [%r] does not match the reference [%r]',
                    idx + 1, received, rf)

            info('Testing CAN bus exchange: test --> target')
            for idx, rf in enumerate(random_frames):
                drv_test.send(rf.id, rf.data, rf.extended)
                try:
                    received = drv_target.receive(1)
                except TimeoutError:
                    fatal('Timeout when trying to receive frame %d', idx + 1)
                enforce(
                    received['ext'] == rf.extended
                    and received['data'] == rf.data
                    and received['id'] == rf.id,
                    'Received frame %d [%r] does not match the reference [%r]',
                    idx + 1, received, rf)

            info('Test exchange OK (2x%d frames)', len(random_frames))

            info('Testing power supply...')

            drv_target.execute_cli_command(
                'cfg set can.power_on 0')  # Bus power OFF
            time.sleep(2)
            stat = yaml.load(drv_target.execute_cli_command('stat'))
            enforce(
                BUS_VOLTAGE_RANGE_OFF[0] <= stat['bus_voltage'] <=
                BUS_VOLTAGE_RANGE_OFF[1],
                'Invalid voltage on the bus (power is turned OFF): %r volts; '
                'there may be a short circuit on the board',
                stat['bus_voltage'])
            info('Bus voltage: %r', stat['bus_voltage'])

            drv_target.execute_cli_command(
                'cfg set can.power_on 1')  # Bus power ON
            time.sleep(2)
            stat = yaml.load(drv_target.execute_cli_command('stat'))
            enforce(
                BUS_VOLTAGE_RANGE_ON[0] <= stat['bus_voltage'] <=
                BUS_VOLTAGE_RANGE_ON[1],
                'Invalid voltage on the bus (power is turned ON): %r volts; '
                'the power supply circuit is malfunctioning',
                stat['bus_voltage'])
            info('Bus voltage: %r', stat['bus_voltage'])

            info('Power supply is OK')

            info('Testing LED indicators...')
            # LED1 - CAN Power      - Red
            # LED2 - Terminator ON  - Orange
            # LED3 - Status         - Blue
            # LED4 - CAN Activity   - Green
            enforce(input('Is LED1 (CAN power, RED) turned on?', yes_no=True),
                    'CAN Power LED is not working')

            enforce(
                input('Is LED2 (terminator, ORANGE) turned on?', yes_no=True),
                'Terminator and/or its LED are not working')

            enforce(
                input('Is LED3 (status, BLUE) blinking about once a second?',
                      yes_no=True), 'Status LED is not working')

            def generate_traffic():
                drv_target.send(0, b'', False)
                time.sleep(0.2)

            with BackgroundSpinner(generate_traffic):
                enforce(
                    input('Is LED4 (activity, GREEN) blinking quickly?',
                          yes_no=True),
                    'Activity LED is not working, or the bus has been disconnected'
                )

        info('Resetting configuration to factory defaults...')
        drv_target.execute_cli_command('cfg erase')

        info('Installing signature...')

        # Getting the signature
        info('Requesting signature for unique ID %s',
             binascii.hexlify(unique_id).decode())
        gen_sign_response = licensing_api.generate_signature(
            unique_id, PRODUCT_NAME)
        if gen_sign_response.new:
            info('New signature has been generated')
        else:
            info(
                'This particular device was signed earlier, reusing the existing signature'
            )
        base64_signature = b64encode(gen_sign_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 = drv_target.execute_cli_command('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(drv_target)['hw_signature']
        logger.info('Installed signature in Base64: %s', installed_signature)
        enforce(
            b64decode(installed_signature) == gen_sign_response.signature,
            'Written signature does not match the generated signature')

        info('Signature has been installed and verified')