Example #1
0
 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)
Example #2
0
 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)
Example #3
0
def phil_init_ex():
    phil = PhilipExtIf()
    yield phil
    phil.dev.close()
Example #4
0
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
Example #5
0
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)))
Example #6
0
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)