def _erase_board_simple(self, target, no_reset): """ :param target: target to which perform the erase :param no_reset: erase with/without reset :return: exit code """ if "mount_point" not in target: raise EraseError(message="mount point missing from target", return_code=EXIT_CODE_MOUNT_POINT_MISSING) if "serial_port" not in target: raise EraseError(message="serial port missing from target", return_code=EXIT_CODE_SERIAL_PORT_MISSING) Erase._can_be_erased(target) # Copy ERASE.ACT to target mount point, this will trigger the erasing. destination = MbedCommon.get_binary_destination(target["mount_point"], "ERASE.ACT") with open(destination, "wb"): pass target = MbedCommon.wait_for_file_disappear(target, "ERASE.ACT") if not no_reset: Reset(logger=self.logger).reset_board(target["serial_port"]) self._verify_erase_success(MbedCommon.get_binary_destination( target["mount_point"], "ERASE.ACT")) self.logger.info("erase %s completed", target["target_id"]) return EXIT_CODE_SUCCESS
def _verify_erase_success(self, destination): """ Verify that ERASE.ACT is not present in the target mount point. :param destination: target mount point :return: None on success, raises otherwise """ if isfile(destination): msg = "Erase failed: ERASE.ACT still present in mount point" self.logger.error(msg) raise EraseError(message=msg, return_code=EXIT_CODE_FILE_STILL_PRESENT)
def erase(self, target_id=None, no_reset=None, method=None): """ Erase (mbed) device(s). :param target_id: target_id :param no_reset: erase with/without reset :param method: method for erase i.e. simple, pyocd or edbg """ if target_id is None: raise EraseError(message="target id is missing", return_code=EXIT_CODE_TARGET_ID_MISSING) self.logger.info("Starting erase for given target_id %s", target_id) self.logger.info("method used for reset: %s", method) available_devices = Common(self.logger).get_available_device_mapping( self.flashers, target_id) targets_to_erase = self.prepare_target_to_erase( target_id, available_devices) if len(targets_to_erase) <= 0: msg = "Could not map given target_id(s) to available devices" raise EraseError( message=msg, return_code=EXIT_CODE_COULD_NOT_MAP_TARGET_ID_TO_DEVICE) for item in targets_to_erase: if method == 'simple': erase_fnc = self._erase_board_simple elif method == 'pyocd': erase_fnc = self._erase_board_with_pyocd elif method == 'edbg': raise EraseError(message="egdb not supported", return_code=EXIT_CODE_IMPLEMENTATION_MISSING) else: raise EraseError( message="Selected method {} not supported".format(method), return_code=EXIT_CODE_MISUSE_CMD) erase_fnc(target=item, no_reset=no_reset) return EXIT_CODE_SUCCESS
def reset_board(self, serial_port): """ :param serial_port: board serial port :return: return exit code based on if successfully reset a board """ from mbed_flasher.flashers.enhancedserial import EnhancedSerial from serial.serialutil import SerialException try: port = EnhancedSerial(serial_port) except SerialException as err: self.logger.error(err) # SerialException.message is type "string", it has 'find' # pylint: disable=no-member if err.message.find('could not open port') != -1: self.logger.error( 'Reset could not be given. Close your Serial connection to device.' ) raise EraseError(message="reset could not be sent", return_code=EXIT_CODE_SERIAL_PORT_OPEN_FAILED) port.baudrate = 115200 port.timeout = 1 port.xonxoff = False port.rtscts = False port.flushInput() port.flushOutput() if port: self.logger.info("sendBreak to device to reboot") result = port.safe_send_break() if result: self.logger.info("reset completed") else: raise EraseError(message="reset failed", return_code=EXIT_CODE_SERIAL_RESET_FAILED) port.close() return EXIT_CODE_SUCCESS
def subcmd_erase_handler(self, args): """ erase command handler """ eraser = Erase() if not args.tid: msg = "Target_id is missing" raise EraseError(message=msg, return_code=EXIT_CODE_TARGET_ID_MISSING) ids = self.parse_id_to_devices(args.tid) return eraser.erase(target_id=ids, no_reset=args.no_reset, method=args.method)
def _erase_board_with_pyocd(self, target, no_reset): try: from pyOCD.board import MbedBoard from pyOCD.pyDAPAccess import DAPAccessIntf except ImportError: raise EraseError(message="pyOCD is not installed", return_code=EXIT_CODE_PYOCD_MISSING) target_id = target["target_id"] board = MbedBoard.chooseBoard(board_id=target_id) self.logger.info("erasing device: %s", target_id) ocd_target = board.target flash = ocd_target.flash try: flash.eraseAll() if not no_reset: ocd_target.reset() except DAPAccessIntf.TransferFaultError as error: raise EraseError(message=error, return_code=EXIT_CODE_PYOCD_ERASE_FAILED) self.logger.info("erase completed for target: %s", target_id) return EXIT_CODE_SUCCESS
def _can_be_erased(target): """ Check if target can be erased. :param target: target board to be checked :return: None if can be erased, raises otherwise """ try: with open(join(target["mount_point"], 'DETAILS.TXT'), 'rb') as new_file: details_txt = new_file.readlines() except (OSError, IOError): raise EraseError(message="No DETAILS.TXT found", return_code=EXIT_CODE_IMPLEMENTATION_MISSING) automation_activated = False daplink_version = 0 for line in details_txt: if line.find(b"Automation allowed: 1") != -1: automation_activated = True if line.find(b"Interface Version") != -1: try: if six.PY2: daplink_version = int(line.split(' ')[-1]) else: daplink_version = int(line.decode('utf-8').split(' ')[-1]) except (IndexError, ValueError): raise EraseError(message="Failed to parse DAPLINK version from DETAILS.TXT", return_code=EXIT_CODE_IMPLEMENTATION_MISSING) if not automation_activated: msg = "Selected device does not have automation activated in DAPLINK" raise EraseError(message=msg, return_code=EXIT_CODE_IMPLEMENTATION_MISSING) if daplink_version < ERASE_DAPLINK_SUPPORT_VERSION: msg = "Selected device has Daplink version {}," \ "erasing supported from version {} onwards". \ format(daplink_version, ERASE_DAPLINK_SUPPORT_VERSION) raise EraseError(message=msg, return_code=EXIT_CODE_IMPLEMENTATION_MISSING)
def subcmd_erase_handler(self, args): """ erase command handler """ eraser = Erase() if args.tid: ids = self.parse_id_to_devices(args.tid) if isinstance(ids, int): retcode = ids else: retcode = eraser.erase(target_id=ids, no_reset=args.no_reset, method=args.method) else: msg = "Target_id is missing" print(msg) raise EraseError(message=msg, return_code=EXIT_CODE_TARGET_ID_MISSING) return retcode
def test_can_be_risen(self): with self.assertRaises(FlashError) as cm: raise EraseError(message="test", return_code=0) self.assertEqual(cm.exception.message, "test") self.assertEqual(cm.exception.return_code, 0)
def _erase_board_simple(self, target, no_reset): """ :param target: target to which perform the erase :param no_reset: erase with/without reset :return: exit code """ if 'mount_point' not in target: raise EraseError(message="mount point missing from target", return_code=EXIT_CODE_MOUNT_POINT_MISSING) if 'serial_port' not in target: raise EraseError(message="serial port missing from target", return_code=EXIT_CODE_SERIAL_PORT_MISSING) automation_activated = False daplink_version = 0 if not isfile(join(target["mount_point"], 'DETAILS.TXT')): raise EraseError(message="No DETAILS.TXT found", return_code=EXIT_CODE_IMPLEMENTATION_MISSING) self.logger.debug(join(target["mount_point"], 'DETAILS.TXT')) with open(join(target["mount_point"], 'DETAILS.TXT'), 'rb') as new_file: for line in new_file: if line.find(b"Automation allowed: 1") != -1: automation_activated = True if line.find(b"Interface Version") != -1: try: if six.PY2: daplink_version = int(line.split(' ')[-1]) else: daplink_version = int( line.decode('utf-8').split(' ')[-1]) except (IndexError, ValueError): raise EraseError( message= "Failed to parse DAPLINK version from DETAILS.TXT", return_code=EXIT_CODE_IMPLEMENTATION_MISSING) if not automation_activated: msg = "Selected device does not have automation activated in DAPLINK" raise EraseError(message=msg, return_code=EXIT_CODE_IMPLEMENTATION_MISSING) if daplink_version < ERASE_DAPLINK_SUPPORT_VERSION: msg = "Selected device has Daplink version {}," \ "erasing supported from version {} onwards".\ format(daplink_version, ERASE_DAPLINK_SUPPORT_VERSION) raise EraseError(message=msg, return_code=EXIT_CODE_IMPLEMENTATION_MISSING) with open(join(target["mount_point"], 'ERASE.ACT'), 'wb'): pass auto_thread = Thread(target=self.wait_to_disappear, args=(target["mount_point"], )) auto_thread.start() while auto_thread.is_alive(): auto_thread.join(0.5) target = FlasherMbed.refresh_target(target["target_id"]) if not target: raise EraseError(message="target id is missing", return_code=EXIT_CODE_TARGET_ID_MISSING) auto_thread = Thread(target=self.runner, args=(target["mount_point"], 'ERASE.ACT')) auto_thread.start() while auto_thread.is_alive(): auto_thread.join(0.5) if not no_reset: success = self.reset_board(target["serial_port"]) if success != 0: raise EraseError(message="erase failed", return_code=success) self.logger.info("erase %s completed", target['target_id']) return EXIT_CODE_SUCCESS