def bsl(self, cmd, message='', expect=None): self.bsl_header(cmd, message) if self.extra_timeout is None: head = self.serial.read(3) else: for timeout in range(self.extra_timeout): head = self.serial.read(3) if head: break if len(head) != 3: raise bsl5.BSL5Timeout('timeout while reading answer (header)') pi, length = struct.unpack("<BH", head) if pi == 0x80: data = self.serial.read(length) if len(data) != length: raise bsl5.BSL5Timeout('timeout while reading answer (data)') crc_str = self.serial.read(2) if len(crc_str) != 2: raise bsl5.BSL5Timeout('timeout while reading answer (CRC)') crc = struct.unpack("<H", crc_str) crc_expected = reduce(crc_update, data, 0xffff) crc_expected = struct.pack('<H', crc_expected) if crc_str != crc_expected: raise bsl5.BSL5Exception('CRC error in answer') if expect is not None and length != expect: raise bsl5.BSL5Error('expected %d bytes, got %d bytes' % (expect, len(data))) return data else: if pi: raise bsl5.BSL5Error( 'received bad PI, expected 0x80 (got 0x%02x)' % (pi)) raise bsl5.BSL5Error( 'received bad PI, expected 0x80 (got empty response)')
def bsl(self, cmd, message='', expect=None): """\ Low level access to the serial communication. This function sends a command and waits until it receives an answer (including timeouts). It will return a string with the data part of the answer. In case of a failure read timeout or rejected commands by the slave, it will raise an exception. If the parameter "expect" is not None, "expect" bytes are expected in the answer, an exception is raised if the answer length does not match. If "expect" is None, the answer is just returned. Frame format: +-----+----+----+-----------+----+----+ | HDR | LL | LH | D1 ... DN | CL | CH | +-----+----+----+-----------+----+----+ """ # first synchronize with slave self.logger.debug('Command 0x%02x %s' % (cmd, message.encode('hex'))) # prepare command with checksum txdata = struct.pack('<BHB', 0x80, 1 + len(message), cmd) + message txdata += struct.pack('<H', functools.reduce(crc_update, txdata, 0xffff)) # append checksum #~ self.logger.debug('Sending command: %r' % (txdata.encode('hex'),)) # transmit command self.serial.write(txdata) # wait for command answer if self.blindWrite: time.sleep(0.100) return if self.ignore_answer: return self.logger.debug('Reading answer...') if self.extra_timeout is None: ans = self.serial.read(1) else: for timeout in range(self.extra_timeout): ans = self.serial.read(1) if ans: break if ans != BSL5_ACK: if ans: raise bsl5.BSL5Error( 'BSL reports error: %s' % BSL5_UART_ERROR_CODES.get(ans, 'unknown error')) raise bsl5.BSL5Error('No ACK received (timeout)') head = self.serial.read(3) if len(head) != 3: raise bsl5.BSL5Timeout('timeout while reading answer (header)') pi, length = struct.unpack("<BH", head) if pi == '\x80': data = self.serial.read(length) if len(data) != length: raise bsl5.BSL5Timeout('timeout while reading answer (data)') crc_str = self.serial.read(2) if len(crc_str) != 2: raise bsl5.BSL5Timeout('timeout while reading answer (CRC)') crc = struct.unpack("<H", crc_str) crc_expected = functools.reduce(crc_update, head + data, 0xffff) if crc != crc_expected: raise bsl5.BSLException('CRC error in answer') if expect is not None and length != expect: raise bsl5.BSL5Error('expected %d bytes, got %d bytes' % (expect, len(data))) return data else: if pi: raise bsl5.BSL5Error( 'received bad PI, expected 0x80 (got 0x%02x)' % (ord(pi), )) raise bsl5.BSL5Error( 'received bad PI, expected 0x80 (got empty response)')