def reset_to_bootloader(args): dbg_print("======== RESET TO BOOTLOADER ========") s = serial.Serial(port=args.port, baudrate=args.baud, bytesize=8, parity='N', stopbits=1, timeout=1, xonxoff=0, rtscts=0) rl = SerialHelper.SerialHelper(s, 3.) rl.clear() if args.half_duplex: BootloaderInitSeq = bootloader.get_init_seq('GHST', args.type) dbg_print(" * Using half duplex (GHST)") else: BootloaderInitSeq = bootloader.get_init_seq('CRSF', args.type) dbg_print(" * Using full duplex (CRSF)") rl.write(BootloaderInitSeq) s.flush() rx_target = rl.read_line().strip() flash_target = re.sub("_VIA_.*", "", args.target.upper()) if rx_target == "": dbg_print("Cannot detect RX target, blindly flashing!") elif rx_target != flash_target: raise WrongTargetSelected("Wrong target selected your RX is '%s', trying to flash '%s'" % (rx_target, flash_target)) elif flash_target != "": dbg_print("Verified RX target '%s'" % (flash_target)) time.sleep(.5) s.close()
def reset_to_bootloader(args) -> int: dbg_print("======== RESET TO BOOTLOADER ========") s = serial.Serial(port=args.port, baudrate=args.baud, bytesize=8, parity='N', stopbits=1, timeout=1, xonxoff=0, rtscts=0) rl = SerialHelper.SerialHelper(s, 3.) rl.clear() if args.half_duplex: BootloaderInitSeq = bootloader.get_init_seq('GHST', args.type) dbg_print(" * Using half duplex (GHST)") else: BootloaderInitSeq = bootloader.get_init_seq('CRSF', args.type) dbg_print(" * Using full duplex (CRSF)") #this is the training sequ for the ROM bootloader, we send it here so it doesn't auto-neg to the wrong baudrate by the BootloaderInitSeq that we send to reset ELRS rl.write(b'\x07\x07\x12\x20' + 32 * b'\x55') time.sleep(0.2) rl.write(BootloaderInitSeq) s.flush() rx_target = rl.read_line().strip() flash_target = re.sub("_VIA_.*", "", args.target.upper()) ignore_incorrect_target = args.action == "uploadforce" if rx_target == "": dbg_print("Cannot detect RX target, blindly flashing!") elif ignore_incorrect_target: dbg_print(f"Force flashing {flash_target}, detected {rx_target}") elif rx_target != flash_target: if query_yes_no( "\n\n\nWrong target selected! your RX is '%s', trying to flash '%s', continue? Y/N\n" % (rx_target, flash_target)): dbg_print("Ok, flashing anyway!") else: dbg_print( "Wrong target selected your RX is '%s', trying to flash '%s'" % (rx_target, flash_target)) return ElrsUploadResult.ErrorMismatch elif flash_target != "": dbg_print("Verified RX target '%s'" % (flash_target)) time.sleep(.5) s.close() return ElrsUploadResult.Success
def reset_to_bootloader(args): dbg_print("======== RESET TO BOOTLOADER ========") s = serial.Serial(port=args.port, baudrate=args.baud, bytesize=8, parity='N', stopbits=1, timeout=1, xonxoff=0, rtscts=0) if args.half_duplex: BootloaderInitSeq = bootloader.get_init_seq('GHST', args.type) dbg_print(" * Using half duplex (GHST)") else: BootloaderInitSeq = bootloader.get_init_seq('CRSF', args.type) dbg_print(" * Using full duplex (CFSF)") s.write(BootloaderInitSeq) s.flush() time.sleep(.5) s.close()
def uart_upload(port, filename, baudrate, ghst=False, ignore_incorrect_target=False, key=None, target="") -> int: SCRIPT_DEBUG = False half_duplex = False dbg_print("=================== FIRMWARE UPLOAD ===================\n") dbg_print(" Bin file '%s'\n" % filename) dbg_print(" Port %s @ %s\n" % (port, baudrate)) logging.basicConfig(level=logging.ERROR) if ghst: BootloaderInitSeq1 = bootloader.get_init_seq('GHST', key) half_duplex = True dbg_print(" Using GHST (half duplex)!\n") else: BootloaderInitSeq1 = bootloader.get_init_seq('CRSF', key) dbg_print(" Using CRSF (full duplex)!\n") BootloaderInitSeq2 = bytes([0x62,0x62,0x62,0x62,0x62,0x62]) if not os.path.exists(filename): msg = "[FAILED] file '%s' does not exist\n" % filename dbg_print(msg) return ElrsUploadResult.ErrorGeneral s = serial.Serial(port=port, baudrate=baudrate, bytesize=8, parity='N', stopbits=1, timeout=5, inter_byte_timeout=None, xonxoff=0, rtscts=0) rl = SerialHelper.SerialHelper(s, 2., ["CCC"], half_duplex) # Check if bootloader *and* passthrough is already active gotBootloader = 'CCC' in rl.read_line() if not gotBootloader: s.close() # Init Betaflight passthrough try: BFinitPassthrough.bf_passthrough_init(port, baudrate, half_duplex) except BFinitPassthrough.PassthroughEnabled as info: dbg_print(" Warning: '%s'\n" % info) except BFinitPassthrough.PassthroughFailed as failed: raise # Prepare to upload s = serial.Serial(port=port, baudrate=baudrate, bytesize=8, parity='N', stopbits=1, timeout=1, xonxoff=0, rtscts=0) rl.set_serial(s) rl.clear() # Check again if we're in the bootloader now that passthrough is setup; # Note: This is for button-method flashing gotBootloader = 'CCC' in rl.read_line() # Init bootloader if not gotBootloader: # legacy bootloader requires a 500ms delay delay_seq2 = .5 rl.set_timeout(2.) rl.set_delimiters(["\n", "CCC"]) currAttempt = 0 dbg_print("\nAttempting to reboot into bootloader...\n") while gotBootloader == False: currAttempt += 1 if 10 < currAttempt: msg = "[FAILED] to get to BL in reasonable time\n" dbg_print(msg) return ElrsUploadResult.ErrorGeneral if 5 < currAttempt: # Enable debug logs after 5 retries SCRIPT_DEBUG = True dbg_print("[%1u] retry...\n" % currAttempt) # clear RX buffer before continuing rl.clear() # request reboot rl.write(BootloaderInitSeq1) start = time.time() while ((time.time() - start) < 2.): line = rl.read_line().strip() if not line: # timeout continue if SCRIPT_DEBUG and line: dbg_print(" **DBG : '%s'\n" % line) if "BL_TYPE" in line: bl_type = line[8:].strip() dbg_print(" Bootloader type found : '%s'\n" % bl_type) # Newer bootloaders do not require delay but keep # a 100ms just in case delay_seq2 = .1 continue versionMatch = re.search('=== (v.*) ===', line, re.IGNORECASE) if versionMatch: bl_version = versionMatch.group(1) dbg_print(" Bootloader version found : '%s'\n" % bl_version) elif "hold down button" in line: time.sleep(delay_seq2) rl.write(BootloaderInitSeq2) gotBootloader = True break elif "CCC" in line: # Button method has been used so we're not catching the header; # let's jump right to the sanity check if we're getting enough C's gotBootloader = True break elif "_RX_" in line: flash_target = re.sub("_VIA_.*", "", target.upper()) if line != flash_target and not ignore_incorrect_target: if query_yes_no("\n\n\nWrong target selected! your RX is '%s', trying to flash '%s', continue? Y/N\n" % (line, flash_target)): ignore_incorrect_target = True continue else: dbg_print("Wrong target selected your RX is '%s', trying to flash '%s'" % (line, flash_target)) return ElrsUploadResult.ErrorMismatch elif flash_target != "": dbg_print("Verified RX target '%s'" % flash_target) dbg_print(" Got into bootloader after: %u attempts\n" % currAttempt) # sanity check! Make sure the bootloader is started dbg_print("Wait sync...") rl.set_delimiters(["CCC"]) if "CCC" not in rl.read_line(15.): msg = "[FAILED] Unable to communicate with bootloader...\n" dbg_print(msg) return ElrsUploadResult.ErrorGeneral dbg_print(" sync OK\n") else: dbg_print("\nWe were already in bootloader\n") else: dbg_print("\nWe were already in bootloader\n") # change timeout to 5sec s.timeout = 5. s.write_timeout = .3 # open binary stream = open(filename, 'rb') filesize = os.stat(filename).st_size filechunks = filesize / 128 dbg_print("\nuploading %d bytes...\n" % filesize) def StatusCallback(total_packets, success_count, error_count): #sys.stdout.flush() if (total_packets % 10 == 0): dbg = str(round((total_packets / filechunks) * 100)) + "%" if (error_count > 0): dbg += ", err: " + str(error_count) dbg_print(dbg + "\n") def getc(size, timeout=3): return s.read(size) or None def putc(data, timeout=3): cnt = s.write(data) if half_duplex: s.flush() # Clean RX buffer in case of half duplex # All written data is read into RX buffer s.read(cnt) return cnt s.reset_input_buffer() modem = XMODEM(getc, putc, mode='xmodem') #modem.log.setLevel(logging.DEBUG) status = modem.send(stream, retry=10, callback=StatusCallback) s.close() stream.close() if (status): dbg_print("Success!!!!\n\n") return ElrsUploadResult.Success dbg_print("[FAILED] Upload failed!\n\n") return ElrsUploadResult.ErrorGeneral
def uart_upload(port, filename, baudrate, key=None, target=""): print_header("=================== FIRMWARE UPLOAD ===================") print_log(" Bin file '%s'" % filename) print_log(" Port %s @ %s" % (port, baudrate)) cmd_reboot_to_bootloader = bootloader.get_init_seq('CRSF', key) if not os.path.exists(filename): msg = "[FAILED] file '%s' does not exist" % filename raise SystemExit(msg) detected_baud = baudrate chip_type, esp = esp_read_chip_id(port, detected_baud) if not chip_type: # Init Betaflight passthrough try: detected_baud = BFinitPassthrough.bf_passthrough_init(port, None) if detected_baud is None: detected_baud = baudrate except BFinitPassthrough.PassthroughEnabled as info: print_warning(" Warning: '%s'" % info) except BFinitPassthrough.PassthroughFailed as failed: raise SystemExit(failed) # Reset into bootloader bootloader.reset_to_bootloader(port, detected_baud, cmd_reboot_to_bootloader, target) # send_training_to_esp_rom(port, detected_baud) chip_type, esp = esp_read_chip_id(port, detected_baud) if not esp: raise SystemExit("Cannot connect to ESP") # Prepare to upload print_header("======== UPLOADING ========") if esp: _binary = open(os.path.abspath(filename), 'rb') class TempArgs(): compress = None no_compress = True no_stub = False encrypt = False flash_size = "keep" flash_mode = "keep" flash_freq = "keep" addr_filename = [] erase_all = False verify = False args = TempArgs() args.addr_filename.append((0, _binary)) try: esptool.write_flash(esp, args) # flash_finish will trigger a soft reset esp.soft_reset(False) finally: _binary.close() esp._port.close() return # -------------------- chip_type = ["auto", "esp8266"][chip_type.startswith("ESP82")] args = [ "-b", str(detected_baud), "-p", port, "-c", chip_type, "--before", "no_reset", "--after", "soft_reset", "write_flash", "0x0", os.path.abspath(filename) ] cmd = " ".join(args) print_log(" Using command: '%s'\n" % cmd) esptool.main(args)
"--half-duplex", action="store_true", dest="half_duplex", help="Use half duplex mode") parser.add_argument( "-t", "--type", type=str, default="ESP82", help= "Defines flash target type which is sent to target in reboot command") args = parser.parse_args() if (args.port == None): args.port = serials_find.get_serial_port() try: bf_passthrough_init(args.port, args.baud) except PassthroughEnabled as err: print_warning(str(err)) if args.reset_to_bl: boot_cmd = bootloader.get_init_seq(['CRSF', 'GHST'][args.half_duplex], args.type) try: bootloader.reset_to_bootloader(args.port, args.baud, boot_cmd, args.target) except bootloader.WrongTargetSelected as err: print_error(str(err)) exit(-1)
def uart_upload(port, filename, baudrate, ghst=False, key=None, target=""): half_duplex = ghst ignore_incorrect_target = False set_debug(SCRIPT_DEBUG) print_header("=================== FIRMWARE UPLOAD ===================") print_log(" Bin file '%s'" % filename) print_log(" Port %s @ %s" % (port, baudrate)) # Needed for XMODEM logging logging.basicConfig(level=logging.ERROR) cmd_reboot_to_bootloader = bootloader.get_init_seq(['CRSF', 'GHST'][ghst], key) cmd_trigger_upload = bootloader.get_bootloader_trigger_seq() if not os.path.exists(filename): msg = "[FAILED] file '%s' does not exist" % filename # print_error(msg) raise SystemExit(msg) detected_baud = baudrate # Init Betaflight passthrough try: detected_baud = BFinitPassthrough.bf_passthrough_init( port, None, half_duplex) if detected_baud is None: detected_baud = baudrate except BFinitPassthrough.PassthroughEnabled as info: print_warning(" Warning: '%s'" % info) except BFinitPassthrough.PassthroughFailed as failed: raise SystemExit(failed) # Prepare to upload s = serial.Serial(port=port, baudrate=detected_baud, bytesize=8, parity='N', stopbits=1, timeout=1, xonxoff=0, rtscts=0) rl = SerialHelper.SerialHelper(s, 2., ["CCC"], half_duplex) rl.clear() gotBootloader = False if bootloader.BAUDRATE_STM_BOOTLOADER == detected_baud: # Check again if we're in the bootloader now that passthrough is setup; # Note: This is for button-method flashing gotBootloader = 'CCC' in rl.read_line() # Init bootloader if not gotBootloader: print_header("======== RESET TO BOOTLOADER ========") # legacy bootloader requires a 500ms delay delay_seq2 = .5 currAttempt = 0 # rl.set_timeout(2.) rl.set_delimiters(["\n", "CCC"]) while gotBootloader == False: currAttempt += 1 if 10 < currAttempt: msg = "[FAILED] to get to BL in reasonable time" #print_error(msg) raise SystemExit(msg) if 5 <= currAttempt: # Enable debug logs after 5 retries set_debug(True) print_log(" [%1u] retry... (baud: %s)" % ( currAttempt, s.baudrate, )) # Change baudrate to match ELRS firmware s.baudrate = detected_baud # clear RX buffer before continuing rl.clear() # request reboot rl.write(cmd_reboot_to_bootloader) if 2 == currAttempt: # BL not detected, change back to given baudrate detected_baud = baudrate elif 4 == currAttempt: # BL not detected, change back to default detected_baud = bootloader.BAUDRATE_STM_BOOTLOADER start = time.time() while ((time.time() - start) < 2.): line = rl.read_line().strip() if not line: # timeout continue print_debug(" **DBG : '%s'" % line) if "BL_TYPE" in line: bl_type = line[8:].strip() print_log(" Bootloader type found : '%s'" % bl_type) # Newer bootloaders do not require delay but keep # a 100ms just in case delay_seq2 = .1 continue versionMatch = re.search('=== (v.*) ===', line, re.IGNORECASE) if versionMatch: bl_version = versionMatch.group(1) print_log(" Bootloader version found : '%s'" % bl_version) elif "hold down button" in line: time.sleep(delay_seq2) rl.write(cmd_trigger_upload) gotBootloader = True break elif "CCC" in line: # Button method has been used so we're not catching the header; # let's jump right to the sanity check if we're getting enough C's gotBootloader = True break elif line.endswith("_RX") and not ignore_incorrect_target: bootloader.validate_reported_rx_type(line, target) ignore_incorrect_target = True # change baurate to communicate with the bootloader s.baudrate = bootloader.BAUDRATE_STM_BOOTLOADER print_log(" Got into bootloader after: %u attempts" % currAttempt) # sanity check! Make sure the bootloader is started print_log(" Wait sync... ", nl=False) rl.set_delimiters(["CCC"]) if "CCC" not in rl.read_line(15.): print_error("FAILED!") msg = "[FAILED] Unable to communicate with bootloader..." raise SystemExit(msg) print_log("OK") print_header("======== UPLOADING ========") # change timeout to 5sec s.timeout = 5. s.write_timeout = .3 # open binary stream = open(filename, 'rb') filesize = os.stat(filename).st_size filechunks = filesize / 128 print_log(" uploading %d bytes..." % filesize) def StatusCallback(total_packets, success_count, error_count): #sys.stdout.flush() if (total_packets % 10 == 0) or filechunks <= total_packets: dbg = " " + str(round((total_packets / filechunks) * 100)) + "%" if (error_count > 0): dbg += ", err: " + str(error_count) print_log(dbg) def getc(size, timeout=3): return s.read(size) or None def putc(data, timeout=3): cnt = s.write(data) if half_duplex: s.flush() # Clean RX buffer in case of half duplex # All written data is read into RX buffer s.read(cnt) return cnt s.reset_input_buffer() modem = XMODEM(getc, putc, mode='xmodem') #modem.log.setLevel(logging.DEBUG) status = modem.send(stream, retry=10, callback=StatusCallback) s.close() stream.close() if (status): print_info(" Success!!!!\n") else: #print_error("[FAILED] Upload failed!") raise SystemExit('Failed to Upload')