コード例 #1
0
class Rtt2Socket:
    def __init__(self,
                 own_send_socket_dict,
                 remote_socket_dict,
                 config=RttNordicConfig,
                 log_lvl=logging.INFO):
        self.config = config

        timeouts = {'descriptions': None, 'events': None}
        self.out_stream = Stream(own_send_socket_dict,
                                 timeouts,
                                 remote_socket_dict=remote_socket_dict)

        self.logger = logging.getLogger('Profiler Rtt to socket')
        self.logger_console = logging.StreamHandler()
        self.logger.setLevel(log_lvl)
        self.log_format = logging.Formatter(
            '[%(levelname)s] %(name)s: %(message)s')
        self.logger_console.setFormatter(self.log_format)
        self.logger.addHandler(self.logger_console)

        self.rtt_up_channels = {
            'info': None,
            'data': None,
        }
        self.rtt_down_channels = {
            'command': None,
        }
        self.connect()

    @staticmethod
    def rtt_get_device_family(snr):
        family = None
        with API('UNKNOWN') as api:
            if snr is not None:
                api.connect_to_emu_with_snr(snr)
            else:
                api.connect_to_emu_without_snr()
            family = api.read_device_family()
            api.disconnect_from_emu()
        return family

    def connect(self):
        snr = self.config['device_snr']
        device_family = Rtt2Socket.rtt_get_device_family(snr)
        self.logger.info('Recognized device family: ' + device_family)
        self.jlink = API(device_family)
        self.jlink.open()

        if snr is not None:
            self.jlink.connect_to_emu_with_snr(self.config['device_snr'])
        else:
            self.jlink.connect_to_emu_without_snr()

        if self.config['reset_on_start']:
            self.jlink.sys_reset()
            self.jlink.go()

        self.jlink.rtt_start()

        TIMEOUT = 20
        start_time = time.time()
        while not self.jlink.rtt_is_control_block_found():
            if time.time() - start_time > TIMEOUT:
                self.logger.error("Cannot find RTT control block")
                sys.exit()

            time.sleep(0.2)

        while (None in list(self.rtt_up_channels.values())) or \
              (None in list(self.rtt_down_channels.values())):
            down_channel_cnt, up_channel_cnt = self.jlink.rtt_read_channel_count(
            )

            for idx in range(0, down_channel_cnt):
                chan_name, _ = self.jlink.rtt_read_channel_info(
                    idx, 'DOWN_DIRECTION')

                try:
                    label = self.config['rtt_down_channel_names'][chan_name]
                    self.rtt_down_channels[label] = idx
                except KeyError:
                    continue

            for idx in range(0, up_channel_cnt):
                chan_name, _ = self.jlink.rtt_read_channel_info(
                    idx, 'UP_DIRECTION')

                try:
                    label = self.config['rtt_up_channel_names'][chan_name]
                    self.rtt_up_channels[label] = idx
                except KeyError:
                    continue

            if time.time() - start_time > TIMEOUT:
                self.logger.error(
                    "Cannot find properly configured RTT channels")
                sys.exit()

            time.sleep(0.2)

        self.logger.info("Connected to device via RTT")

    def disconnect(self):
        self.stop_logging_events()
        # read remaining data to buffer
        bufs = bytearray()
        while True:
            try:
                buf = self.jlink.rtt_read(self.rtt_up_channels['data'],
                                          self.config['rtt_read_chunk_size'],
                                          encoding=None)

            except APIError:
                self.logger.error("Problem with reading RTT data")
                buf = []

            if len(buf) > 0:
                bufs.extend(buf)
            else:
                if len(bufs) > 0:
                    try:
                        self.out_stream.send_ev(bufs)
                    except StreamError as err:
                        self.logger.info("Unable to send remaining events: " +
                                         str(err))
                break

        try:
            self.jlink.rtt_stop()
            self.jlink.disconnect_from_emu()
            self.jlink.close()

        except APIError:
            self.logger.error("JLink connection lost")
            return

        self.logger.info("Disconnected from device")

    def read_bytes(self):
        try:
            buf = self.jlink.rtt_read(self.rtt_up_channels['data'],
                                      self.config['rtt_read_chunk_size'],
                                      encoding=None)

        except APIError:
            self.logger.error("Problem with reading RTT data")
            self.disconnect()
            sys.exit()

        return buf

    def _read_all_events_descriptions(self):
        self._send_command(Command.INFO)
        desc_buf = bytearray()
        # Empty field is send after last event description
        while True:
            try:
                buf_temp = self.jlink.rtt_read(
                    self.rtt_up_channels['info'],
                    self.config['rtt_read_chunk_size'],
                    encoding=None)
            except APIError:
                self.logger.error("Problem with reading RTT data")
                self.disconnect()
                sys.exit()

            desc_buf.extend(buf_temp)
            if buf_temp[-2:] == bytearray('\n\n', 'utf-8'):
                return desc_buf
            time.sleep(0.1)

    def read_and_transmit_data(self):
        desc_buf = self._read_all_events_descriptions()
        try:
            self.out_stream.send_desc(desc_buf)
        except StreamError as err:
            self.logger.error("Error. Unable to send data: {}".format(err))
            self.disconnect()
            sys.exit()

        self.start_logging_events()
        while True:
            buf = self.read_bytes()

            if len(buf) > 0:
                try:
                    self.out_stream.send_ev(buf)
                except StreamError as err:
                    if err.args[1] != 'closed':
                        self.logger.error(
                            "Error. Unable to send data: {}".format(err))
                        self.disconnect()
                        sys.exit()
                    # Receiver has been closed
                    self.close()

            if len(buf) < self.config['rtt_additional_read_thresh']:
                time.sleep(self.config['rtt_read_sleep_time'])

    def start_logging_events(self):
        self._send_command(Command.START)

    def stop_logging_events(self):
        self._send_command(Command.STOP)

    def _send_command(self, command_type):
        command = bytearray(1)
        command[0] = command_type.value
        try:
            self.jlink.rtt_write(self.rtt_down_channels['command'], command,
                                 None)
        except APIError:
            self.logger.error("Problem with writing RTT data")

    def close(self):
        self.logger.info("Real time transmission closed")
        self.disconnect()
        sys.exit()
コード例 #2
0
class RttNordicProfilerHost:
    def __init__(self,
                 config=RttNordicConfig,
                 finish_event=None,
                 queue=None,
                 event_filename=None,
                 event_types_filename=None,
                 log_lvl=logging.WARNING):
        self.event_filename = event_filename
        self.event_types_filename = event_types_filename
        self.config = config
        self.finish_event = finish_event
        self.queue = queue
        self.received_events = EventsData([], {})
        self.timestamp_overflows = 0
        self.after_half = False

        self.desc_buf = ""
        self.bufs = list()
        self.bcnt = 0
        self.last_read_time = time.time()
        self.reading_data = True

        self.logger = logging.getLogger('RTT Profiler Host')
        self.logger_console = logging.StreamHandler()
        self.logger.setLevel(log_lvl)
        self.log_format = logging.Formatter(
            '[%(levelname)s] %(name)s: %(message)s')
        self.logger_console.setFormatter(self.log_format)
        self.logger.addHandler(self.logger_console)

        self.connect()

    @staticmethod
    def rtt_get_device_family(snr):
        family = None
        with API('UNKNOWN') as api:
            if snr is not None:
                api.connect_to_emu_with_snr(snr)
            else:
                api.connect_to_emu_without_snr()
            family = api.read_device_family()
            api.disconnect_from_emu()
        return family

    def connect(self):
        snr = self.config['device_snr']
        device_family = RttNordicProfilerHost.rtt_get_device_family(snr)
        self.logger.info('Recognized device family: ' + device_family)
        self.jlink = API(device_family)
        self.jlink.open()

        if snr is not None:
            self.jlink.connect_to_emu_with_snr(self.config['device_snr'])
        else:
            self.jlink.connect_to_emu_without_snr()

        if self.config['reset_on_start']:
            self.jlink.sys_reset()
            self.jlink.go()

        self.jlink.rtt_start()

        TIMEOUT = 20
        start_time = time.time()
        while not self.jlink.rtt_is_control_block_found():
            if time.time() - start_time > TIMEOUT:
                self.logger.error("Cannot find RTT control block")
                sys.exit()

            time.sleep(1)

        self.logger.info("Connected to device via RTT")

    def shutdown(self):
        self.disconnect()
        self._read_remaining_events()
        if self.event_filename and self.event_types_filename:
            self.received_events.write_data_to_files(self.event_filename,
                                                     self.event_types_filename)

    def disconnect(self):
        self.stop_logging_events()
        # read remaining data to buffer
        while True:
            try:
                buf = self.jlink.rtt_read(self.config['rtt_data_channel'],
                                          self.config['rtt_read_chunk_size'],
                                          encoding=None)

            except APIError:
                self.logger.error("Problem with reading RTT data.")
                buf = []

            if len(buf) > 0:
                self.bufs.append(buf)
                self.bcnt += len(buf)
            else:
                break

        try:
            self.jlink.rtt_stop()
            self.jlink.disconnect_from_emu()
            self.jlink.close()

        except APIError:
            self.logger.error("JLink connection lost. Saving collected data.")
            return

        self.logger.info("Disconnected from device")

    def _get_buffered_data(self, num_bytes):
        buf = bytearray()
        while len(buf) < num_bytes:
            tbuf = self.bufs[0]
            size = num_bytes - len(buf)
            if len(tbuf) <= size:
                buf = buf + tbuf
                del self.bufs[0]
            else:
                buf = buf + tbuf[0:size]
                self.bufs[0] = tbuf[size:]
        self.bcnt -= num_bytes
        return buf

    def _read_bytes(self, num_bytes):
        now = time.time()

        while self.reading_data:
            if now - self.last_read_time < self.config['rtt_read_period'] \
            and self.bcnt >= num_bytes:
                break

            try:
                buf = self.jlink.rtt_read(self.config['rtt_data_channel'],
                                          self.config['rtt_read_chunk_size'],
                                          encoding=None)
            except APIError:
                self.logger.error("Problem with reading RTT data.")
                self.shutdown()
                sys.exit()

            if len(buf) > 0:
                self.bufs.append(buf)
                self.bcnt += len(buf)

            if len(buf) > self.config['rtt_additional_read_thresh']:
                continue

            self.last_read_time = now

            if self.bcnt >= num_bytes:
                break

            if self.finish_event is not None and self.finish_event.is_set():
                self.finish_event.clear()
                self.logger.info("Real time transmission closed")
                self.shutdown()
                self.logger.info("Events data saved to files")
                sys.exit()

            time.sleep(0.05)

        return self._get_buffered_data(num_bytes)

    def _calculate_timestamp_from_clock_ticks(self, clock_ticks):
        return self.config['ms_per_timestamp_tick'] * (
            clock_ticks +
            self.timestamp_overflows * self.config['timestamp_raw_max']) / 1000

    def _read_single_event_description(self):
        while '\n' not in self.desc_buf:
            try:
                buf_temp = self.jlink.rtt_read(
                    self.config['rtt_info_channel'],
                    self.config['rtt_read_chunk_size'],
                    encoding='utf-8')

            except APIError:
                self.logger.error("Problem with reading RTT data.")
                self.shutdown()

            self.desc_buf += buf_temp
            time.sleep(0.1)

        desc = str(self.desc_buf[0:self.desc_buf.find('\n')])
        # Empty field is send after last event description
        if len(desc) == 0:
            return None, None
        self.desc_buf = self.desc_buf[self.desc_buf.find('\n') + 1:]

        desc_fields = desc.split(',')

        name = desc_fields[0]
        id = int(desc_fields[1])
        data_type = []
        for i in range(2, len(desc_fields) // 2 + 1):
            data_type.append(desc_fields[i])
        data = []
        for i in range(len(desc_fields) // 2 + 1, len(desc_fields)):
            data.append(desc_fields[i])
        return id, EventType(name, data_type, data)

    def _read_all_events_descriptions(self):
        while True:
            id, et = self._read_single_event_description()
            if (id is None or et is None):
                break
            self.received_events.registered_events_types[id] = et

    def get_events_descriptions(self):
        self._send_command(Command.INFO)
        self._read_all_events_descriptions()
        if self.queue is not None:
            self.queue.put(self.received_events.registered_events_types)
        self.logger.info("Received events descriptions")
        self.logger.info("Ready to start logging events")

    def _read_single_event_rtt(self):
        id = int.from_bytes(self._read_bytes(1),
                            byteorder=self.config['byteorder'],
                            signed=False)
        et = self.received_events.registered_events_types[id]

        buf = self._read_bytes(4)
        timestamp_raw = (int.from_bytes(buf,
                                        byteorder=self.config['byteorder'],
                                        signed=False))

        if self.after_half \
        and timestamp_raw < 0.2 * self.config['timestamp_raw_max']:
            self.timestamp_overflows += 1
            self.after_half = False

        if timestamp_raw > 0.6 * self.config['timestamp_raw_max']:
            if timestamp_raw < 0.9 * self.config['timestamp_raw_max']:
                self.after_half = True

        timestamp = self._calculate_timestamp_from_clock_ticks(timestamp_raw)

        data = []
        for i in et.data_types:
            signum = False
            if i[0] == 's':
                signum = True
            buf = self._read_bytes(4)
            data.append(
                int.from_bytes(buf,
                               byteorder=self.config['byteorder'],
                               signed=signum))
        return Event(id, timestamp, data)

    def _read_remaining_events(self):
        self.reading_data = False
        while self.bcnt != 0:
            event = self._read_single_event_rtt()
            self.received_events.events.append(event)
            if self.queue is not None:
                self.queue.put(event)

        # End of transmission
        if self.queue is not None:
            self.queue.put(None)

    def read_events_rtt(self, time_seconds):
        self.logger.info("Start logging events data")
        self.start_logging_events()
        start_time = time.time()
        current_time = start_time
        while current_time - start_time < time_seconds or time_seconds < 0:
            event = self._read_single_event_rtt()
            self.received_events.events.append(event)
            if self.queue is not None:
                self.queue.put(event)
            current_time = time.time()
        self.logger.info("Real time transmission closed")
        self.shutdown()
        self.logger.info("Events data saved to files")
        sys.exit()

    def start_logging_events(self):
        self._send_command(Command.START)

    def stop_logging_events(self):
        self._send_command(Command.STOP)

    def _send_command(self, command_type):
        command = bytearray(1)
        command[0] = command_type.value
        try:
            self.jlink.rtt_write(self.config['rtt_command_channel'], command,
                                 None)
        except APIError:
            self.logger.error("Problem with writing RTT data.")