def start(self): GPIOUtils.setup() hwprofile = GPIOUtils.get_hardware_profile() while hwprofile is None or "HARDWARE_VERSION" not in hwprofile: logger.error("Fetch hardware profile failed: %s", hwprofile) try: logger.error("Re-burn firmware") fsrc = resource_stream("fluxmonitor", "data/mainboard.bin") storage = Storage("update_fw") with storage.open("mainboard.bin", "wb") as fdst: copyfileobj(fsrc, fdst) GPIOUtils.update_mbfw() except RuntimeWarning as e: logger.error("%s", e.args[0]) except Exception: logger.exception("Re-burn firmware failed") sleep(3.0) hwprofile = GPIOUtils.get_hardware_profile() self.hwprofile = hwprofile if get_model_id() == MODEL_D1P: self.gpio = PinMappingV1(self.meta) else: self.gpio = PinMappingV0(self.meta) self.btn_monitor = FrontButtonMonitor(self.gpio, self.kernel.loop, self.send_button_event) self.connect_uart()
def on_binary(self, buf, handler): try: l = len(buf) if self.padding_length > l: self.tmpfile.write(buf) self.padding_length -= l else: if self.padding_length == l: self.tmpfile.write(buf) else: self.tmpfile.write(buf[:self.padding_length]) logger.error("Recv data length error") handler.binary_mode = False logger.info("New firmware received") self.tmpfile.file.flush() self.tmpfile.seek(0) s = Storage("update_fw") with s.open("upload.fxfw", "wb") as f: f.write(self.tmpfile.read()) proc = Popen(["fxupdate.py", "--dryrun", self.tmpfile.name]) self.subwatcher = self.stack.loop.child( proc.pid, False, self.on_verified, (handler, proc)) self.subwatcher.start() except RuntimeError as e: handler.send_text(("error %s" % e.args[0]).encode()) except Exception: logger.exception("Unhandle Error") handler.send_text("error %s" % UNKNOWN_ERROR)
def on_binary(self, buf, handler): try: l = len(buf) if self.padding_length > l: self.tmpfile.write(buf) self.padding_length -= l else: if self.padding_length == l: self.tmpfile.write(buf) else: self.tmpfile.write(buf[:self.padding_length]) handler.binary_mode = False self.tmpfile.seek(0) s = Storage("update_fw") with s.open("head.bin", "wb") as f: f.write(self.tmpfile.read()) logger.info("Head fireware uploaded, start processing") handler.send_text("ok") self.process_update(handler) # Note: self.process_update will invoke self.stack.exit_task except RuntimeError as e: handler.send_text(("error %s" % e.args[0]).encode()) except Exception: logger.exception("Unhandle Error") handler.send_text("error " + UNKNOWN_ERROR)
def on_binary(self, buf, handler): try: l = len(buf) if self.padding_length > l: self.tmpfile.write(buf) self.padding_length -= l else: if self.padding_length == l: self.tmpfile.write(buf) else: self.tmpfile.write(buf[:self.padding_length]) handler.binary_mode = False self.tmpfile.seek(0) s = Storage("update_fw") with s.open("mainboard.bin", "wb") as f: f.write(self.tmpfile.read()) logging.warn("Fireware uploaded, start processing") self.send_upload_request() handler.send_text("ok") self.stack.exit_task(self, True) except RuntimeError as e: handler.send_text(("error %s" % e.args[0]).encode()) except Exception: logger.exception("Unhandle Error") handler.send_text("error %s" % UNKNOWN_ERROR)
def update_hbfw(self, stage_cb=lambda m: None): raspi_uart = Serial(port="/dev/ttyAMA0", baudrate=115200, stopbits=1, xonxoff=0, rtscts=0, timeout=0) def wait_ack(stage): t = time() while time() - t < 5.0: rl = select((raspi_uart, ), (), (), 5.0)[0] if rl: ret = raspi_uart.read(1) if ret == 'y': return elif ret == '\x1f': raise RuntimeError(SUBSYSTEM_ERROR, "HEAD RETURN 0x1f") else: raise RuntimeError(UNKNOWN_ERROR, "HEAD RETURN %s" % repr(ret)) raise RuntimeError(NO_RESPONSE, stage) def send_cmd(cmd, stage): raspi_uart.write(chr(cmd)) raspi_uart.write(chr(cmd ^ 0xFF)) wait_ack(stage) sleep(0.1) def crc8(msg, init=0): crc = init for c in msg: crc = crc ^ ord(c) return chr(crc) def bootloader_hello(): raspi_uart.write('\x7f') wait_ack("HELLO") logger.debug("Update head fw") storage = Storage("update_fw") if not storage.exists("head.bin"): raise RuntimeError(NOT_FOUND) with storage.open("head.bin", "rb") as f: fw = f.read() size = len(fw) pages = size // 2048 if size % 2048 > 0: pages += 1 logger.debug("Fw size=%i, use page=%i", size, pages) try: # Bootstrap stage_cb(b"B") raspi_uart.parity = PARITY_EVEN GPIO.output(self.TOOLHEAD_POWER, self.TOOLHEAD_POWER_OFF) GPIO.output(self.TOOLHEAD_BOOT, GPIO.HIGH) sleep(0.5) GPIO.output(self.TOOLHEAD_POWER, self.TOOLHEAD_POWER_ON) sleep(0.5) raspi_uart.setRTS(0) raspi_uart.setDTR(0) sleep(0.1) raspi_uart.setDTR(1) sleep(0.5) # Hello stage_cb(b"H") try: bootloader_hello() except Exception: sleep(0.5) bootloader_hello() send_cmd(0x00, "G_VR") l = ord(raspi_uart.read()) version = raspi_uart.read(1) a = raspi_uart.read(l) logger.debug("VER %s", repr(a)) wait_ack("G_VRL") logger.debug("Update head: bootloader ver=%s", version) if version != '1': raise RuntimeError(NOT_SUPPORT) # Earse stage_cb(b"E") send_cmd(0x44, "G_ERASE") cmd = struct.pack(">H", pages - 1) cmd += "".join([struct.pack(">H", i) for i in xrange(pages)]) raspi_uart.write(cmd) raspi_uart.write(crc8(cmd)) wait_ack("G_E") # Write stage_cb(b"W") offset = 0 while offset < size: stage_cb(("%07x" % (size - offset)).encode()) l = min(size - offset, 128) send_cmd(0x31, "G_WINIT") addr = struct.pack(">I", 0x08000000 + offset) raspi_uart.write(addr) raspi_uart.write(crc8(addr)) wait_ack("G_WREADY") payload = chr(l - 1) + fw[offset:offset + l] raspi_uart.write(payload) raspi_uart.write(crc8(payload)) wait_ack("G_WDONE") offset += l stage_cb("00000000") finally: GPIO.output(self.TOOLHEAD_BOOT, GPIO.LOW) GPIO.output(self.TOOLHEAD_POWER, self.TOOLHEAD_POWER_OFF) sleep(0.5) GPIO.output(self.TOOLHEAD_POWER, self._head_power_stat) raspi_uart.parity = PARITY_NONE raspi_uart.close() logger.debug("Update fw end")