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()
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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()
Ejemplo n.º 4
0
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)
Ejemplo n.º 6
0
                        "--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')