def __init__(self, port=None, data_only=True, use_dev_map=False): if port is None: self.phil = self._connect_wizard(use_dev_map=use_dev_map) else: self.phil = PhilipExtIf(port, use_dev_map=use_dev_map) print("Interface Version: {}".format(self.phil.if_version)) self.data_only = data_only cmd.Cmd.__init__(self)
def _connect_wizard(use_dev_map=False): print("Starting PHiLIP shell") serial_devices = serial.tools.list_ports.comports() if len(serial_devices) == 0: raise ConnectionError("Could not find any available devices") elif len(serial_devices) == 1: print('Connected to {}'.format(serial_devices[0])) return PhilipExtIf(port=serial_devices[0][0], use_dev_map=use_dev_map) else: print('Select a serial port:') for i, s_dev in enumerate(serial_devices): print("{}: {}".format(i, s_dev)) s_num = input("Selection(number): ") return PhilipExtIf(port=serial_devices[int(s_num)][0], use_dev_map=use_dev_map)
def phil_init_ex(): phil = PhilipExtIf() yield phil phil.dev.close()
def test_parse_array(data, type_size, prim_type, expected): """Tests parsing an array with various sizes""" assert PhilipExtIf()._parse_array(data, type_size, prim_type) == expected
def test_mm_from_version(regtest, version_str): """Regression tests for all version of mem maps""" regtest.write(pformat(PhilipExtIf().mm_from_version(version_str)))
class PhilipShell(cmd.Cmd): """Command loop for the PHiLIP interface Args: port - Serial port for the PHiLIP, if None connection wizard tries to connent data_only - If true only data prints from command an not the whole response struct """ prompt = 'PHiLIP: ' def __init__(self, port=None, data_only=True, use_dev_map=False): if port is None: self.phil = self._connect_wizard(use_dev_map=use_dev_map) else: self.phil = PhilipExtIf(port, use_dev_map=use_dev_map) print("Interface Version: {}".format(self.phil.if_version)) self.data_only = data_only cmd.Cmd.__init__(self) @staticmethod def _connect_wizard(use_dev_map=False): print("Starting PHiLIP shell") serial_devices = serial.tools.list_ports.comports() if len(serial_devices) == 0: raise ConnectionError("Could not find any available devices") elif len(serial_devices) == 1: print('Connected to {}'.format(serial_devices[0])) return PhilipExtIf(port=serial_devices[0][0], use_dev_map=use_dev_map) else: print('Select a serial port:') for i, s_dev in enumerate(serial_devices): print("{}: {}".format(i, s_dev)) s_num = input("Selection(number): ") return PhilipExtIf(port=serial_devices[int(s_num)][0], use_dev_map=use_dev_map) def preloop(self): if readline: try: readline.read_history_file() except IOError: pass def do_read_reg(self, arg): """Read a register defined by the memory map Usage: read_reg <cmd_name> [offset] [size] [to_byte_array] [timeout] Args: cmd_name: The name of the register to read offset: The number of elements to offset in an array size: The number of elements to read in an array to_byte_array: If True and data is bytes leave it as an array timeout: Optional timeout value for command specific timeouts """ self._print_func_result(self.phil.read_reg, arg) def complete_read_reg(self, text, line, begidx, endidx): """Completes arg with memory map record names""" begidx = begidx endidx = endidx return self._complete_map(text, line) def do_write_reg(self, arg): """Writes a register defined by the memory map If writing to change a periph configuration the .mode.init bit should be set to 0 for reinitialization to occur. Usage: write_reg <cmd_name> <data> [offset] [timeout] Args: cmd_name: The name of the register to write data: The data to write to the register offset: The number of elements to offset in an array timeout: Optional timeout value for command specific timeouts Example: To write to user register 0 the data 42 we can do this write_reg user_reg 42 0 To write many bytes the data must not be seperated by spaces write_reg user_reg [1,2,3,4,5,6] 0 """ self._print_func_result(self.phil.write_reg, arg) def complete_write_reg(self, text, line, begidx, endidx): """Completes arg with memory map record names""" begidx = begidx endidx = endidx return self._complete_map(text, line) def do_read_struct(self, arg): """Reads a set of registers defined by the memory map Usage: read_struct <cmd_name> [timeout] Args: cmd_name: The name if the structure to read timeout: Optional timeout value for command specific timeouts """ self._print_func_result(self.phil.read_struct, arg) def complete_read_struct(self, text, line, begidx, endidx): """Completes arg with memory map record structs""" begidx = begidx endidx = endidx mline = line.partition(' ')[2] offs = len(mline) - len(text) map_records = [*self.phil.mem_map] map_structs = [] for record in map_records: first_name = record.split('.')[0] if first_name not in map_structs: map_structs.append(first_name) return [s[offs:] for s in map_structs if s.startswith(mline)] def do_execute_changes(self, arg): """Executes or commits device configuration changes This will cause any changes in configuration to be applied. For many periphs the .mode.init must be set to 0 for the periph to reinitialize. Usage: execute_changes [timeout] Args: timeout: Optional timeout value for command specific timeouts """ self._print_func_result(self.phil.execute_changes, arg) def do_philip_reset(self, arg): """Resets the device Usage: philip_reset [timeout] Args: timeout: Optional timeout value for command specific timeouts """ self._print_func_result(self.phil.reset_mcu, arg) def do_get_version(self, arg): """Get the version of the interface/memory map that is being used Usage: philip_reset """ arg = arg print(self.phil.if_version) def do_write_and_execute(self, arg): """Writes the register and the init for the struct and executes changes Usage: write_and_execute <cmd_name> <data> [timeout] Args: cmd_name: The name of the register to write data: The data to write to the register timeout: Optional timeout value for command specific timeouts """ self._print_func_result(self.phil.write_and_execute, arg) def complete_write_and_execute(self, text, line, begidx, endidx): """Completes arg with memory map record names""" begidx = begidx endidx = endidx return self._complete_map(text, line) def do_dut_reset(self, arg): """Provides a reset to the dut Toggles the dut reset pin for the reset time. Usage: dut_reset [reset_time] [timeout] Args: reset_time: Optional duration the dut is put in reset timeout: Optional timeout value for command specific timeouts """ self._print_func_result(self.phil.dut_reset, arg) def do_read_trace(self, arg): """Reads event trace from the dut Usage: read_trace """ self._print_func_result(self.phil.read_trace, arg) def do_data_filter(self, arg): """Select or toggle filtering for data Usage: data_filter [{ON, OFF}] Args: {ON, OFF}: Turn filtering on or off, if no arg it toggles """ if arg: if arg.upper() == "ON": self.data_only = True print("Filtering for data") elif arg.upper() == "OFF": self.data_only = False print("Raw data, no filtering") else: print("Incorrect arg") elif self.data_only: self.data_only = False print("Raw data, no filtering") else: self.data_only = True print("Filtering for data") def do_print_map(self, arg): """Prints the device map Usage: print_map [cmd_name] Args: cmd_name: The name of the register in the map to print """ arg = arg if arg: try: print(dumps(self.phil.mem_map[arg], sort_keys=True, indent=4)) except KeyError as exc: print("Cannot parse {}".format(exc)) else: print(dumps(self.phil.mem_map, sort_keys=True, indent=4)) def complete_print_map(self, text, line, begidx, endidx): """Completes arg with memory map record names""" begidx = begidx endidx = endidx return self._complete_map(text, line) def _complete_map(self, text, line): mline = line.partition(' ')[2] offs = len(mline) - len(text) map_records = [*self.phil.mem_map] return [s[offs:] for s in map_records if s.startswith(mline)] def do_info_record_type(self, arg): """Prints the device map Usage: info_record_type <record_type> Args: record_type: The record type in a map, such as description """ try: record_types = {} for key, val in self.phil.mem_map.items(): if arg in val: if val[arg]: record_types[key] = val[arg] print(dumps(record_types, sort_keys=True, indent=4)) except KeyError as exc: print("Cannot parse {}".format(exc)) # pylint: disable=R0201 def complete_info_record_type(self, text, line, begidx, endidx): """Completes arg with common record types""" begidx = begidx endidx = endidx mline = line.partition(' ')[2] offs = len(mline) - len(text) info_record_types = [ 'description', 'access', 'default', 'bit', 'flag', 'max', 'min' ] return [s[offs:] for s in info_record_types if s.startswith(mline)] def do_show_pinout(self, arg): """Prints the pinout for the connected board Usage: show_pinout """ try: if arg: showboard = int(arg) else: showboard = self.phil.read_reg('sys.status.board')['data'] if showboard == 1: print(""" PHILIP-B -> BLUEPILL ____ ___|__|___ DUT_RST = B12 - | | - GND DUT_CTS = B13 - | | - GND DUT_RTS = B14 - | | - 3V3 USER_BTN = B15 - | | - NRST DUT_IC = A8 - | | - B11 = DUT_RX IF_TX = A9 - | | - B10 = DUT_TX IF_RX = A10 - | | - B1 = PM_V_ADC USB_DM = A11 - | | - B0 = PM_HI_ADC USB_DP = A12 - | | - A7 = PM_LO_ADC DUT_NSS = A15 - | | - A6 = DUT_ADC DUT_SCK = B3 - | | - A5 = TEST_FAIL DUT_MISO = B4 - | | - A4 = TEST_WARN DUT_MOSI = B5 - | | - A3 = TEST_PASS DUT_SCL = B6 - | | - A2 = DEBUG2 DUT_SDA = B7 - | | - A1 = DEBUG1 DUT_PWM = B8 - | | - A0 = DEBUG0 DUT_DAC = B9 - | | - C15 5V - | | - C14 GND - | | - C13 = LED0 3V3 - | | - VBAT __________ |||| """) else: print(""" PHILIP-N -> NUCLEO-F103RB CN6 CN5 DUT_SCL = PB8 = SCL/D15 - DUT_SDA = PB9 = SDA/D14 - AVDD - GND - - LED0 = PA5 =SCK/D13 - - IOREF MISO/D12 - - NRST PWM/MOSI/D11 - - 3V3 PWM/CS/D10 - - 5V PWM/D9 - - GND DUT_TX = PA9 = D8 - - GND - VIN DUT_IC = PA8 = D7 - PWM/D6 - - A0 = PA0 = TEST_WARN DEBUG1 = PB4 = PWM/D5 - - A1 = PA1 = TEST_FAIL DEBUG2 = PB5 = D4 - - A2 = PA4 = TEST_PASS DEBUG0 = PB3 = PWM/D3 - - A3 = PB0 = DUT_ADC DUT_RX = PA10 = D2 - - A4 = PC1 = PM_HI_ADC IF_TX = PA2 = TX/D1 - - A5 = PC0 = PM_V_ADC IF_RX = PA3 = RX/D0 - CN8 CN9 -1 - DUT_DAC -1 - DUT_PWM -2 - DUT_SCL -2 - -3 - DUT_SDA -3 - -4 - -4 - -5 - -5 - -6 - LED0 -6 - DUT_RTS -7 - -7 - DUT_CTS -8 - -8 - DUT_NSS -9 - -9 - -10- -10- -11- DUT_TX -11- DUT_RST USER_BTN -12- DUT_IC -12- -13- -13- DUT_MOSI -14- TEST_WARN DEBUG1 -14- DUT_MISO -15- TEST_FAIL DEBUG2 -15- DUT_SCK -16- TEST_PASS DEBUG0 -16- -17- DUT_ADC DUT_RX -17- PM_LO_ADC -18- PM_HI_ADC IF_TX -18- -19- PM_V_ADC IF_RX -19- """) except (ValueError) as exc: print(exc) def do_exit(self, arg): """I mean it should be obvious Usage: exit """ arg = arg return True def _print_func_result_success(self, results): if not isinstance(results, list): results = [results] result = self.phil.RESULT_SUCCESS printed_something = False for res in results: if self.data_only: if 'result' in res: if res['result'] is self.phil.RESULT_SUCCESS: if 'data' in res: print(dumps(res['data'])) printed_something = True else: result = res['result'] else: print(dumps(res)) printed_something = True else: print(dumps(res)) printed_something = True if not printed_something: print(result) def _print_func_result(self, func, arg): value = (arg or '').split(' ') func_args = [v for v in value if v] try: results = func(*func_args) except KeyError as exc: print('Could not parse argument {}'.format(exc)) except (TypeError, ValueError, SyntaxError) as exc: print(exc) else: self._print_func_result_success(results)