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." )
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
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.')
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')
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")