def read_target_memory(self, addr, size, resume=True): assert self.get_mode() == self.MODE_IF with ConnectHelper.session_with_chosen_probe( unique_id=self.get_unique_id(), resume_on_disconnect=resume) as session: data = session.target.read_memory_block8(addr, size) return bytearray(data)
def test_connect(connect_mode, expected_state, resume): print("Connecting with connect_mode=%s" % connect_mode) live_session = ConnectHelper.session_with_chosen_probe( unique_id=board_id, init_board=False, connect_mode=connect_mode, resume_on_disconnect=resume, **get_session_options()) live_session.open() live_board = live_session.board print("Verifying target is", STATE_NAMES.get(expected_state, "unknown")) actualState = live_board.target.get_state() # Accept sleeping for running, as a hack to work around nRF52840-DK test binary. # TODO remove sleeping hack. if (actualState == expected_state) \ or (expected_state == RUNNING and actualState == Target.TARGET_SLEEPING): passed = 1 print("TEST PASSED") else: passed = 0 print("TEST FAILED (state={}, expected={})".format( STATE_NAMES.get(actualState, "unknown"), STATE_NAMES.get(expected_state, "unknown"))) print("Disconnecting with resume=%s" % resume) live_session.close() live_session = None return passed
def _read_continuous_memory(address=0x0, count=4): """Read any continuous memory area from the micro:bit. Reads the contents of any micro:bit continuous memory area, starting from the 'address' argument for as many bytes as indicated by 'count'. There is no input sanitation in this function and is the responsibility of the caller to input values within range of the target board or deal with any exceptions raised by PyOCD. :param address: Integer indicating the start address to read. :param count: Integer, how many bytes to read. :return: A list of integers, each representing a byte of data. """ read_data = None try: with ConnectHelper.session_with_chosen_probe( blocking=False, auto_unlock=False, halt_on_connect=True, resume_on_disconnect=True, ) as session: board = session.board target = board.target read_data = target.read_memory_block8(address, count) except Exception as e: raise Exception("{}\nDid not find any connected boards.".format( str(e))) return read_data
def execute(self, capability, *args, **kwargs): """! Executes capability by name @param capability Capability name @param args Additional arguments @param kwargs Additional arguments @details Each capability e.g. may directly just call some command line program or execute building pythonic function @return Capability call return value """ if not PYOCD_PRESENT: self.print_plugin_error( 'The "pyocd" feature is not installed. Please run ' '"pip install mbed-os-tools[pyocd]" to enable the "pyocd" reset plugin.' ) return False if not kwargs['target_id']: self.print_plugin_error("Error: target_id not set") return False result = False if self.check_parameters(capability, *args, **kwargs) is True: if kwargs['target_id']: if capability == 'pyocd': target_id = kwargs['target_id'] with ConnectHelper.session_with_chosen_probe( unique_id=target_id, resume_on_disconnect=False) as session: session.target.reset() session.target.resume() result = True return result
def _connect(self): """Connect PyOCD to the main micro:bit microcontroller.""" if not self.session: try: self.session = ConnectHelper.session_with_chosen_probe( blocking=False, auto_unlock=False, halt_on_connect=True, resume_on_disconnect=True, ) if self.session is None: raise Exception("Could not open the debugger session.") self.session.open() self.board = self.session.board self.target = self.board.target self.board_id = self.board.unique_id[:4] except Exception as e: raise Exception( "{}\n{}\n".format(str(e), "-" * 70) + "Error: Did not find any connected boards." ) if self.board_id not in MICROBIT_MEM_REGIONS: self._disconnect() raise Exception("Incompatible board ID from connected device.") self.mem = MICROBIT_MEM_REGIONS[self.board_id]
def validate_boards(data): did_pass = True print('boards', end=' ') p = 'boards' in data and type(data['boards']) is list if p: b = data['boards'] if p: print("PASSED") else: did_pass = False print("FAILED") # Only if we're running this test standalone do we want to compare against the list # of boards returned by ConnectHelper.get_sessions_for_all_connected_probes(). When running in the full # automated test suite, there could be other test jobs running concurrently that have # exclusive access to the boards they are testing. Thus, those boards will not show up # in the return list and this test will fail. if testing_standalone: try: all_sessions = ConnectHelper.get_sessions_for_all_connected_probes( blocking=False) all_mbeds = [x.board for x in all_sessions] p = len(all_mbeds) == len(b) matching_boards = 0 if p: for mbed in all_mbeds: for brd in b: if mbed.unique_id == brd['unique_id']: matching_boards += 1 p = 'info' in brd and 'target' in brd and 'board_name' in brd if not p: break if not p: break p = matching_boards == len(all_mbeds) if p: print("PASSED") else: did_pass = False print("FAILED") except Exception as e: print("FAILED") traceback.print_exc(file=sys.stdout) did_pass = False else: # Check for required keys in all board info dicts. p = True for brd in b: p = ('unique_id' in brd and 'info' in brd and 'target' in brd and 'board_name' in brd) if not p: break if p: print("PASSED") else: did_pass = False print("FAILED") return did_pass
def execute(self, capability, *args, **kwargs): """Reset a target using pyOCD. The "capability" name must be "pyocd". If it isn't this method will just fail. Args: capability: Capability name. Returns: True if the reset was successful, otherwise False. """ if not PYOCD_PRESENT: self.print_plugin_error( 'The "pyocd" feature is not installed. Please run ' '"pip install mbed-os-tools[pyocd]" to enable the "pyocd" reset plugin.' ) return False if not kwargs["target_id"]: self.print_plugin_error("Error: target_id not set") return False result = False if self.check_parameters(capability, *args, **kwargs) is True: if kwargs["target_id"]: if capability == "pyocd": target_id = kwargs["target_id"] with ConnectHelper.session_with_chosen_probe( unique_id=target_id, resume_on_disconnect=False ) as session: session.target.reset() session.target.resume() result = True return result
def open_session(self): if self.session is not None and self.session.is_open: self.session.close() if self.probe is None: QMessageBox.information(self.window, "ERROR", "No probe", QMessageBox.Ok) return target_device = "stm32f103c8" if target_device not in TARGET: QMessageBox.information(self.window, "ERROR", "MCU not supported", QMessageBox.Ok) return self.session = ConnectHelper.session_with_chosen_probe( target_override=target_device, unique_id=self.probe.unique_id) self.session.open() # print(self.probe.unique_id) board = self.session.board self.target = board.target memory_map = board.target.get_memory_map() ram_region = memory_map.get_default_region_of_type(MemoryType.RAM) rom_region = memory_map.get_boot_memory() self.addr_bin = rom_region.start self.ui.flash.setEnabled(True)
def open(self) -> None: """Open PyOCD interface for NXP SPSDK. The PyOCD opening function for SPSDK library to support various DEBUG PROBES. The function is used to initialize the connection to target and enable using debug probe for DAT purposes. :raises ProbeNotFoundError: The probe has not found :raises DebugMailBoxAPNotFoundError: The debug mailbox access port NOT found :raises DebugProbeError: The PyOCD cannot establish communication with target """ try: self.pyocd_session = ConnectHelper.session_with_chosen_probe( blocking=False, unique_id=self.hardware_id) if self.pyocd_session is None: raise ProbeNotFoundError("No probe available!") self.pyocd_session.options.set("probe_all_aps", True) self.pyocd_session.delegate = self self.pyocd_session.open() logger.info( f"PyOCD connected via {self.pyocd_session.probe.product_name} probe." ) except PyOCDError: raise DebugProbeError( "PyOCD cannot establish communication with target.") self.di = self._get_dmbox_ap() # TODO move this functionality into higher level of code if self.di is None: raise DebugMailBoxAPNotFoundError( "No debug mail box access point available!")
def test_connect(halt_on_connect, expected_state, resume): print("Connecting with halt_on_connect=%s" % halt_on_connect) live_session = ConnectHelper.session_with_chosen_probe( board_id=board_id, init_board=False, halt_on_connect=halt_on_connect, resume_on_disconnect=resume, **get_session_options()) live_session.open() live_board = live_session.board print("Verifying target is", STATE_NAMES.get(expected_state, "unknown")) actualState = live_board.target.get_state() # Accept sleeping for running, as a hack to work around nRF52840-DK test binary. # TODO remove sleeping hack. if (actualState == expected_state) \ or (expected_state == RUNNING and actualState == Target.TARGET_SLEEPING): passed = 1 print("TEST PASSED") else: passed = 0 print("TEST FAILED (state={}, expected={})".format( STATE_NAMES.get(actualState, "unknown"), STATE_NAMES.get(expected_state, "unknown"))) print("Disconnecting with resume=%s" % resume) live_session.close() live_session = None return passed
def __init__(self): app = QApplication(sys.argv) self.window = QWidget() self.ui = Ui_Form() self.ui.setupUi(self.window) self.session = None probes = ConnectHelper.get_all_connected_probes(blocking=False) for probe in probes: self.ui.daplink_list.addItem(probe.description) if len(probes) > 0: self.probe = probes[0] # print(self.probe) else: self.probe = None # logger = logging.getLogger(__name__) # logger.setLevel(level=logging.DEBUG) # StreamHandler # stream_handler = logging.StreamHandler(self.ui.log.append) # stream_handler.setLevel(level=logging.DEBUG) # logger.addHandler(stream_handler) self.ui.flash.clicked.connect(self.flash_device_run) self.ui.update_dap.clicked.connect(self.update_daplink) self.ui.connect.clicked.connect(self.open_session) self.ui.selsec_firmware.clicked.connect(self.select_file) self.ui.daplink_list.currentIndexChanged.connect(self.daplink_change) self.ui.flash.setDisabled(True) self.ui.progressBar.setValue(0) self.window.show() app.exec_()
def open(self) -> None: """Open PyOCD interface for NXP SPSDK. The PyOCD opening function for SPSDK library to support various DEBUG PROBES. The function is used to initialize the connection to target and enable using debug probe for DAT purposes. :raises SPSDKProbeNotFoundError: The probe has not found :raises SPSDKDebugMailBoxAPNotFoundError: The debug mailbox access port NOT found :raises SPSDKDebugProbeError: The PyOCD cannot establish communication with target """ try: self.pyocd_session = ConnectHelper.session_with_chosen_probe( blocking=False, unique_id=self.hardware_id) if self.pyocd_session is None: raise SPSDKProbeNotFoundError("No probe available!") self.pyocd_session.options.set("scan_all_aps", True) self.pyocd_session.delegate = self self.pyocd_session.open() logger.info( f"PyOCD connected via {self.pyocd_session.probe.product_name} probe." ) except PyOCDError as exc: raise SPSDKDebugProbeError( "PyOCD cannot establish communication with target.") from exc self.dbgmlbx_ap = self._get_dmbox_ap() self.mem_ap = self._get_mem_ap() if self.mem_ap is None: logger.warning( "The memory interface not found - probably locked device") if self.dbgmlbx_ap is None: raise SPSDKDebugMailBoxAPNotFoundError( "No debug mail box access point available!")
def search_and_lock(board_id): """Repeatedly lock a board with the given ID""" for _ in range(0, 20): device = DAPAccess.get_device(board_id) device.open() device.close() with ConnectHelper.session_with_chosen_probe(unique_id=board_id): pass
def daplink_change(self): probes = ConnectHelper.get_all_connected_probes(blocking=False) for probe in probes: if probe.description == self.ui.daplink_list.currentText(): self.probe = probe else: self.probe = None
def execute(self, capability, *args, **kwargs): """Flash a firmware image to a device using pyOCD. In this implementation we don't seem to care what the capability name is. Args: capability: Capability name. args: Additional arguments. kwargs: Additional arguments. Returns: True if flashing succeeded, otherwise False. """ if not PYOCD_PRESENT: self.print_plugin_error( 'The "pyocd" feature is not installed. Please run ' '"pip install mbed-os-tools[pyocd]" to enable the "pyocd" copy plugin.' ) return False if not self.check_parameters(capability, *args, **kwargs): return False if not kwargs["image_path"]: self.print_plugin_error("Error: image path not specified") return False if not kwargs["target_id"]: self.print_plugin_error("Error: Target ID") return False target_id = kwargs["target_id"] image_path = os.path.normpath(kwargs["image_path"]) with ConnectHelper.session_with_chosen_probe( unique_id=target_id, resume_on_disconnect=False ) as session: # Performance hack! # Eventually pyOCD will know default clock speed # per target test_clock = 10000000 target_type = session.board.target_type if target_type == "nrf51": # Override clock since 10MHz is too fast test_clock = 1000000 if target_type == "ncs36510": # Override clock since 10MHz is too fast test_clock = 1000000 # Configure link session.probe.set_clock(test_clock) # Program the file programmer = FileProgrammer(session) programmer.program(image_path, format=kwargs["format"]) return True
def update_daplink(self): self.ui.daplink_list.clear() probes = ConnectHelper.get_all_connected_probes(blocking=False) for probe in probes: self.ui.daplink_list.addItem(probe.description) if len(probes) > 0: self.probe = probes[0] else: self.probe = None
def __init__(self, elf_filepath): self.session = ConnectHelper.session_with_chosen_probe( return_first=True, # Assuming that 1 board is attached. Or, we just use the first one. connect_mode='attach') # This will keep the target running. default is 'halt' in which case target.resume() should be called. self.target = self.session.board.target self.target.elf = elf_filepath self.provider = ELFSymbolProvider(self.target.elf)
def connect(self, target_name=None, interface=None, probe_id=None, ap='cm4', blocking=True): """ Connects to target using default debug interface. :param target_name: The target name. :param interface: Debug interface. :param ap: The access port used for communication (cm0 or cm4). :param probe_id: Probe serial number. :param blocking: Specifies whether to wait for a probe to be connected if there are no available probes. :return: True if connected successfully, otherwise False. """ if interface: raise NotImplementedError else: if target_name: logger.info(f'Target: {target_name}') # Search for device in target map with open(TARGET_MAP) as f: file_content = f.read() json_data = json.loads(file_content) for json_target in json_data: if target_name.lower().strip() == json_target.lower( ).strip(): target_name = json_data[json_target][ap.lower()] break options = {'target_override': target_name} else: options = {} if self.wait_for_target is not None: blocking = self.wait_for_target self.session = \ ConnectHelper.session_with_chosen_probe(blocking=blocking, options=options, board_id=probe_id, unique_id=probe_id) if self.session is None: return False self.board = self.session.board self.session.open() self.target = self.board.target self.probe = self.session.probe self.ap = ap self.set_ap(AP.SYS) logger.info(f'Probe ID: {self.probe.unique_id}') return True
def execute(self, capability, *args, **kwargs): """! Executes capability by name @param capability Capability name @param args Additional arguments @param kwargs Additional arguments @return Capability call return value """ if not PYOCD_PRESENT: self.print_plugin_error( 'The "pyocd" feature is not installed. Please run ' '"pip install mbed-os-tools[pyocd]" to enable the "pyocd" copy plugin.' ) return False if not self.check_parameters(capability, *args, **kwargs): return False if not kwargs['image_path']: self.print_plugin_error("Error: image path not specified") return False if not kwargs['target_id']: self.print_plugin_error("Error: Target ID") return False target_id = kwargs['target_id'] image_path = os.path.normpath(kwargs['image_path']) with ConnectHelper.session_with_chosen_probe(unique_id=target_id, resume_on_disconnect=False) as session: # Performance hack! # Eventually pyOCD will know default clock speed # per target test_clock = 10000000 target_type = session.board.target_type if target_type == "nrf51": # Override clock since 10MHz is too fast test_clock = 1000000 if target_type == "ncs36510": # Override clock since 10MHz is too fast test_clock = 1000000 # Configure link session.probe.set_clock(test_clock) # Program the file programmer = FileProgrammer(session) programmer.program(image_path, format=kwargs['format']) return True
def connect(self, target_name=None, interface=None, probe_id=None): """ Connects to target using default debug interface. :param target_name: The target name. :param interface: Debug interface. :param probe_id: Probe serial number. :return: True if connected successfully, otherwise False. """ if interface: raise NotImplementedError else: if target_name: # Search for device in target map with open(TARGET_MAP) as f: file_content = f.read() json_data = json.loads(file_content) for json_target in json_data: if target_name.lower().strip() == json_target.lower( ).strip(): target_name = json_data[json_target] break options = {'target_override': target_name} else: options = {} self.session = ConnectHelper.session_with_chosen_probe( blocking=True, options=options, board_id=probe_id, unique_id=probe_id) if self.session is None: return False self.board = self.session.board self.session.open() self.target = self.board.target self.probe = self.session.probe # Write infinite loop into RAM and start core execution self.halt() # B662 - CPSIE I - Enable IRQ by clearing PRIMASK # E7FE - B - Jump to address (argument is an offset) self.write32(0x08000000, 0xE7FEB662) self.write_reg('pc', 0x08000000) self.write_reg('sp', 0x08001000) self.write_reg('xpsr', 0x01000000) self.resume() return True
def tgt(request): board = None try: session = ConnectHelper.session_with_chosen_probe(blocking=False, return_first=True) except Exception as error: logging.error("Exception during session_with_chosen_probe", exc_info=error) if session is None: pytest.skip("No probe present") return board = session.board session.options['resume_on_disconnect'] = False board.target.reset_stop_on_reset() def cleanup(): board.uninit() request.addfinalizer(cleanup) return board.target
def tgt(request): session = None try: session = ConnectHelper.session_with_chosen_probe(blocking=False, return_first=True) except Exception as error: logging.error("Exception during session_with_chosen_probe", exc_info=error) if session is None: pytest.skip("No probe present") return session.open() session.options['resume_on_disconnect'] = False assert session.target session.target.reset_and_halt() def close_session(): session.close() request.addfinalizer(close_session) return session.target
def __init__(self, path): self.var = {} self.path = path files = os.listdir(path) self.project = '' for file in files: if file.split('.')[-1] == 'uvprojx': self.project = file.replace('.uvprojx', '') if self.project == '': raise NameError("Can't find keil project file") print(path) self.session = ConnectHelper.session_with_chosen_probe() print('ok') self.session.open() print('ok') self.board = self.session.board self.target = self.board.target self.target.elf = os.path.join(path, '%s/%s.axf' % (self.project, self.project)) print(self.target.elf) self.provider = ELFSymbolProvider(self.target.elf)
def tgt(request): board = None try: session = ConnectHelper.session_with_chosen_probe(blocking=False, return_first=True) except Exception as error: logging.error("Exception during session_with_chosen_probe", exc_info=error) if session is None: pytest.skip("No probe present") return board = session.board session.options['resume_on_disconnect'] = False board.target.reset_and_halt() def cleanup(): board.uninit() request.addfinalizer(cleanup) return board.target
def get_connected_probes(cls, hardware_id: str = None ) -> List[ProbeDescription]: """Get all connected probes over PyOCD. This functions returns the list of all connected probes in system by PyOCD package. :param hardware_id: None to list all probes, otherwice the the only probe with matching hardware id is listed. :return: probe_description """ from .utils import DebugProbes probes = DebugProbes() connected_probes = ConnectHelper.get_all_connected_probes( blocking=False, unique_id=hardware_id) for probe in connected_probes: probes.append( ProbeDescription("PyOCD", probe.unique_id, probe.description, DebugProbePyOCD)) return probes
def user_script_test(board_id): with ConnectHelper.session_with_chosen_probe( unique_id=board_id, user_script=TEST_USER_SCRIPT, **get_session_options()) as session: board = session.board target = session.target test_params = get_target_test_params(session) session.probe.set_clock(test_params['test_clock']) memory_map = target.get_memory_map() boot_region = memory_map.get_boot_memory() ram_region = memory_map.get_default_region_of_type(MemoryType.RAM) binary_file = get_test_binary_path(board.test_binary) test_pass_count = 0 test_count = 0 result = UserScriptTestResult() target.reset_and_halt() target.resume() target.halt() target.step() test_count += 1 test_pass_count += 1 print("\nTest Summary:") print("Pass count %i of %i tests" % (test_pass_count, test_count)) if test_pass_count == test_count: print("USER SCRIPT TEST PASSED") else: print("USER SCRIPT TEST FAILED") target.reset() result.passed = test_count == test_pass_count return result
def open_session(self): # print("open session") if self.probe is None: QMessageBox.information(self.window, "ERROR", "No probe", QMessageBox.Ok) return if self.ui.device_list.currentText() is "": QMessageBox.information(self.window, "ERROR", "select mcu first", QMessageBox.Ok) return self.session = ConnectHelper.session_with_chosen_probe( target_override=self.ui.device_list.currentText(), unique_id=self.probe.unique_id) self.session.open() # print(self.probe.unique_id) board = self.session.board self.target = board.target # print("Board's name:%s" % board.name) # print("Board's description:%s" % board.description) # print("Board's target_type:%s" % board.target_type) # print("Board's unique_id:%s" % board.unique_id) # print("Board's test_binary:%s" % board.test_binary) # print("Unique ID: %s" % board.unique_id) memory_map = board.target.get_memory_map() ram_region = memory_map.get_default_region_of_type(MemoryType.RAM) rom_region = memory_map.get_boot_memory() self.addr_bin = rom_region.start self.ui.erase.setEnabled(True) self.ui.flash.setEnabled(True) self.ui.run.setEnabled(True) self.ui.halt.setEnabled(True) self.ui.flash_run.setEnabled(True) self.ui.resume.setEnabled(True)
def stlinkFlash(self): self.Log.write(" Flash PLC use STLink\n") try: with ConnectHelper.session_with_chosen_probe() as session: target = session.target # todo:stlink read cpu id # if self.dev_id and stm._dev_id != self.dev_id: # self.Log.write_error(_("MCU ID Don't Match!")) # return if self.prgBoot.IsChecked(): self.Log.write(_('Flash BootLoader ...')) with FileProgrammer(session, chip_erase='auto', smart_flash=True) as programmer: programmer.program(self.bootbin, file_format='bin', base_address=0x8000000) if self.prgRte.IsChecked(): self.Log.write(_('Flash RTE firmware ...')) with FileProgrammer(session, chip_erase='auto', smart_flash=True) as programmer: programmer.program(self.rtebin, file_format='bin', base_address=self.adrRte) if self.prgApp.IsChecked(): self.Log.write(_('Flash PLC APP ...')) with FileProgrammer(session, chip_erase='auto', smart_flash=True) as programmer: programmer.program(self.appBin, file_format='bin', base_address=self.adrApp) self.Log.write(_('Flash end.')) except Exception as e: self.Log.write_error(_('Error:%s') % str(e)) self.Log.write_error(_('Flash Failed.'))
def get_connected_probes(cls, hardware_id: str = None, user_params: Dict = None) -> list: """Get all connected probes over PyOCD. This functions returns the list of all connected probes in system by PyOCD package. :param hardware_id: None to list all probes, otherwise the the only probe with matching hardware id is listed. :param user_params: The user params dictionary :return: probe_description """ # pylint: disable=import-outside-toplevel from .utils import DebugProbes, ProbeDescription probes = DebugProbes() connected_probes = ConnectHelper.get_all_connected_probes( blocking=False, unique_id=hardware_id) for probe in connected_probes: probes.append( ProbeDescription("PyOCD", probe.unique_id, probe.description, DebugProbePyOCD)) return probes
def flash_loader_test(board_id): with ConnectHelper.session_with_chosen_probe(unique_id=board_id, **get_session_options()) as session: board = session.board target = session.target target_type = board.target_type test_clock = 10000000 if target_type == "nrf51": # Override clock since 10MHz is too fast test_clock = 1000000 if target_type == "ncs36510": # Override clock since 10MHz is too fast test_clock = 1000000 session.probe.set_clock(test_clock) memory_map = board.target.get_memory_map() boot_region = memory_map.get_boot_memory() boot_start_addr = boot_region.start boot_end_addr = boot_region.end boot_blocksize = boot_region.blocksize test_pass_count = 0 test_count = 0 result = FlashLoaderTestResult() binary_file_path = os.path.join(parentdir, 'binaries', board.test_binary) with open(binary_file_path, "rb") as f: data = list(bytearray(f.read())) data_length = len(data) print("\n------ Test Basic Load ------") loader = FlashLoader(session, chip_erase=False) loader.add_data(boot_start_addr, data) loader.commit() verify_data = target.read_memory_block8(boot_start_addr, data_length) if same(verify_data, data): print("TEST PASSED") test_pass_count += 1 else: print("TEST FAILED") test_count += 1 print("\n------ Test Load Sector Erase ------") test_data = [0x55] * boot_blocksize addr = (boot_end_addr + 1) - (boot_blocksize * 2) loader = FlashLoader(session, chip_erase=False) loader.add_data(addr, test_data) loader.add_data(addr + boot_blocksize, test_data) loader.commit() verify_data = target.read_memory_block8(addr, boot_blocksize * 2) verify_data2 = target.read_memory_block8(boot_start_addr, data_length) if same(verify_data, test_data * 2) and same(verify_data2, data): print("TEST PASSED") test_pass_count += 1 else: print("TEST FAILED") test_count += 1 print("\n------ Test Basic Sector Erase ------") eraser = FlashEraser(session, FlashEraser.Mode.SECTOR) eraser.erase(["0x%x+0x%x" % (addr, boot_blocksize)]) verify_data = target.read_memory_block8(addr, boot_blocksize) if target.memory_map.get_region_for_address(addr).is_erased(verify_data): print("TEST PASSED") test_pass_count += 1 else: print("TEST FAILED") test_count += 1 print("\n------ Test Load Chip Erase ------") loader = FlashLoader(session, chip_erase=True) loader.add_data(boot_start_addr, data) loader.commit() verify_data = target.read_memory_block8(boot_start_addr, data_length) verify_data2 = target.read_memory_block8(addr, boot_blocksize * 2) if same(verify_data, data) and target.memory_map.get_region_for_address(addr).is_erased(verify_data2): print("TEST PASSED") test_pass_count += 1 else: print("TEST FAILED") test_count += 1 print("\n------ Test Binary File Load ------") programmer = FileProgrammer(session) programmer.program(binary_file_path, format='bin', base_address=boot_start_addr) verify_data = target.read_memory_block8(boot_start_addr, data_length) if same(verify_data, data): print("TEST PASSED") test_pass_count += 1 else: print("TEST FAILED") test_count += 1 print("\n\nTest Summary:") print("Pass count %i of %i tests" % (test_pass_count, test_count)) if test_pass_count == test_count: print("FLASH TEST SCRIPT PASSED") else: print("FLASH TEST SCRIPT FAILED") target.reset() result.passed = test_count == test_pass_count return result
def basic_test(board_id, file): with ConnectHelper.session_with_chosen_probe(unique_id=board_id, **get_session_options()) as session: board = session.board addr = 0 size = 0 f = None binary_file = "l1_" if file is None: binary_file = os.path.join(parentdir, 'binaries', board.test_binary) else: binary_file = file print("binary file: %s" % binary_file) memory_map = board.target.get_memory_map() ram_region = memory_map.get_first_region_of_type(MemoryType.RAM) rom_region = memory_map.get_boot_memory() addr = ram_region.start size = 0x502 addr_bin = rom_region.start addr_flash = rom_region.start + rom_region.length // 2 target = board.target flash = rom_region.flash print("\n\n------ GET Unique ID ------") print("Unique ID: %s" % board.unique_id) print("\n\n------ TEST READ / WRITE CORE REGISTER ------") pc = target.read_core_register('pc') print("initial pc: 0x%X" % target.read_core_register('pc')) # write in pc dummy value target.write_core_register('pc', 0x3D82) print("now pc: 0x%X" % target.read_core_register('pc')) # write initial pc value target.write_core_register('pc', pc) print("initial pc value rewritten: 0x%X" % target.read_core_register('pc')) msp = target.read_core_register('msp') psp = target.read_core_register('psp') print("MSP = 0x%08x; PSP = 0x%08x" % (msp, psp)) control = target.read_core_register('control') faultmask = target.read_core_register('faultmask') basepri = target.read_core_register('basepri') primask = target.read_core_register('primask') print("CONTROL = 0x%02x; FAULTMASK = 0x%02x; BASEPRI = 0x%02x; PRIMASK = 0x%02x" % (control, faultmask, basepri, primask)) target.write_core_register('primask', 1) newPrimask = target.read_core_register('primask') print("New PRIMASK = 0x%02x" % newPrimask) target.write_core_register('primask', primask) newPrimask = target.read_core_register('primask') print("Restored PRIMASK = 0x%02x" % newPrimask) if target.has_fpu: s0 = target.read_core_register('s0') print("S0 = %g (0x%08x)" % (s0, float32_to_u32(s0))) target.write_core_register('s0', math.pi) newS0 = target.read_core_register('s0') print("New S0 = %g (0x%08x)" % (newS0, float32_to_u32(newS0))) target.write_core_register('s0', s0) newS0 = target.read_core_register('s0') print("Restored S0 = %g (0x%08x)" % (newS0, float32_to_u32(newS0))) print("\n\n------ TEST HALT / RESUME ------") print("resume") target.resume() sleep(0.2) print("halt") target.halt() print("HALT: pc: 0x%X" % target.read_core_register('pc')) sleep(0.2) print("\n\n------ TEST STEP ------") print("reset and halt") target.reset_stop_on_reset() currentPC = target.read_core_register('pc') print("HALT: pc: 0x%X" % currentPC) sleep(0.2) for i in range(4): print("step") target.step() newPC = target.read_core_register('pc') print("STEP: pc: 0x%X" % newPC) currentPC = newPC sleep(0.2) print("\n\n------ TEST READ / WRITE MEMORY ------") target.halt() print("READ32/WRITE32") val = randrange(0, 0xffffffff) print("write32 0x%X at 0x%X" % (val, addr)) target.write_memory(addr, val) res = target.read_memory(addr) print("read32 at 0x%X: 0x%X" % (addr, res)) if res != val: print("ERROR in READ/WRITE 32") print("\nREAD16/WRITE16") val = randrange(0, 0xffff) print("write16 0x%X at 0x%X" % (val, addr + 2)) target.write_memory(addr + 2, val, 16) res = target.read_memory(addr + 2, 16) print("read16 at 0x%X: 0x%X" % (addr + 2, res)) if res != val: print("ERROR in READ/WRITE 16") print("\nREAD8/WRITE8") val = randrange(0, 0xff) print("write8 0x%X at 0x%X" % (val, addr + 1)) target.write_memory(addr + 1, val, 8) res = target.read_memory(addr + 1, 8) print("read8 at 0x%X: 0x%X" % (addr + 1, res)) if res != val: print("ERROR in READ/WRITE 8") print("\n\n------ TEST READ / WRITE MEMORY BLOCK ------") data = [randrange(1, 50) for x in range(size)] target.write_memory_block8(addr, data) block = target.read_memory_block8(addr, size) error = False for i in range(len(block)): if (block[i] != data[i]): error = True print("ERROR: 0x%X, 0x%X, 0x%X!!!" % ((addr + i), block[i], data[i])) if error: print("TEST FAILED") else: print("TEST PASSED") print("\n\n------ TEST RESET ------") target.reset() sleep(0.1) target.halt() for i in range(5): target.step() print("pc: 0x%X" % target.read_core_register('pc')) print("\n\n------ TEST PROGRAM/ERASE PAGE ------") # Fill 3 pages with 0x55 page_size = flash.get_page_info(addr_flash).size fill = [0x55] * page_size for i in range(0, 3): address = addr_flash + page_size * i # Test only supports a location with 3 aligned # pages of the same size current_page_size = flash.get_page_info(addr_flash).size assert page_size == current_page_size assert address % current_page_size == 0 flash.init(flash.Operation.ERASE) flash.erase_page(address) flash.uninit() flash.init(flash.Operation.PROGRAM) flash.program_page(address, fill) flash.uninit() # Erase the middle page flash.init(flash.Operation.ERASE) flash.erase_page(addr_flash + page_size) flash.cleanup() # Verify the 1st and 3rd page were not erased, and that the 2nd page is fully erased data = target.read_memory_block8(addr_flash, page_size * 3) expected = fill + [0xFF] * page_size + fill if data == expected: print("TEST PASSED") else: print("TEST FAILED") print("\n\n----- FLASH NEW BINARY -----") FileProgrammer(session).program(binary_file, base_address=addr_bin) target.reset()
def test_gdb(board_id=None, n=0): temp_test_elf_name = None result = GdbTestResult() with ConnectHelper.session_with_chosen_probe(board_id=board_id, **get_session_options()) as session: board = session.board memory_map = board.target.get_memory_map() ram_region = memory_map.get_first_region_of_type(MemoryType.RAM) rom_region = memory_map.get_boot_memory() target_type = board.target_type binary_file = os.path.join(parentdir, 'binaries', board.test_binary) if board_id is None: board_id = board.unique_id test_clock = 10000000 test_port = 3333 + n telnet_port = 4444 + n error_on_invalid_access = True # Hardware breakpoints are not supported above 0x20000000 on # CortexM devices ignore_hw_bkpt_result = 1 if ram_region.start >= 0x20000000 else 0 if target_type in ("nrf51", "nrf52", "nrf52840"): # Override clock since 10MHz is too fast test_clock = 1000000 # Reading invalid ram returns 0 or nrf51 error_on_invalid_access = False if target_type == "ncs36510": # Override clock since 10MHz is too fast test_clock = 1000000 # Program with initial test image FileProgrammer(session).program(binary_file, base_address=rom_region.start) # Generate an elf from the binary test file. temp_test_elf_name = tempfile.mktemp('.elf') objcopyOutput = check_output([OBJCOPY, "-v", "-I", "binary", "-O", "elf32-littlearm", "-B", "arm", "-S", "--set-start", "0x%x" % rom_region.start, "--change-addresses", "0x%x" % rom_region.start, binary_file, temp_test_elf_name], stderr=STDOUT) print(to_str_safe(objcopyOutput)) # Need to escape backslashes on Windows. if sys.platform.startswith('win'): temp_test_elf_name = temp_test_elf_name.replace('\\', '\\\\') # Write out the test configuration test_params = { "test_port" : test_port, "rom_start" : rom_region.start, "rom_length" : rom_region.length, "ram_start" : ram_region.start, "ram_length" : ram_region.length, "invalid_start" : 0x3E000000, "invalid_length" : 0x1000, "expect_error_on_invalid_access" : error_on_invalid_access, "ignore_hw_bkpt_result" : ignore_hw_bkpt_result, "test_elf" : temp_test_elf_name, } test_param_filename = "test_params%d.txt" % n with open(test_param_filename, "w") as f: f.write(json.dumps(test_params)) # Run the test gdb = [PYTHON_GDB, "-ex", "set $testn=%d" % n, "--command=gdb_script.py"] output_filename = "output_%s_%d.txt" % (board.target_type, n) with open(output_filename, "w") as f: program = Popen(gdb, stdin=PIPE, stdout=f, stderr=STDOUT) args = ['gdbserver', '--port=%i' % test_port, "--telnet-port=%i" % telnet_port, "--frequency=%i" % test_clock, "--uid=%s" % board_id, '-Oboard_config_file=test_boards.json' ] server = PyOCDTool() server.run(args) program.wait() # Read back the result test_result_filename = "test_results%d.txt" % n with open(test_result_filename, "r") as f: test_result = json.loads(f.read()) # Print results if set(TEST_RESULT_KEYS).issubset(test_result): print("----------------Test Results----------------") print("HW breakpoint count: %s" % test_result["breakpoint_count"]) print("Watchpoint count: %s" % test_result["watchpoint_count"]) print("Average instruction step time: %s" % test_result["step_time_si"]) print("Average single step time: %s" % test_result["step_time_s"]) print("Average over step time: %s" % test_result["step_time_n"]) print("Failure count: %i" % test_result["fail_count"]) result.passed = test_result["fail_count"] == 0 else: result.passed = False # Cleanup if temp_test_elf_name and os.path.exists(temp_test_elf_name): os.remove(temp_test_elf_name) os.remove(test_result_filename) os.remove(test_param_filename) return result
def main(): parser = argparse.ArgumentParser(description='pyOCD automated testing') parser.add_argument('-d', '--debug', action="store_true", help='Enable debug logging') parser.add_argument('-q', '--quiet', action="store_true", help='Hide test progress for 1 job') parser.add_argument('-j', '--jobs', action="store", default=1, type=int, metavar="JOBS", help='Set number of concurrent board tests (default is 1)') parser.add_argument('-b', '--board', action="append", metavar="ID", help="Limit testing to boards with specified unique IDs. Multiple boards can be listed.") args = parser.parse_args() # Force jobs to 1 when running under CI until concurrency issues with enumerating boards are # solved. Specifically, the connect test has intermittently failed to open boards on Linux and # Win7. This is only done under CI, and in this script, to make testing concurrent runs easy. if 'CI_TEST' in os.environ: args.jobs = 1 # Disable multiple jobs on macOS prior to Python 3.4. By default, multiprocessing uses # fork() on Unix, which doesn't work on the Mac because CoreFoundation requires exec() # to be used in order to init correctly (CoreFoundation is used in hidapi). Only on Python # version 3.4+ is the multiprocessing.set_start_method() API available that lets us # switch to the 'spawn' method, i.e. exec(). if args.jobs > 1 and sys.platform.startswith('darwin') and sys.version_info[0:2] < (3, 4): print("WARNING: Cannot support multiple jobs on macOS prior to Python 3.4. Forcing 1 job.") args.jobs = 1 # Setup logging based on concurrency and quiet option. level = logging.DEBUG if args.debug else logging.INFO if args.jobs == 1 and not args.quiet: # Create common log file. if os.path.exists(LOG_FILE): os.remove(LOG_FILE) logToConsole = True commonLogFile = open(LOG_FILE, "a") else: logToConsole = False commonLogFile = None board_list = [] result_list = [] # Put together list of boards to test board_list = ConnectHelper.get_all_connected_probes(blocking=False) board_id_list = sorted(b.unique_id for b in board_list) # Filter boards. if args.board: board_id_list = [b for b in board_id_list if any(c for c in args.board if c.lower() in b.lower())] # If only 1 job was requested, don't bother spawning processes. start = time() if args.jobs == 1: for n, board_id in enumerate(board_id_list): result_list += test_board(board_id, n, level, logToConsole, commonLogFile) else: # Create a pool of processes to run tests. try: pool = mp.Pool(args.jobs) # Issue board test job to process pool. async_results = [pool.apply_async(test_board, (board_id, n, level, logToConsole, commonLogFile)) for n, board_id in enumerate(board_id_list)] # Gather results. for r in async_results: result_list += r.get(timeout=JOB_TIMEOUT) finally: pool.close() pool.join() stop = time() test_time = (stop - start) print_summary(test_list, result_list, test_time) with open(SUMMARY_FILE, "w") as output_file: print_summary(test_list, result_list, test_time, output_file) generate_xml_results(result_list) exit_val = 0 if Test.all_tests_pass(result_list) else -1 exit(exit_val)
def test_mass_storage(workspace, parent_test): """Test the mass storage endpoint Requirements: None Positional arguments: filename - A string containing the name of the file to load Return: True if the test passed, False otherwise """ test_info = parent_test.create_subtest('test_mass_storage') # Setup test board = workspace.board target = workspace.target bin_file = target.bin_path hex_file = target.hex_path with open(bin_file, 'rb') as test_file: bin_file_contents = bytearray(test_file.read()) with open(hex_file, 'rb') as test_file: hex_file_contents = bytearray(test_file.read()) blank_bin_contents = bytearray([0xff]) * 0x2000 vectors_and_pad = bin_file_contents[0:32] + blank_bin_contents locked_when_erased = board.get_board_id() in info.BOARD_ID_LOCKED_WHEN_ERASED page_erase_supported = board.get_board_id() in info.BOARD_ID_SUPPORTING_PAGE_ERASE bad_vector_table = target.name in info.TARGET_WITH_BAD_VECTOR_TABLE_LIST intel_hex = intelhex.IntelHex(hex_file) addresses = intel_hex.addresses() addresses.sort() start = addresses[0] # Test loading a binary file with shutils if not bad_vector_table: test = MassStorageTester(board, test_info, "Shutil binary file load") test.set_shutils_copy(bin_file) test.set_expected_data(bin_file_contents, start) test.run() # Test loading a binary file with flushes if not bad_vector_table: test = MassStorageTester(board, test_info, "Load binary with flushes") test.set_programming_data(bin_file_contents, 'image.bin') test.set_expected_data(bin_file_contents, start) test.set_flush_size(0x1000) test.run() # Test loading a hex file with shutils test = MassStorageTester(board, test_info, "Shutil hex file load") test.set_shutils_copy(hex_file) test.set_expected_data(bin_file_contents, start) test.run() # Test loading a hex file with flushes test = MassStorageTester(board, test_info, "Load hex with flushes") test.set_programming_data(hex_file_contents, 'image.hex') test.set_expected_data(bin_file_contents, start) test.set_flush_size(0x1000) test.run() # Test loading a binary smaller than a sector if not bad_vector_table: test = MassStorageTester(board, test_info, "Load .bin smaller than sector") test_data_size = 0x789 test_data = bin_file_contents[0:0 + test_data_size] test.set_programming_data(test_data, 'image.bin') test.set_expected_data(test_data, start) test.run() # Test loading a blank binary - this image should cause a timeout # since it doesn't have a valid vector table test = MassStorageTester(board, test_info, "Load blank binary") test.set_programming_data(blank_bin_contents, 'image.bin') test.set_expected_failure_msg("The transfer timed out.", "transient, user") test.set_expected_data(None, start) test.run() # Test loading a blank binary with a vector table but padded with 0xFF. # A blank image can lock some devices. if not bad_vector_table: test = MassStorageTester(board, test_info, "Load blank binary + vector table") test.set_programming_data(vectors_and_pad, 'image.bin') if locked_when_erased: test.set_expected_failure_msg("The interface firmware ABORTED programming. Image is trying to set security bits", "user") test.set_expected_data(None, start) else: test.set_expected_data(vectors_and_pad, start) test.run() # Test a normal load with dummy files created beforehand test = MassStorageTester(board, test_info, "Extra Files") test.set_programming_data(hex_file_contents, 'image.hex') test.add_mock_dirs(MOCK_DIR_LIST) test.add_mock_files(MOCK_FILE_LIST) test.add_mock_dirs_after_load(MOCK_DIR_LIST_AFTER) test.add_mock_files_after_load(MOCK_FILE_LIST_AFTER) test.set_expected_data(bin_file_contents, start) test.run() # Note - it is not unexpected for an "Extra Files" test to fail # when a binary file is loaded, since there is no way to # tell where the end of the file is. if page_erase_supported: # Test page erase, a.k.a. sector erase by generating iHex with discrete addresses, # programing the device then comparing device memory against expected content. test = MassStorageTester(board, test_info, "Sector Erase") with ConnectHelper.session_with_chosen_probe(unique_id=board.get_unique_id(), open_session=False) as session: memory_map = session.target.memory_map flash_regions = memory_map.get_regions_of_type(MemoryType.FLASH) max_address = intel_hex.maxaddr() # Create an object. We'll add the addresses of unused even blocks to it first, then unused odd blocks for each region ih = intelhex.IntelHex() # Add the content from test bin first expected_bin_contents = bin_file_contents for region_index, the_region in enumerate(flash_regions): if the_region.is_boot_memory is False: continue flash_start = the_region.start flash_length = the_region.length block_size = the_region.blocksize number_of_blocks = flash_length // block_size # Sanity check the regions are contiguous if region_index: assert flash_start == (flash_regions[region_index - 1].start + flash_regions[region_index - 1].length) if max_address >= (flash_start + flash_length): # This bin image crosses this region, don't modify the content, go to the next region continue elif max_address >= flash_start: # This bin image occupies partial region. Skip the used portion to avoid touching any security bits and pad the rest expected_bin_contents += bytearray([0xff]) * (flash_start + flash_length - max_address - 1) # Calculate the starting block after the image to avoid stumbling upon security bits block_start = (max_address - flash_start) // block_size + 1 else: # This bin image doesn't reach this region expected_bin_contents += bytearray([0xff]) * flash_length block_start = 0 # For all even blocks, overwrite all addresses with 0x55; for all odd blocks, overwrite all addresses with 0xAA for pass_number in range (2): if pass_number == 0: modifier = 0x55 else: modifier = 0xAA block_start += 1 for block_idx in range(block_start, number_of_blocks, 2): for address_to_modify in range (flash_start + block_idx * block_size, flash_start + (block_idx + 1) * block_size): expected_bin_contents[address_to_modify] = modifier ih[address_to_modify] = modifier if not os.path.exists("tmp"): os.makedirs("tmp") # Write out the modified iHex to file ih.tofile("tmp/interleave.hex", format='hex') # Load this hex file with shutils test.set_shutils_copy("tmp/interleave.hex") test.set_expected_data(expected_bin_contents, start) test.run() # Finally, load a good binary test = MassStorageTester(board, test_info, "Load good file to restore state") test.set_programming_data(hex_file_contents, 'image.hex') test.set_expected_data(bin_file_contents, start) test.run()
def cortex_test(board_id): with ConnectHelper.session_with_chosen_probe(unique_id=board_id, **get_session_options()) as session: board = session.board target_type = board.target_type binary_file = os.path.join(parentdir, 'binaries', board.test_binary) test_params = get_target_test_params(session) test_clock = test_params['test_clock'] addr_invalid = 0x3E000000 # Last 16MB of ARM SRAM region - typically empty expect_invalid_access_to_fail = test_params['error_on_invalid_access'] memory_map = board.target.get_memory_map() ram_region = memory_map.get_first_region_of_type(MemoryType.RAM) rom_region = memory_map.get_boot_memory() addr = ram_region.start size = 0x502 addr_bin = rom_region.start target = board.target probe = session.probe probe.set_clock(test_clock) test_pass_count = 0 test_count = 0 result = CortexTestResult() debugContext = target.get_target_context() gdbFacade = GDBDebugContextFacade(debugContext) print("\n\n----- FLASH NEW BINARY BEFORE TEST -----") FileProgrammer(session).program(binary_file, base_address=addr_bin) # Let the target run for a bit so it # can initialize the watchdog if it needs to target.resume() sleep(0.2) target.halt() print("PROGRAMMING COMPLETE") print("\n\n----- TESTING CORTEX-M PERFORMANCE -----") test_time = test_function(session, gdbFacade.get_t_response) result.times["get_t_response"] = test_time print("Function get_t_response time: %f" % test_time) # Step test_time = test_function(session, target.step) result.times["step"] = test_time print("Function step time: %f" % test_time) # Breakpoint def set_remove_breakpoint(): target.set_breakpoint(0) target.remove_breakpoint(0) test_time = test_function(session, set_remove_breakpoint) result.times["bp_add_remove"] = test_time print("Add and remove breakpoint: %f" % test_time) # get_register_context test_time = test_function(session, gdbFacade.get_register_context) result.times["get_reg_context"] = test_time print("Function get_register_context: %f" % test_time) # set_register_context context = gdbFacade.get_register_context() def set_register_context(): gdbFacade.set_register_context(context) test_time = test_function(session, set_register_context) result.times["set_reg_context"] = test_time print("Function set_register_context: %f" % test_time) # Run / Halt def run_halt(): target.resume() target.halt() test_time = test_function(session, run_halt) result.times["run_halt"] = test_time print("Resume and halt: %f" % test_time) # GDB stepping def simulate_step(): target.step() gdbFacade.get_t_response() target.set_breakpoint(0) target.resume() target.halt() gdbFacade.get_t_response() target.remove_breakpoint(0) test_time = test_function(session, simulate_step) result.times["gdb_step"] = test_time print("Simulated GDB step: %f" % test_time) # Test passes if there are no exceptions test_pass_count += 1 test_count += 1 print("TEST PASSED") print("\n\n------ Testing Reset Types ------") def reset_methods(fnc): print("Hardware reset") fnc(reset_type=Target.ResetType.HW) print("Hardware reset (default=HW)") target.selected_core.default_reset_type = Target.ResetType.HW fnc(reset_type=None) print("Software reset (default=SYSRESETREQ)") target.selected_core.default_reset_type = Target.ResetType.SW_SYSRESETREQ fnc(reset_type=None) print("Software reset (default=VECTRESET)") target.selected_core.default_reset_type = Target.ResetType.SW_VECTRESET fnc(reset_type=None) print("Software reset (default=emulated)") target.selected_core.default_reset_type = Target.ResetType.SW_EMULATED fnc(reset_type=None) print("(Default) Software reset (SYSRESETREQ)") target.selected_core.default_software_reset_type = Target.ResetType.SW_SYSRESETREQ fnc(reset_type=Target.ResetType.SW) print("(Default) Software reset (VECTRESET)") target.selected_core.default_software_reset_type = Target.ResetType.SW_VECTRESET fnc(reset_type=Target.ResetType.SW) print("(Default) Software reset (emulated)") target.selected_core.default_software_reset_type = Target.ResetType.SW_EMULATED fnc(reset_type=Target.ResetType.SW) print("Software reset (option=default)") target.selected_core.default_reset_type = Target.ResetType.SW target.selected_core.default_software_reset_type = Target.ResetType.SW_SYSRESETREQ session.options['reset_type'] = 'default' fnc(reset_type=None) print("Software reset (option=hw)") session.options['reset_type'] = 'hw' fnc(reset_type=None) print("Software reset (option=sw)") session.options['reset_type'] = 'sw' fnc(reset_type=None) print("Software reset (option=sw_sysresetreq)") session.options['reset_type'] = 'sw_sysresetreq' fnc(reset_type=None) print("Software reset (option=sw_vectreset)") session.options['reset_type'] = 'sw_vectreset' fnc(reset_type=None) print("Software reset (option=sw_emulated)") session.options['reset_type'] = 'sw_emulated' fnc(reset_type=None) reset_methods(target.reset) # Test passes if there are no exceptions test_pass_count += 1 test_count += 1 print("TEST PASSED") print("\n\n------ Testing Reset Halt ------") reset_methods(target.reset_and_halt) # Test passes if there are no exceptions test_pass_count += 1 test_count += 1 print("TEST PASSED") print("\n\n------ Testing Register Read/Write ------") print("Reading r0") val = target.read_core_register('r0') origR0 = val rawVal = target.read_core_register_raw('r0') test_count += 1 if val == rawVal: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED") print("Writing r0") target.write_core_register('r0', 0x12345678) val = target.read_core_register('r0') rawVal = target.read_core_register_raw('r0') test_count += 1 if val == 0x12345678 and rawVal == 0x12345678: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED") print("Raw writing r0") target.write_core_register_raw('r0', 0x87654321) val = target.read_core_register('r0') rawVal = target.read_core_register_raw('r0') test_count += 1 if val == 0x87654321 and rawVal == 0x87654321: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED") print("Read/write r0, r1, r2, r3") origRegs = target.read_core_registers_raw(['r0', 'r1', 'r2', 'r3']) target.write_core_registers_raw(['r0', 'r1', 'r2', 'r3'], [1, 2, 3, 4]) vals = target.read_core_registers_raw(['r0', 'r1', 'r2', 'r3']) passed = vals[0] == 1 and vals[1] == 2 and vals[2] == 3 and vals[3] == 4 test_count += 1 if passed: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED") # Restore regs origRegs[0] = origR0 target.write_core_registers_raw(['r0', 'r1', 'r2', 'r3'], origRegs) if target.selected_core.has_fpu: print("Reading s0") val = target.read_core_register('s0') rawVal = target.read_core_register_raw('s0') origRawS0 = rawVal passed = isinstance(val, float) and isinstance(rawVal, int) \ and float32_to_u32(val) == rawVal test_count += 1 if passed: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED") print("Writing s0") target.write_core_register('s0', math.pi) val = target.read_core_register('s0') rawVal = target.read_core_register_raw('s0') passed = float_compare(val, math.pi) and float_compare(u32_to_float32(rawVal), math.pi) test_count += 1 if passed: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED (%f==%f, 0x%08x->%f)" % (val, math.pi, rawVal, u32_to_float32(rawVal))) print("Raw writing s0") x = float32_to_u32(32.768) target.write_core_register_raw('s0', x) val = target.read_core_register('s0') passed = float_compare(val, 32.768) test_count += 1 if passed: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED (%f==%f)" % (val, 32.768)) print("Read/write s0, s1") _1p1 = float32_to_u32(1.1) _2p2 = float32_to_u32(2.2) origRegs = target.read_core_registers_raw(['s0', 's1']) target.write_core_registers_raw(['s0', 's1'], [_1p1, _2p2]) vals = target.read_core_registers_raw(['s0', 's1']) s0 = target.read_core_register('s0') s1 = target.read_core_register('s1') passed = vals[0] == _1p1 and float_compare(s0, 1.1) \ and vals[1] == _2p2 and float_compare(s1, 2.2) test_count += 1 if passed: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED (0x%08x==0x%08x, %f==%f, 0x%08x==0x%08x, %f==%f)" \ % (vals[0], _1p1, s0, 1.1, vals[1], _2p2, s1, 2.2)) # Restore s0 origRegs[0] = origRawS0 target.write_core_registers_raw(['s0', 's1'], origRegs) print("\n\n------ Testing Invalid Memory Access Recovery ------") memory_access_pass = True try: print("reading 0x1000 bytes at invalid address 0x%08x" % addr_invalid) target.read_memory_block8(addr_invalid, 0x1000) target.flush() # If no exception is thrown the tests fails except on nrf51 where invalid addresses read as 0 if expect_invalid_access_to_fail: print(" failed to get expected fault") memory_access_pass = False else: print(" no fault as expected") except exceptions.TransferFaultError as exc: print(" got expected error: " + str(exc)) try: print("reading 0x1000 bytes at invalid address 0x%08x" % (addr_invalid + 1)) target.read_memory_block8(addr_invalid + 1, 0x1000) target.flush() # If no exception is thrown the tests fails except on nrf51 where invalid addresses read as 0 if expect_invalid_access_to_fail: print(" failed to get expected fault") memory_access_pass = False else: print(" no fault as expected") except exceptions.TransferFaultError as exc: print(" got expected error: " + str(exc)) data = [0x00] * 0x1000 try: print("writing 0x%08x bytes at invalid address 0x%08x" % (len(data), addr_invalid)) target.write_memory_block8(addr_invalid, data) target.flush() # If no exception is thrown the tests fails except on nrf51 where invalid addresses read as 0 if expect_invalid_access_to_fail: print(" failed to get expected fault!") memory_access_pass = False else: print(" no fault as expected") except exceptions.TransferFaultError as exc: print(" got expected error: " + str(exc)) data = [0x00] * 0x1000 try: print("writing 0x%08x bytes at invalid address 0x%08x" % (len(data), addr_invalid + 1)) target.write_memory_block8(addr_invalid + 1, data) target.flush() # If no exception is thrown the tests fails except on nrf51 where invalid addresses read as 0 if expect_invalid_access_to_fail: print(" failed to get expected fault!") memory_access_pass = False else: print(" no fault as expected") except exceptions.TransferFaultError as exc: print(" got expected error: " + str(exc)) data = [randrange(0, 255) for x in range(size)] print("r/w 0x%08x bytes at 0x%08x" % (size, addr)) target.write_memory_block8(addr, data) block = target.read_memory_block8(addr, size) if same(data, block): print(" Aligned access pass") else: print(" Memory read does not match memory written") memory_access_pass = False data = [randrange(0, 255) for x in range(size)] print("r/w 0x%08x bytes at 0x%08x" % (size, addr + 1)) target.write_memory_block8(addr + 1, data) block = target.read_memory_block8(addr + 1, size) if same(data, block): print(" Unaligned access pass") else: print(" Unaligned memory read does not match memory written") memory_access_pass = False test_count += 1 if memory_access_pass: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED") print("\n\n------ Testing Software Breakpoints ------") test_passed = True orig8x2 = target.read_memory_block8(addr, 2) orig8 = target.read8(addr) orig16 = target.read16(addr & ~1) orig32 = target.read32(addr & ~3) origAligned32 = target.read_memory_block32(addr & ~3, 1) def test_filters(): test_passed = True filtered = target.read_memory_block8(addr, 2) if same(orig8x2, filtered): print("2 byte unaligned passed") else: print("2 byte unaligned failed (read %x-%x, expected %x-%x)" % (filtered[0], filtered[1], orig8x2[0], orig8x2[1])) test_passed = False for now in (True, False): filtered = target.read8(addr, now) if not now: filtered = filtered() if filtered == orig8: print("8-bit passed [now=%s]" % now) else: print("8-bit failed [now=%s] (read %x, expected %x)" % (now, filtered, orig8)) test_passed = False filtered = target.read16(addr & ~1, now) if not now: filtered = filtered() if filtered == orig16: print("16-bit passed [now=%s]" % now) else: print("16-bit failed [now=%s] (read %x, expected %x)" % (now, filtered, orig16)) test_passed = False filtered = target.read32(addr & ~3, now) if not now: filtered = filtered() if filtered == orig32: print("32-bit passed [now=%s]" % now) else: print("32-bit failed [now=%s] (read %x, expected %x)" % (now, filtered, orig32)) test_passed = False filtered = target.read_memory_block32(addr & ~3, 1) if same(filtered, origAligned32): print("32-bit aligned passed") else: print("32-bit aligned failed (read %x, expected %x)" % (filtered[0], origAligned32[0])) test_passed = False return test_passed print("Installed software breakpoint at 0x%08x" % addr) target.set_breakpoint(addr, Target.BREAKPOINT_SW) test_passed = test_filters() and test_passed print("Removed software breakpoint") target.remove_breakpoint(addr) test_passed = test_filters() and test_passed test_count += 1 if test_passed: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED") target.reset() result.passed = test_count == test_pass_count return result
def test_gdb(board_id=None, n=0): temp_test_elf_name = None result = GdbTestResult() with ConnectHelper.session_with_chosen_probe(unique_id=board_id, **get_session_options()) as session: board = session.board memory_map = board.target.get_memory_map() ram_region = memory_map.get_first_region_of_type(MemoryType.RAM) rom_region = memory_map.get_boot_memory() target_type = board.target_type binary_file = os.path.join(parentdir, 'binaries', board.test_binary) if board_id is None: board_id = board.unique_id target_test_params = get_target_test_params(session) test_port = 3333 + n telnet_port = 4444 + n # Hardware breakpoints are not supported above 0x20000000 on # CortexM devices ignore_hw_bkpt_result = 1 if ram_region.start >= 0x20000000 else 0 # Program with initial test image FileProgrammer(session).program(binary_file, base_address=rom_region.start) # Generate an elf from the binary test file. temp_test_elf_name = binary_to_elf_file(binary_file, rom_region.start) # Write out the test configuration test_params = { "test_port" : test_port, "rom_start" : rom_region.start, "rom_length" : rom_region.length, "ram_start" : ram_region.start, "ram_length" : ram_region.length, "invalid_start" : 0x3E000000, "invalid_length" : 0x1000, "expect_error_on_invalid_access" : target_test_params['error_on_invalid_access'], "ignore_hw_bkpt_result" : ignore_hw_bkpt_result, "test_elf" : temp_test_elf_name, } test_param_filename = "test_params%d.txt" % n with open(test_param_filename, "w") as f: f.write(json.dumps(test_params)) # Run the test gdb = [PYTHON_GDB, "-ex", "set $testn=%d" % n, "--command=gdb_script.py"] output_filename = "output_%s_%d.txt" % (board.target_type, n) with open(output_filename, "w") as f: program = Popen(gdb, stdin=PIPE, stdout=f, stderr=STDOUT) args = ['gdbserver', '--port=%i' % test_port, "--telnet-port=%i" % telnet_port, "--frequency=%i" % target_test_params['test_clock'], "--uid=%s" % board_id, ] server = PyOCDTool() server.run(args) program.wait() # Read back the result test_result_filename = "test_results%d.txt" % n with open(test_result_filename, "r") as f: test_result = json.loads(f.read()) # Print results if set(TEST_RESULT_KEYS).issubset(test_result): print("----------------Test Results----------------") print("HW breakpoint count: %s" % test_result["breakpoint_count"]) print("Watchpoint count: %s" % test_result["watchpoint_count"]) print("Average instruction step time: %s" % test_result["step_time_si"]) print("Average single step time: %s" % test_result["step_time_s"]) print("Average over step time: %s" % test_result["step_time_n"]) print("Failure count: %i" % test_result["fail_count"]) result.passed = test_result["fail_count"] == 0 else: result.passed = False # Cleanup if temp_test_elf_name and os.path.exists(temp_test_elf_name): os.remove(temp_test_elf_name) os.remove(test_result_filename) os.remove(test_param_filename) return result
def validate_boards(data): did_pass = True print('boards', end=' ') p = 'boards' in data and type(data['boards']) is list if p: b = data['boards'] if p: print("PASSED") else: did_pass = False print("FAILED") # Only if we're running this test standalone do we want to compare against the list # of boards returned by ConnectHelper.get_sessions_for_all_connected_probes(). When running in the full # automated test suite, there could be other test jobs running concurrently that have # exclusive access to the boards they are testing. Thus, those boards will not show up # in the return list and this test will fail. if testing_standalone: try: all_sessions = ConnectHelper.get_sessions_for_all_connected_probes(blocking=False) all_mbeds = [x.board for x in all_sessions] p = len(all_mbeds) == len(b) matching_boards = 0 if p: for mbed in all_mbeds: for brd in b: if mbed.unique_id == brd['unique_id']: matching_boards += 1 p = 'info' in brd and 'target' in brd and 'board_name' in brd if not p: break if not p: break p = matching_boards == len(all_mbeds) if p: print("PASSED") else: did_pass = False print("FAILED") except Exception as e: print("FAILED") traceback.print_exc(file=sys.stdout) did_pass = False else: # Check for required keys in all board info dicts. p = True for brd in b: p = ('unique_id' in brd and 'info' in brd and 'target' in brd and 'board_name' in brd) if not p: break if p: print("PASSED") else: did_pass = False print("FAILED") return did_pass
def main(): parser = argparse.ArgumentParser(description='pyOCD automated testing') parser.add_argument('-d', '--debug', action="store_true", help='Enable debug logging') parser.add_argument('-q', '--quiet', action="store_true", help='Hide test progress for 1 job') parser.add_argument('-j', '--jobs', action="store", default=1, type=int, metavar="JOBS", help='Set number of concurrent board tests (default is 1)') parser.add_argument('-b', '--board', action="append", metavar="ID", help="Limit testing to boards with specified unique IDs. Multiple boards can be listed.") args = parser.parse_args() # Allow CI to override the number of concurrent jobs. if 'CI_JOBS' in os.environ: args.jobs = int(os.environ['CI_JOBS']) # Disable multiple jobs on macOS prior to Python 3.4. By default, multiprocessing uses # fork() on Unix, which doesn't work on the Mac because CoreFoundation requires exec() # to be used in order to init correctly (CoreFoundation is used in hidapi). Only on Python # version 3.4+ is the multiprocessing.set_start_method() API available that lets us # switch to the 'spawn' method, i.e. exec(). if args.jobs > 1 and sys.platform.startswith('darwin') and sys.version_info[0:2] < (3, 4): print("WARNING: Cannot support multiple jobs on macOS prior to Python 3.4. Forcing 1 job.") args.jobs = 1 # Setup logging based on concurrency and quiet option. level = logging.DEBUG if args.debug else logging.INFO if args.jobs == 1 and not args.quiet: log_file = LOG_FILE_TEMPLATE.format(get_env_file_name()) # Create common log file. if os.path.exists(log_file): os.remove(log_file) logToConsole = True commonLogFile = open(log_file, "a") else: logToConsole = False commonLogFile = None board_list = [] result_list = [] # Put together list of boards to test board_list = ConnectHelper.get_all_connected_probes(blocking=False) board_id_list = sorted(b.unique_id for b in board_list) # Filter boards. if args.board: board_id_list = [b for b in board_id_list if any(c for c in args.board if c.lower() in b.lower())] # If only 1 job was requested, don't bother spawning processes. start = time() if args.jobs == 1: for n, board_id in enumerate(board_id_list): result_list += test_board(board_id, n, level, logToConsole, commonLogFile) else: # Create a pool of processes to run tests. try: pool = mp.Pool(args.jobs) # Issue board test job to process pool. async_results = [pool.apply_async(test_board, (board_id, n, level, logToConsole, commonLogFile)) for n, board_id in enumerate(board_id_list)] # Gather results. for r in async_results: result_list += r.get(timeout=JOB_TIMEOUT) finally: pool.close() pool.join() stop = time() test_time = (stop - start) print_summary(test_list, result_list, test_time) summary_file = SUMMARY_FILE_TEMPLATE.format(get_env_file_name()) with open(summary_file, "w") as output_file: print_summary(test_list, result_list, test_time, output_file) generate_xml_results(result_list) exit_val = 0 if Test.all_tests_pass(result_list) else -1 exit(exit_val)
def read_target_memory(self, addr, size, resume=True): assert self.get_mode() == self.MODE_IF with ConnectHelper.session_with_chosen_probe(unique_id=self.get_unique_id(), resume_on_disconnect=resume) as session: data = session.target.read_memory_block8(addr, size) return bytearray(data)
print("\n{:<4}{:<12}{:<19}{:<12}{:<21}{:<11}{:<10}".format( "#", "Prev Exit", "Halt on Connect", "Expected", "Disconnect Resume", "Exit", "Passed")) for i, case in enumerate(test_cases): print("{:<4}{:<12}{:<19}{:<12}{:<21}{:<11}{:<10}".format( i, STATE_NAMES[case.prev_exit_state], repr(case.halt_on_connect), STATE_NAMES[case.expected_state], repr(case.disconnect_resume), STATE_NAMES[case.exit_state], "PASS" if case.passed else "FAIL")) print("\nPass count %i of %i tests" % (test_pass_count, test_count)) if test_pass_count == test_count: print("CONNECT TEST SCRIPT PASSED") else: print("CONNECT TEST SCRIPT FAILED") result.passed = (test_count == test_pass_count) return result if __name__ == "__main__": parser = argparse.ArgumentParser(description='pyOCD connect test') parser.add_argument('-d', '--debug', action="store_true", help='Enable debug logging') args = parser.parse_args() level = logging.DEBUG if args.debug else logging.INFO logging.basicConfig(level=level) session = ConnectHelper.session_with_chosen_probe(open_session=False, **get_session_options()) test = ConnectTest() result = [test.run(session.board)] test.print_perf_info(result)
def speed_test(board_id): with ConnectHelper.session_with_chosen_probe(unique_id=board_id, **get_session_options()) as session: board = session.board target_type = board.target_type memory_map = board.target.get_memory_map() ram_region = memory_map.get_first_region_of_type(MemoryType.RAM) rom_region = memory_map.get_boot_memory() # Limit region sizes used for performance testing to 1 MB. We don't really need to # be reading all 32 MB of a QSPI! ram_start = ram_region.start ram_size = min(ram_region.length, _1MB) rom_start = rom_region.start rom_size = min(rom_region.length, _1MB) target = board.target test_pass_count = 0 test_count = 0 result = SpeedTestResult() test_params = get_target_test_params(session) session.probe.set_clock(test_params['test_clock']) test_config = "uncached 8-bit" def test_ram(record_speed=False, width=8): print("\n\n------ TEST RAM READ / WRITE SPEED [%s] ------" % test_config) test_addr = ram_start test_size = ram_size data = [randrange(1, 50) for x in range(test_size)] start = time() if width == 8: target.write_memory_block8(test_addr, data) elif width == 32: target.write_memory_block32(test_addr, conversion.byte_list_to_u32le_list(data)) target.flush() stop = time() diff = stop - start if diff == 0: print("Unexpected ram write elapsed time of 0!") write_speed = 0 else: write_speed = test_size / diff if record_speed: result.write_speed = write_speed print("Writing %i byte took %.3f seconds: %.3f B/s" % (test_size, diff, write_speed)) start = time() if width == 8: block = target.read_memory_block8(test_addr, test_size) elif width == 32: block = conversion.u32le_list_to_byte_list(target.read_memory_block32(test_addr, test_size // 4)) target.flush() stop = time() diff = stop - start if diff == 0: print("Unexpected ram read elapsed time of 0!") read_speed = 0 else: read_speed = test_size / diff if record_speed: result.read_speed = read_speed print("Reading %i byte took %.3f seconds: %.3f B/s" % (test_size, diff, read_speed)) error = False if len(block) != len(data): error = True print("ERROR: read length (%d) != write length (%d)!" % (len(block), len(data))) if not error: for i in range(len(block)): if (block[i] != data[i]): error = True print("ERROR: 0x%X, 0x%X, 0x%X!!!" % ((addr + i), block[i], data[i])) if error: print("TEST FAILED") else: print("TEST PASSED") return not error def test_rom(record_speed=False, width=8): print("\n\n------ TEST ROM READ SPEED [%s] ------" % test_config) test_addr = rom_start test_size = rom_size start = time() if width == 8: block = target.read_memory_block8(test_addr, test_size) elif width == 32: block = conversion.u32le_list_to_byte_list(target.read_memory_block32(test_addr, test_size // 4)) target.flush() stop = time() diff = stop - start if diff == 0: print("Unexpected rom read elapsed time of 0!") read_speed = 0 else: read_speed = test_size / diff if record_speed: result.rom_read_speed = read_speed print("Reading %i byte took %.3f seconds: %.3f B/s" % (test_size, diff, read_speed)) print("TEST PASSED") return True # 8-bit without memcache passed = test_ram(True, 8) test_count += 1 test_pass_count += int(passed) passed = test_rom(True, 8) test_count += 1 test_pass_count += int(passed) # 32-bit without memcache test_config = "uncached 32-bit" passed = test_ram(False, 32) test_count += 1 test_pass_count += int(passed) passed = test_rom(False, 32) test_count += 1 test_pass_count += int(passed) # With memcache target = target.get_target_context() test_config = "cached 8-bit, pass 1" passed = test_ram() test_count += 1 test_pass_count += int(passed) passed = test_rom() test_count += 1 test_pass_count += int(passed) # Again with memcache test_config = "cached 8-bit, pass 2" passed = test_ram() test_count += 1 test_pass_count += int(passed) passed = test_rom() test_count += 1 test_pass_count += int(passed) board.target.reset() result.passed = test_count == test_pass_count return result
def speed_test(board_id): with ConnectHelper.session_with_chosen_probe(board_id=board_id, **get_session_options()) as session: board = session.board target_type = board.target_type test_clock = 10000000 if target_type == "nrf51": # Override clock since 10MHz is too fast test_clock = 1000000 if target_type == "ncs36510": # Override clock since 10MHz is too fast test_clock = 1000000 memory_map = board.target.get_memory_map() ram_region = memory_map.get_first_region_of_type(MemoryType.RAM) rom_region = memory_map.get_boot_memory() ram_start = ram_region.start ram_size = ram_region.length rom_start = rom_region.start rom_size = rom_region.length target = board.target test_pass_count = 0 test_count = 0 result = SpeedTestResult() session.probe.set_clock(test_clock) print("\n\n------ TEST RAM READ / WRITE SPEED ------") test_addr = ram_start test_size = ram_size data = [randrange(1, 50) for x in range(test_size)] start = time() target.write_memory_block8(test_addr, data) target.flush() stop = time() diff = stop - start result.write_speed = test_size / diff print("Writing %i byte took %.3f seconds: %.3f B/s" % (test_size, diff, result.write_speed)) start = time() block = target.read_memory_block8(test_addr, test_size) target.flush() stop = time() diff = stop - start result.read_speed = test_size / diff print("Reading %i byte took %.3f seconds: %.3f B/s" % (test_size, diff, result.read_speed)) error = False for i in range(len(block)): if (block[i] != data[i]): error = True print("ERROR: 0x%X, 0x%X, 0x%X!!!" % ((addr + i), block[i], data[i])) if error: print("TEST FAILED") else: print("TEST PASSED") test_pass_count += 1 test_count += 1 print("\n\n------ TEST ROM READ SPEED ------") test_addr = rom_start test_size = rom_size start = time() block = target.read_memory_block8(test_addr, test_size) target.flush() stop = time() diff = stop - start print("Reading %i byte took %.3f seconds: %.3f B/s" % (test_size, diff, test_size / diff)) print("TEST PASSED") test_pass_count += 1 test_count += 1 target.reset() result.passed = test_count == test_pass_count return result
def connect_test(board): board_id = board.unique_id binary_file = os.path.join(parentdir, 'binaries', board.test_binary) print("binary file: %s" % binary_file) test_pass_count = 0 test_count = 0 result = ConnectTestResult() # Install binary. live_session = ConnectHelper.session_with_chosen_probe(board_id=board_id, **get_session_options()) live_board = live_session.board memory_map = board.target.get_memory_map() rom_region = memory_map.get_boot_memory() rom_start = rom_region.start def test_connect(halt_on_connect, expected_state, resume): print("Connecting with halt_on_connect=%s" % halt_on_connect) live_session = ConnectHelper.session_with_chosen_probe( board_id=board_id, init_board=False, halt_on_connect=halt_on_connect, resume_on_disconnect=resume, **get_session_options()) live_session.open() live_board = live_session.board print("Verifying target is", STATE_NAMES.get(expected_state, "unknown")) actualState = live_board.target.get_state() # Accept sleeping for running, as a hack to work around nRF52840-DK test binary. # TODO remove sleeping hack. if (actualState == expected_state) \ or (expected_state == RUNNING and actualState == Target.TARGET_SLEEPING): passed = 1 print("TEST PASSED") else: passed = 0 print("TEST FAILED (state={}, expected={})".format( STATE_NAMES.get(actualState, "unknown"), STATE_NAMES.get(expected_state, "unknown"))) print("Disconnecting with resume=%s" % resume) live_session.close() live_session = None return passed # TEST CASE COMBINATIONS test_cases = [ # <prev_exit> <halt_on_connect> <expected_state> <disconnect_resume> <exit_state> ConnectTestCase( RUNNING, False, RUNNING, False, RUNNING ), ConnectTestCase( RUNNING, True, HALTED, False, HALTED ), ConnectTestCase( HALTED, True, HALTED, True, RUNNING ), ConnectTestCase( RUNNING, True, HALTED, True, RUNNING ), ConnectTestCase( RUNNING, False, RUNNING, True, RUNNING ), ConnectTestCase( RUNNING, True, HALTED, False, HALTED ), ConnectTestCase( HALTED, False, HALTED, False, HALTED ), ConnectTestCase( HALTED, True, HALTED, False, HALTED ), ConnectTestCase( HALTED, False, HALTED, True, RUNNING ), ConnectTestCase( RUNNING, False, RUNNING, False, RUNNING ), ] print("\n\n----- TESTING CONNECT/DISCONNECT -----") print("Flashing new binary") FileProgrammer(live_session).program(binary_file, base_address=rom_start) live_board.target.reset() test_count += 1 print("Verifying target is running") if live_board.target.is_running(): test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED") print("Disconnecting with resume=True") live_session.options['resume_on_disconnect'] = True live_session.close() live_session = None # Leave running. # Run all the cases. for case in test_cases: test_count += 1 did_pass = test_connect( halt_on_connect=case.halt_on_connect, expected_state=case.expected_state, resume=case.disconnect_resume ) test_pass_count += did_pass case.passed=did_pass print("\n\nTest Summary:") print("\n{:<4}{:<12}{:<19}{:<12}{:<21}{:<11}{:<10}".format( "#", "Prev Exit", "Halt on Connect", "Expected", "Disconnect Resume", "Exit", "Passed")) for i, case in enumerate(test_cases): print("{:<4}{:<12}{:<19}{:<12}{:<21}{:<11}{:<10}".format( i, STATE_NAMES[case.prev_exit_state], repr(case.halt_on_connect), STATE_NAMES[case.expected_state], repr(case.disconnect_resume), STATE_NAMES[case.exit_state], "PASS" if case.passed else "FAIL")) print("\nPass count %i of %i tests" % (test_pass_count, test_count)) if test_pass_count == test_count: print("CONNECT TEST SCRIPT PASSED") else: print("CONNECT TEST SCRIPT FAILED") result.passed = (test_count == test_pass_count) return result
def debug_context_test(board_id): with ConnectHelper.session_with_chosen_probe(unique_id=board_id, **get_session_options()) as session: board = session.board target = session.target test_params = get_target_test_params(session) session.probe.set_clock(test_params['test_clock']) memory_map = target.get_memory_map() boot_region = memory_map.get_boot_memory() ram_region = memory_map.get_first_region_of_type(MemoryType.RAM) binary_file = os.path.join(parentdir, 'binaries', board.test_binary) gdb_test_binary_file = os.path.join(parentdir, GDB_TEST_BIN) gdb_test_elf_file = os.path.join(parentdir, GDB_TEST_ELF) # Read the gdb test binary file. with open(gdb_test_binary_file, "rb") as f: gdb_test_binary_data = list(bytearray(f.read())) gdb_test_binary_data_length = len(gdb_test_binary_data) # Set the elf on the target, which will add a context to read from the elf. target.elf = gdb_test_elf_file test_pass_count = 0 test_count = 0 result = DebugContextTestResult() ctx = target.get_target_context() target.reset_and_halt() # Reproduce a gdbserver failure. print("\n------ Test 1: Mem cache ------") print("Writing gdb test binary") ctx.write_memory_block8(0x20000000, gdb_test_binary_data) print("Reading first chunk") data = ctx.read_memory_block8(0x20000000, 64) if data == gdb_test_binary_data[:64]: test_pass_count += 1 test_count += 1 print("Reading N chunks") for n in range(8): offset = 0x7e + (4 * n) data = ctx.read_memory_block8(0x20000000 + offset, 4) if data == gdb_test_binary_data[offset:offset + 4]: test_pass_count += 1 test_count += 1 print("\nTest Summary:") print("Pass count %i of %i tests" % (test_pass_count, test_count)) if test_pass_count == test_count: print("DEBUG CONTEXT TEST PASSED") else: print("DEBUG CONTEXT TEST FAILED") target.reset() result.passed = test_count == test_pass_count return result
def cortex_test(board_id): with ConnectHelper.session_with_chosen_probe( board_id=board_id, **get_session_options()) as session: board = session.board target_type = board.target_type binary_file = os.path.join(parentdir, 'binaries', board.test_binary) test_params = get_target_test_params(session) test_clock = test_params['test_clock'] addr_invalid = 0x3E000000 # Last 16MB of ARM SRAM region - typically empty expect_invalid_access_to_fail = test_params['error_on_invalid_access'] memory_map = board.target.get_memory_map() ram_region = memory_map.get_first_region_of_type(MemoryType.RAM) rom_region = memory_map.get_boot_memory() addr = ram_region.start size = 0x502 addr_bin = rom_region.start target = board.target probe = session.probe probe.set_clock(test_clock) test_pass_count = 0 test_count = 0 result = CortexTestResult() debugContext = target.get_target_context() gdbFacade = GDBDebugContextFacade(debugContext) print("\n\n----- FLASH NEW BINARY BEFORE TEST -----") FileProgrammer(session).program(binary_file, base_address=addr_bin) # Let the target run for a bit so it # can initialize the watchdog if it needs to target.resume() sleep(0.2) target.halt() print("PROGRAMMING COMPLETE") print("\n\n----- TESTING CORTEX-M PERFORMANCE -----") test_time = test_function(session, gdbFacade.get_t_response) result.times["get_t_response"] = test_time print("Function get_t_response time: %f" % test_time) # Step test_time = test_function(session, target.step) result.times["step"] = test_time print("Function step time: %f" % test_time) # Breakpoint def set_remove_breakpoint(): target.set_breakpoint(0) target.remove_breakpoint(0) test_time = test_function(session, set_remove_breakpoint) result.times["bp_add_remove"] = test_time print("Add and remove breakpoint: %f" % test_time) # get_register_context test_time = test_function(session, gdbFacade.get_register_context) result.times["get_reg_context"] = test_time print("Function get_register_context: %f" % test_time) # set_register_context context = gdbFacade.get_register_context() def set_register_context(): gdbFacade.set_register_context(context) test_time = test_function(session, set_register_context) result.times["set_reg_context"] = test_time print("Function set_register_context: %f" % test_time) # Run / Halt def run_halt(): target.resume() target.halt() test_time = test_function(session, run_halt) result.times["run_halt"] = test_time print("Resume and halt: %f" % test_time) # GDB stepping def simulate_step(): target.step() gdbFacade.get_t_response() target.set_breakpoint(0) target.resume() target.halt() gdbFacade.get_t_response() target.remove_breakpoint(0) test_time = test_function(session, simulate_step) result.times["gdb_step"] = test_time print("Simulated GDB step: %f" % test_time) # Test passes if there are no exceptions test_pass_count += 1 test_count += 1 print("TEST PASSED") print("\n\n------ Testing Reset Types ------") def reset_methods(fnc): print("Hardware reset") fnc(reset_type=Target.ResetType.HW) print("Hardware reset (default=HW)") target.selected_core.default_reset_type = Target.ResetType.HW fnc(reset_type=None) print("Software reset (default=SYSRESETREQ)") target.selected_core.default_reset_type = Target.ResetType.SW_SYSRESETREQ fnc(reset_type=None) print("Software reset (default=VECTRESET)") target.selected_core.default_reset_type = Target.ResetType.SW_VECTRESET fnc(reset_type=None) print("Software reset (default=emulated)") target.selected_core.default_reset_type = Target.ResetType.SW_EMULATED fnc(reset_type=None) print("(Default) Software reset (SYSRESETREQ)") target.selected_core.default_software_reset_type = Target.ResetType.SW_SYSRESETREQ fnc(reset_type=Target.ResetType.SW) print("(Default) Software reset (VECTRESET)") target.selected_core.default_software_reset_type = Target.ResetType.SW_VECTRESET fnc(reset_type=Target.ResetType.SW) print("(Default) Software reset (emulated)") target.selected_core.default_software_reset_type = Target.ResetType.SW_EMULATED fnc(reset_type=Target.ResetType.SW) print("Software reset (option=default)") target.selected_core.default_reset_type = Target.ResetType.SW target.selected_core.default_software_reset_type = Target.ResetType.SW_SYSRESETREQ session.options['reset_type'] = 'default' fnc(reset_type=None) print("Software reset (option=hw)") session.options['reset_type'] = 'hw' fnc(reset_type=None) print("Software reset (option=sw)") session.options['reset_type'] = 'sw' fnc(reset_type=None) print("Software reset (option=sw_sysresetreq)") session.options['reset_type'] = 'sw_sysresetreq' fnc(reset_type=None) print("Software reset (option=sw_vectreset)") session.options['reset_type'] = 'sw_vectreset' fnc(reset_type=None) print("Software reset (option=sw_emulated)") session.options['reset_type'] = 'sw_emulated' fnc(reset_type=None) reset_methods(target.reset) # Test passes if there are no exceptions test_pass_count += 1 test_count += 1 print("TEST PASSED") print("\n\n------ Testing Reset Halt ------") reset_methods(target.reset_and_halt) # Test passes if there are no exceptions test_pass_count += 1 test_count += 1 print("TEST PASSED") print("\n\n------ Testing Register Read/Write ------") print("Reading r0") val = target.read_core_register('r0') origR0 = val rawVal = target.read_core_register_raw('r0') test_count += 1 if val == rawVal: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED") print("Writing r0") target.write_core_register('r0', 0x12345678) val = target.read_core_register('r0') rawVal = target.read_core_register_raw('r0') test_count += 1 if val == 0x12345678 and rawVal == 0x12345678: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED") print("Raw writing r0") target.write_core_register_raw('r0', 0x87654321) val = target.read_core_register('r0') rawVal = target.read_core_register_raw('r0') test_count += 1 if val == 0x87654321 and rawVal == 0x87654321: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED") print("Read/write r0, r1, r2, r3") origRegs = target.read_core_registers_raw(['r0', 'r1', 'r2', 'r3']) target.write_core_registers_raw(['r0', 'r1', 'r2', 'r3'], [1, 2, 3, 4]) vals = target.read_core_registers_raw(['r0', 'r1', 'r2', 'r3']) passed = vals[0] == 1 and vals[1] == 2 and vals[2] == 3 and vals[3] == 4 test_count += 1 if passed: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED") # Restore regs origRegs[0] = origR0 target.write_core_registers_raw(['r0', 'r1', 'r2', 'r3'], origRegs) if target.selected_core.has_fpu: print("Reading s0") val = target.read_core_register('s0') rawVal = target.read_core_register_raw('s0') origRawS0 = rawVal passed = isinstance(val, float) and isinstance(rawVal, int) \ and float32_to_u32(val) == rawVal test_count += 1 if passed: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED") print("Writing s0") target.write_core_register('s0', math.pi) val = target.read_core_register('s0') rawVal = target.read_core_register_raw('s0') passed = float_compare(val, math.pi) and float_compare( u32_to_float32(rawVal), math.pi) test_count += 1 if passed: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED (%f==%f, 0x%08x->%f)" % (val, math.pi, rawVal, u32_to_float32(rawVal))) print("Raw writing s0") x = float32_to_u32(32.768) target.write_core_register_raw('s0', x) val = target.read_core_register('s0') passed = float_compare(val, 32.768) test_count += 1 if passed: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED (%f==%f)" % (val, 32.768)) print("Read/write s0, s1") _1p1 = float32_to_u32(1.1) _2p2 = float32_to_u32(2.2) origRegs = target.read_core_registers_raw(['s0', 's1']) target.write_core_registers_raw(['s0', 's1'], [_1p1, _2p2]) vals = target.read_core_registers_raw(['s0', 's1']) s0 = target.read_core_register('s0') s1 = target.read_core_register('s1') passed = vals[0] == _1p1 and float_compare(s0, 1.1) \ and vals[1] == _2p2 and float_compare(s1, 2.2) test_count += 1 if passed: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED (0x%08x==0x%08x, %f==%f, 0x%08x==0x%08x, %f==%f)" \ % (vals[0], _1p1, s0, 1.1, vals[1], _2p2, s1, 2.2)) # Restore s0 origRegs[0] = origRawS0 target.write_core_registers_raw(['s0', 's1'], origRegs) print("\n\n------ Testing Invalid Memory Access Recovery ------") memory_access_pass = True try: print("reading 0x1000 bytes at invalid address 0x%08x" % addr_invalid) target.read_memory_block8(addr_invalid, 0x1000) target.flush() # If no exception is thrown the tests fails except on nrf51 where invalid addresses read as 0 if expect_invalid_access_to_fail: print(" failed to get expected fault") memory_access_pass = False else: print(" no fault as expected") except exceptions.TransferFaultError as exc: print(" got expected error: " + str(exc)) try: print("reading 0x1000 bytes at invalid address 0x%08x" % (addr_invalid + 1)) target.read_memory_block8(addr_invalid + 1, 0x1000) target.flush() # If no exception is thrown the tests fails except on nrf51 where invalid addresses read as 0 if expect_invalid_access_to_fail: print(" failed to get expected fault") memory_access_pass = False else: print(" no fault as expected") except exceptions.TransferFaultError as exc: print(" got expected error: " + str(exc)) data = [0x00] * 0x1000 try: print("writing 0x%08x bytes at invalid address 0x%08x" % (len(data), addr_invalid)) target.write_memory_block8(addr_invalid, data) target.flush() # If no exception is thrown the tests fails except on nrf51 where invalid addresses read as 0 if expect_invalid_access_to_fail: print(" failed to get expected fault!") memory_access_pass = False else: print(" no fault as expected") except exceptions.TransferFaultError as exc: print(" got expected error: " + str(exc)) data = [0x00] * 0x1000 try: print("writing 0x%08x bytes at invalid address 0x%08x" % (len(data), addr_invalid + 1)) target.write_memory_block8(addr_invalid + 1, data) target.flush() # If no exception is thrown the tests fails except on nrf51 where invalid addresses read as 0 if expect_invalid_access_to_fail: print(" failed to get expected fault!") memory_access_pass = False else: print(" no fault as expected") except exceptions.TransferFaultError as exc: print(" got expected error: " + str(exc)) data = [randrange(0, 255) for x in range(size)] print("r/w 0x%08x bytes at 0x%08x" % (size, addr)) target.write_memory_block8(addr, data) block = target.read_memory_block8(addr, size) if same(data, block): print(" Aligned access pass") else: print(" Memory read does not match memory written") memory_access_pass = False data = [randrange(0, 255) for x in range(size)] print("r/w 0x%08x bytes at 0x%08x" % (size, addr + 1)) target.write_memory_block8(addr + 1, data) block = target.read_memory_block8(addr + 1, size) if same(data, block): print(" Unaligned access pass") else: print(" Unaligned memory read does not match memory written") memory_access_pass = False test_count += 1 if memory_access_pass: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED") print("\n\n------ Testing Software Breakpoints ------") test_passed = True orig8x2 = target.read_memory_block8(addr, 2) orig8 = target.read8(addr) orig16 = target.read16(addr & ~1) orig32 = target.read32(addr & ~3) origAligned32 = target.read_memory_block32(addr & ~3, 1) def test_filters(): test_passed = True filtered = target.read_memory_block8(addr, 2) if same(orig8x2, filtered): print("2 byte unaligned passed") else: print("2 byte unaligned failed (read %x-%x, expected %x-%x)" % (filtered[0], filtered[1], orig8x2[0], orig8x2[1])) test_passed = False for now in (True, False): filtered = target.read8(addr, now) if not now: filtered = filtered() if filtered == orig8: print("8-bit passed [now=%s]" % now) else: print("8-bit failed [now=%s] (read %x, expected %x)" % (now, filtered, orig8)) test_passed = False filtered = target.read16(addr & ~1, now) if not now: filtered = filtered() if filtered == orig16: print("16-bit passed [now=%s]" % now) else: print("16-bit failed [now=%s] (read %x, expected %x)" % (now, filtered, orig16)) test_passed = False filtered = target.read32(addr & ~3, now) if not now: filtered = filtered() if filtered == orig32: print("32-bit passed [now=%s]" % now) else: print("32-bit failed [now=%s] (read %x, expected %x)" % (now, filtered, orig32)) test_passed = False filtered = target.read_memory_block32(addr & ~3, 1) if same(filtered, origAligned32): print("32-bit aligned passed") else: print("32-bit aligned failed (read %x, expected %x)" % (filtered[0], origAligned32[0])) test_passed = False return test_passed print("Installed software breakpoint at 0x%08x" % addr) target.set_breakpoint(addr, Target.BREAKPOINT_SW) test_passed = test_filters() and test_passed print("Removed software breakpoint") target.remove_breakpoint(addr) test_passed = test_filters() and test_passed test_count += 1 if test_passed: test_pass_count += 1 print("TEST PASSED") else: print("TEST FAILED") target.reset() result.passed = test_count == test_pass_count return result
from random import randrange import math import logging parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, parentdir) from pyocd.core.helpers import ConnectHelper from pyocd.flash.loader import FileProgrammer from test_util import get_session_options logging.basicConfig(level=logging.INFO) print("\n\n------ Test attaching to locked board ------") for i in range(0, 10): with ConnectHelper.session_with_chosen_probe(**get_session_options()) as session: board = session.board # Erase and then reset - This locks Kinetis devices board.flash.init(board.flash.Operation.ERASE) board.flash.erase_all() board.flash.cleanup() board.target.reset() print("\n\n------ Testing Attaching to board ------") for i in range(0, 100): with ConnectHelper.session_with_chosen_probe(**get_session_options()) as session: board = session.board board.target.halt() sleep(0.01) board.target.resume() sleep(0.01)
def commands_test(board_id): with ConnectHelper.session_with_chosen_probe( unique_id=board_id, **get_session_options()) as session: board = session.board target = session.target target_type = board.target_type test_params = get_target_test_params(session) session.probe.set_clock(test_params['test_clock']) memory_map = board.target.get_memory_map() boot_region = memory_map.get_boot_memory() ram_region = memory_map.get_default_region_of_type(MemoryType.RAM) ram_base = ram_region.start boot_start_addr = boot_region.start boot_end_addr = boot_region.end boot_blocksize = boot_region.blocksize binary_file = get_test_binary_path(board.test_binary) # Generate an Intel hex file from the binary test file. temp_test_hex_name = binary_to_hex_file(binary_file, boot_region.start) temp_bin_file = tempfile.mktemp('.bin') with open(binary_file, "rb") as f: test_data = list(bytearray(f.read())) test_data_length = len(test_data) test_file_sectors = round_up_div(test_data_length, boot_blocksize) boot_first_free_block_addr = boot_start_addr + test_file_sectors * boot_blocksize reset_handler_addr = conversion.byte_list_to_u32le_list( test_data[4:8])[0] test_pass_count = 0 test_count = 0 failed_commands = [] result = CommandsTestResult() context = CommandExecutionContext() context.attach_session(session) COMMANDS_TO_TEST = [ "status", "reset", "reset halt", "reg", "reg general", "reg all", "reg r0", "wreg r0 0x12345678", "d pc", "d --center pc 32", "read64 0x%08x" % ((boot_start_addr + boot_blocksize) & ~7), "read32 0x%08x" % ((boot_start_addr + boot_blocksize) & ~3), "read16 0x%08x" % ((boot_start_addr + boot_blocksize) & ~1), "read8 0x%08x" % (boot_start_addr + boot_blocksize), "rd 0x%08x 16" % ram_base, "rw 0x%08x 16" % ram_base, "rh 0x%08x 16" % ram_base, "rb 0x%08x 16" % ram_base, "write64 0x%08x 0x1122334455667788 0xaabbccddeeff0011" % ram_base, "write32 0x%08x 0x11223344 0x55667788" % ram_base, "write16 0x%08x 0xabcd" % (ram_base + 8), "write8 0x%08x 0 1 2 3 4 5 6" % (ram_base + 10), "savemem 0x%08x 128 '%s'" % (boot_start_addr, fix_windows_path(temp_bin_file)), "loadmem 0x%08x '%s'" % (ram_base, fix_windows_path(temp_bin_file)), "loadmem 0x%08x '%s'" % (boot_start_addr, fix_windows_path(binary_file)), "load '%s'" % fix_windows_path(temp_test_hex_name), "load '%s' 0x%08x" % (fix_windows_path(binary_file), boot_start_addr), "compare 0x%08x '%s'" % (ram_base, fix_windows_path(temp_bin_file)), "compare 0x%08x 32 '%s'" % (ram_base, fix_windows_path(temp_bin_file)), "fill 0x%08x 128 0xa5" % ram_base, "fill 16 0x%08x 64 0x55aa" % (ram_base + 64), "find 0x%08x 128 0xaa 0x55" % ram_base, # find that will pass "find 0x%08x 128 0xff" % ram_base, # find that will fail "erase 0x%08x" % (boot_first_free_block_addr), "erase 0x%08x 1" % (boot_first_free_block_addr + boot_blocksize), "go", "halt", "step", "s 4", "continue", "h", "break 0x%08x" % reset_handler_addr, "lsbreak", "rmbreak 0x%08x" % reset_handler_addr, "watch 0x%08x" % ram_base, "lswatch", "rmwatch 0x%08x" % ram_base, "watch 0x%08x rw 2" % ram_base, "rmwatch 0x%08x" % ram_base, "core", "core 0", "readdp 0", # read DPIDR "writedp 0 0x1e", # write ABORT to clear error flags "readap 0xfc", # read IDR "readap 0 0xfc", # read IDR of AP#0 "writeap 0x4 0", # set TAR to 0 "writeap 0 0x4 0", # set TAR to 0 on AP#0 "gdbserver start", "gdbserver status", "gdbserver stop", "probeserver start", "probeserver status", "probeserver stop", "show probe-uid", "show target", "show cores", "show map", "show peripherals", "show fault", "show nreset", "set nreset 1", "show option reset_type", "set option reset_type=sw", "show mem-ap", "set mem-ap 0", "show hnonsec", "set hnonsec 0", "show hprot", "set hprot 0x3", # set default hprot: data, priv "show graph", "show locked", "show register-groups", "show vector-catch", "set vector-catch all", "show step-into-interrupts", "set step-into-interrupts 1", "set log info", "set frequency %d" % test_params['test_clock'], # Semicolon-separated commands. 'rw 0x%08x ; rw 0x%08x' % (ram_base, ram_base + 4), 'rb 0x%08x;rb 0x%08x' % (ram_base, ram_base + 1), 'rb 0x%08x; rb 0x%08x' % (ram_base, ram_base + 1), # Python and system commands. '$2+ 2', '$ target', '!echo hello', '!echo hi ; echo there', # semicolon in a sytem command (because semicolon separation is not supported for Python/system command lines) ' $ " ".join(["hello", "there"])', ' ! echo "yo dude" ', # Commands not tested: # "list", # "erase", # chip erase # "unlock", # "exit", # "initdp", # "makeap", # "reinit", # "where", # "symbol", ] # For now we just verify that the commands run without raising an exception. print("\n------ Testing commands ------") def test_command(cmd): try: print("\nTEST: %s" % cmd) context.process_command_line(cmd) except: print("TEST FAILED") failed_commands.append(cmd) traceback.print_exc(file=sys.stdout) return False else: print("TEST PASSED") return True for cmd in COMMANDS_TO_TEST: if test_command(cmd): test_pass_count += 1 test_count += 1 print("\n\nTest Summary:") print("Pass count %i of %i tests" % (test_pass_count, test_count)) if failed_commands: for c in failed_commands: print(" - '" + c + "'") if test_pass_count == test_count: print("COMMANDS TEST SCRIPT PASSED") else: print("COMMANDS TEST SCRIPT FAILED") target.reset() result.passed = test_count == test_pass_count return result
def flash_test(board_id): with ConnectHelper.session_with_chosen_probe(unique_id=board_id, **get_session_options()) as session: board = session.board target_type = board.target_type memory_map = board.target.get_memory_map() ram_region = memory_map.get_first_region_of_type(MemoryType.RAM) ram_start = ram_region.start ram_size = ram_region.length target = board.target test_params = get_target_test_params(session) session.probe.set_clock(test_params['test_clock']) test_pass_count = 0 test_count = 0 result = FlashTestResult() # Test each flash region separately. for rom_region in memory_map.get_regions_of_type(MemoryType.FLASH): if not rom_region.is_testable: continue rom_start = rom_region.start rom_size = rom_region.length flash = rom_region.flash flash_info = flash.get_flash_info() # This can be any value, as long as it's not the erased byte value. We take the # inverse of the erased value so that for most flash, the unerased value is 0x00. unerasedValue = invert32(flash.region.erased_byte_value) & 0xff print("\n\n===== Testing flash region '%s' from 0x%08x to 0x%08x ====" % (rom_region.name, rom_region.start, rom_region.end)) binary_file = os.path.join(parentdir, 'binaries', board.test_binary) with open(binary_file, "rb") as f: data = f.read() data = struct.unpack("%iB" % len(data), data) unused = rom_size - len(data) # Make sure data doesn't overflow this region. if unused < 0: data = data[:rom_size] unused = 0 addr = rom_start size = len(data) # Turn on extra checks for the next 4 tests flash.set_flash_algo_debug(True) print("\n------ Test Erased Value Check ------") d = [flash.region.erased_byte_value] * 128 if flash.region.is_erased(d): print("TEST PASSED") test_pass_count += 1 else: print("TEST FAILED") test_count += 1 d = [unerasedValue] + [flash.region.erased_byte_value] * 127 if not flash.region.is_erased(d): print("TEST PASSED") test_pass_count += 1 else: print("TEST FAILED") test_count += 1 print("\n------ Test Basic Page Erase ------") info = flash.flash_block(addr, data, False, "sector", progress_cb=print_progress()) data_flashed = target.read_memory_block8(addr, size) if same(data_flashed, data) and info.program_type is FlashBuilder.FLASH_SECTOR_ERASE: print("TEST PASSED") test_pass_count += 1 else: print("TEST FAILED") test_count += 1 print("\n------ Test Basic Chip Erase ------") info = flash.flash_block(addr, data, False, "chip", progress_cb=print_progress()) data_flashed = target.read_memory_block8(addr, size) if same(data_flashed, data) and info.program_type is FlashBuilder.FLASH_CHIP_ERASE: print("TEST PASSED") test_pass_count += 1 else: print("TEST FAILED") test_count += 1 print("\n------ Test Smart Page Erase ------") info = flash.flash_block(addr, data, True, "sector", progress_cb=print_progress()) data_flashed = target.read_memory_block8(addr, size) if same(data_flashed, data) and info.program_type is FlashBuilder.FLASH_SECTOR_ERASE: print("TEST PASSED") test_pass_count += 1 else: print("TEST FAILED") test_count += 1 print("\n------ Test Smart Chip Erase ------") info = flash.flash_block(addr, data, True, "chip", progress_cb=print_progress()) data_flashed = target.read_memory_block8(addr, size) if same(data_flashed, data) and info.program_type is FlashBuilder.FLASH_CHIP_ERASE: print("TEST PASSED") test_pass_count += 1 else: print("TEST FAILED") test_count += 1 flash.set_flash_algo_debug(False) print("\n------ Test Basic Page Erase (Entire region) ------") new_data = list(data) new_data.extend(unused * [0x77]) info = flash.flash_block(addr, new_data, False, "sector", progress_cb=print_progress()) if info.program_type == FlashBuilder.FLASH_SECTOR_ERASE: print("TEST PASSED") test_pass_count += 1 result.page_erase_rate = float(len(new_data)) / float(info.program_time) else: print("TEST FAILED") test_count += 1 print("\n------ Test Fast Verify ------") info = flash.flash_block(addr, new_data, progress_cb=print_progress(), fast_verify=True) if info.program_type == FlashBuilder.FLASH_SECTOR_ERASE: print("TEST PASSED") test_pass_count += 1 else: print("TEST FAILED") test_count += 1 print("\n------ Test Offset Write ------") addr = rom_start + rom_size // 2 page_size = flash.get_page_info(addr).size new_data = [0x55] * page_size * 2 info = flash.flash_block(addr, new_data, progress_cb=print_progress()) data_flashed = target.read_memory_block8(addr, len(new_data)) if same(data_flashed, new_data) and info.program_type is FlashBuilder.FLASH_SECTOR_ERASE: print("TEST PASSED") test_pass_count += 1 else: print("TEST FAILED") test_count += 1 print("\n------ Test Multiple Block Writes ------") addr = rom_start + rom_size // 2 page_size = flash.get_page_info(addr).size more_data = [0x33] * page_size * 2 addr = (rom_start + rom_size // 2) + 1 #cover multiple pages fb = flash.get_flash_builder() fb.add_data(rom_start, data) fb.add_data(addr, more_data) fb.program(progress_cb=print_progress()) data_flashed = target.read_memory_block8(rom_start, len(data)) data_flashed_more = target.read_memory_block8(addr, len(more_data)) if same(data_flashed, data) and same(data_flashed_more, more_data): print("TEST PASSED") test_pass_count += 1 else: print("TEST FAILED") test_count += 1 print("\n------ Test Overlapping Blocks ------") test_pass = False addr = (rom_start + rom_size // 2) #cover multiple pages page_size = flash.get_page_info(addr).size new_data = [0x33] * page_size fb = flash.get_flash_builder() fb.add_data(addr, new_data) try: fb.add_data(addr + 1, new_data) except ValueError as e: print("Exception: %s" % e) test_pass = True if test_pass: print("TEST PASSED") test_pass_count += 1 else: print("TEST FAILED") test_count += 1 print("\n------ Test Empty Block Write ------") # Freebee if nothing asserts fb = flash.get_flash_builder() fb.program() print("TEST PASSED") test_pass_count += 1 test_count += 1 print("\n------ Test Missing Progress Callback ------") # Freebee if nothing asserts addr = rom_start flash.flash_block(rom_start, data, True) print("TEST PASSED") test_pass_count += 1 test_count += 1 # Only run test if the reset handler can be programmed (rom start at address 0) if rom_start == 0: print("\n------ Test Non-Thumb reset handler ------") non_thumb_data = list(data) # Clear bit 0 of 2nd word - reset handler non_thumb_data[4] = non_thumb_data[4] & ~1 flash.flash_block(rom_start, non_thumb_data) flash.flash_block(rom_start, data) print("TEST PASSED") test_pass_count += 1 test_count += 1 # Note - The decision based tests below are order dependent since they # depend on the previous state of the flash if rom_start == flash_info.rom_start: print("\n------ Test Chip Erase Decision ------") new_data = list(data) new_data.extend([flash.region.erased_byte_value] * unused) # Pad with erased value info = flash.flash_block(addr, new_data, progress_cb=print_progress()) if info.program_type == FlashBuilder.FLASH_CHIP_ERASE: print("TEST PASSED") test_pass_count += 1 result.chip_erase_rate_erased = float(len(new_data)) / float(info.program_time) else: print("TEST FAILED") test_count += 1 print("\n------ Test Chip Erase Decision 2 ------") new_data = list(data) new_data.extend([unerasedValue] * unused) # Pad with unerased value info = flash.flash_block(addr, new_data, progress_cb=print_progress()) if info.program_type == FlashBuilder.FLASH_CHIP_ERASE: print("TEST PASSED") test_pass_count += 1 result.chip_erase_rate = float(len(new_data)) / float(info.program_time) else: print("TEST FAILED") test_count += 1 print("\n------ Test Page Erase Decision ------") new_data = list(data) new_data.extend([unerasedValue] * unused) # Pad with unerased value info = flash.flash_block(addr, new_data, progress_cb=print_progress()) if info.program_type == FlashBuilder.FLASH_SECTOR_ERASE: print("TEST PASSED") test_pass_count += 1 result.page_erase_rate_same = float(len(new_data)) / float(info.program_time) result.analyze = info.analyze_type result.analyze_time = info.analyze_time result.analyze_rate = float(len(new_data)) / float(info.analyze_time) else: print("TEST FAILED") test_count += 1 print("\n------ Test Page Erase Decision 2 ------") new_data = list(data) size_same = unused * 5 // 6 size_differ = unused - size_same new_data.extend([unerasedValue] * size_same) # Pad 5/6 with unerased value and 1/6 with 0x55 new_data.extend([0x55] * size_differ) info = flash.flash_block(addr, new_data, progress_cb=print_progress()) if info.program_type == FlashBuilder.FLASH_SECTOR_ERASE: print("TEST PASSED") test_pass_count += 1 else: print("TEST FAILED") test_count += 1 print("\n\nTest Summary:") print("Pass count %i of %i tests" % (test_pass_count, test_count)) if test_pass_count == test_count: print("FLASH TEST SCRIPT PASSED") else: print("FLASH TEST SCRIPT FAILED") target.reset() result.passed = test_count == test_pass_count return result