Ejemplo n.º 1
0
def get_port_by_uuid(device, uuid):
    ports = get_ports(device) + get_ports("1209:2100")
    for port in ports:
        try:
            with port:
                p = TinyProg(port)
                if p.meta.uuid().startswith(uuid):
                    return port

        except Exception:
            pass
    return None
Ejemplo n.º 2
0
def check_for_wrong_tinyfpga_bx_vidpid():
    """
    Some of the TinyFPGA BX boards have the wrong USB VID:PID.  This function
    looks for such boards.
    """
    boards_needing_update = []

    ports = get_ports("1209:2100")
    for port in ports:
        with port:
            p = TinyProg(port)
            m = p.meta.root
            if m[u"boardmeta"][u"name"] == u"TinyFPGA BX":
                boards_needing_update.append(port)

    return boards_needing_update
Ejemplo n.º 3
0
def main():
    import sys
    import argparse
    import serial
    from serial.tools.list_ports import comports
    from tinyprog import TinyProg

    parser = argparse.ArgumentParser()

    parser.add_argument("-l",
                        "--list",
                        action="store_true",
                        help="list connected and active FPGA boards")
    parser.add_argument("-p",
                        "--program",
                        type=str,
                        help="program FPGA board with the given bitstream")
    parser.add_argument("-u",
                        "--program-userdata",
                        type=str,
                        help="program FPGA board with the given user data")
    parser.add_argument("-b",
                        "--boot",
                        action="store_true",
                        help="command the FPGA board to exit the "
                        "bootloader and load the user configuration")
    parser.add_argument("-c", "--com", type=str, help="serial port name")
    parser.add_argument("-i", "--id", type=str, help="FPGA board ID")
    parser.add_argument(
        "-d",
        "--device",
        type=str,
        default="1209:2100",
        help="device id (vendor:product); default is (1209:2100)")
    parser.add_argument("-a",
                        "--addr",
                        type=int,
                        help="force the address to write the bitstream to")
    parser.add_argument(
        "-m",
        "--meta",
        action="store_true",
        help="dump out the metadata for all connected boards in JSON")

    args = parser.parse_args()

    device = args.device.lower().replace(':', '')
    if len(device) != 8 or not all(c in '0123456789abcdef' for c in device):
        print "    Invalid device id, use format vendor:product"
        sys.exit(1)
    device = '{}:{}'.format(device[:4], device[4:])
    active_boards = [p[0] for p in comports() if device in p[2]]

    if args.meta:
        meta = []
        for port in active_boards:
            with serial.Serial(port, timeout=1.0, writeTimeout=1.0) as ser:
                p = TinyProg(ser)
                m = p.meta.root
                m["port"] = port
                meta.append(m)
        import json
        print json.dumps(meta, indent=2)
        sys.exit(0)

    print ""
    print "    TinyProg CLI"
    print "    ------------"

    print "    Using device id {}".format(device)

    # find port to use
    active_port = None
    if args.com is not None:
        active_port = args.com
    elif args.id is not None:
        for port in active_boards:
            with serial.Serial(port, timeout=1.0, writeTimeout=1.0) as ser:
                p = TinyProg(ser)
                if p.meta.uuid().startswith(args.id):
                    active_port = port
                    break

    elif not active_boards:
        print "    No port was specified and no active bootloaders found."
        print "    Activate bootloader by pressing the reset button."
        sys.exit(1)
    elif len(active_boards) == 1:
        print "    Only one board with active bootloader, using it."
        active_port = active_boards[0]
    else:
        print "    Please choose a board with the -c or -i option."

    # list boards
    if args.list or active_port is None:
        print "    Boards with active bootloaders:"
        for port in active_boards:
            with serial.Serial(port, timeout=1.0, writeTimeout=1.0) as ser:
                p = TinyProg(ser)
                m = p.meta.root
                print ""
                print "        %s: %s %s" % (port, m[u"boardmeta"][u"name"],
                                             m[u"boardmeta"][u"hver"])
                print "            UUID: %s" % m[u"boardmeta"][u"uuid"]
                print "            FPGA: %s" % m[u"boardmeta"][u"fpga"]

        if len(active_boards) == 0:
            print "        No active bootloaders found.  Check USB connections"
            print "        and press reset button to activate bootloader."

    # program the flash memory
    elif args.program is not None:
        print "    Programming " + active_port + " with " + args.program

        def progress(info):
            if isinstance(info, str):
                print "    " + info

        with serial.Serial(active_port, timeout=1.0, writeTimeout=1.0) as ser:
            fpga = TinyProg(ser, progress)
            bitstream = fpga.slurp(args.program)
            addr = fpga.meta.userimage_addr_range()[0]
            if args.addr is not None:
                addr = args.addr
            if addr < 0:
                print "    Negative write addr: {}".format(addr)
                sys.exit(1)
            if not fpga.is_bootloader_active():
                print "    Bootloader not active"
                sys.exit(1)
            print "    Programming at addr {:06x}".format(addr)
            if fpga.program_bitstream(addr, bitstream):
                sys.exit(0)
            else:
                sys.exit(1)

    # boot the FPGA
    if args.boot:
        print "    Booting " + active_port
        with serial.Serial(active_port, timeout=1.0, writeTimeout=1.0) as ser:
            fpga = TinyProg(ser)
            fpga.boot()
Ejemplo n.º 4
0
def main():
    def parse_int(str_value):
        str_value = str_value.strip().lower()
        if str_value.startswith("0x"):
            return int(str_value[2:], 16)
        else:
            return int(str_value)

    parser = argparse.ArgumentParser()
    parser.add_argument("--version",
                        action="store_true",
                        help="Print the tinyprog version.")
    parser.add_argument("-l",
                        "--list",
                        action="store_true",
                        help="list connected and active FPGA boards")
    parser.add_argument(
        "-p",
        "--program",
        type=str,
        help="program FPGA board with the given user bitstream")
    parser.add_argument("-u",
                        "--program-userdata",
                        type=str,
                        help="program FPGA board with the given user data")
    parser.add_argument(
        "--program-image",
        type=str,
        help="program FPGA board with a combined user bitstream and data")
    parser.add_argument("-b",
                        "--boot",
                        action="store_true",
                        help="command the FPGA board to exit the "
                        "bootloader and load the user configuration")
    parser.add_argument("-c", "--com", type=str, help="serial port name")
    parser.add_argument("-i", "--id", type=str, help="FPGA board ID")
    parser.add_argument(
        "-d",
        "--device",
        type=str,
        default="1d50:6130",
        help="device id (vendor:product); default is (1d50:6130)")
    parser.add_argument("-a",
                        "--addr",
                        type=str,
                        help="force the address to write the bitstream to")
    parser.add_argument(
        "-m",
        "--meta",
        action="store_true",
        help="dump out the metadata for all connected boards in JSON")
    parser.add_argument(
        "--security",
        type=str,
        help="update the security page in the flash at address addr")
    parser.add_argument(
        "--update-bootloader",
        action="store_true",
        help="check for new bootloader and update eligible connected boards")
    parser.add_argument("--libusb",
                        action="store_true",
                        help="""\
try using libusb to connect to boards without a serial driver attached""")
    parser.add_argument("--pyserial",
                        action="store_true",
                        help="use pyserial to connect to boards")

    args = parser.parse_args()
    if args.version:
        print("tinyprog %s (%s)" %
              (tinyprog.__version__, tinyprog.__full_version__))
        sys.exit(0)

    device = args.device.lower().replace(':', '')
    if len(device) != 8 or not all(c in '0123456789abcdef' for c in device):
        print("    Invalid device id, use format vendor:product")
        sys.exit(1)
    device = '{}:{}'.format(device[:4], device[4:])

    tinyprog.use_libusb = args.libusb
    tinyprog.use_pyserial = args.pyserial

    try:
        active_boards = get_ports(device) + get_ports("1209:2100")

        if args.meta:
            meta = []
            for port in active_boards:
                with port:
                    p = TinyProg(port)
                    m = p.meta.root
                    m["port"] = str(port)
                    meta.append(m)
            print(json.dumps(meta, indent=2))
            sys.exit(0)

        print("")
        print("    TinyProg CLI")
        print("    ------------")

        print("    Using device id {}".format(device))

        # find port to use
        active_port = None
        if args.com is not None:
            active_port = tinyprog.SerialPort(args.com)

        elif args.id is not None:
            active_port = get_port_by_uuid(device, args.id)

        elif not active_boards:
            print("""\
    No port was specified and no active bootloaders found.
    Activate bootloader by pressing the reset button.
""")
            sys.exit(1)

        elif len(active_boards) == 1:
            print("""\
    Only one board with active bootloader, using it.
""")
            active_port = active_boards[0]

        else:
            print("""\
    Please choose a board with the -c or -i option.  Using first board in list.
""")
            active_port = active_boards[0]

        # list boards
        if args.list or active_port is None:
            print("    Boards with active bootloaders:")
            for port in active_boards:
                with port:
                    p = TinyProg(port)
                    m = p.meta.root
                    print_board(port, m)

            if len(active_boards) == 0:
                print("""\
        No active bootloaders found.  Check USB connections
        and press reset button to activate bootloader.""")

        if args.update_bootloader:
            boards_needing_update = (check_for_wrong_tinyfpga_bx_vidpid() +
                                     check_for_new_bootloader())

            if len(boards_needing_update) == 0:
                print("""\
        All connected and active boards are up to date!""")
            else:
                for port in boards_needing_update:
                    perform_bootloader_update(port)

        # program the flash memory
        if (args.program
                is not None) or (args.program_userdata is not None) or (
                    args.security is not None) or (args.program_image
                                                   is not None):
            boot_fpga = False

            def progress(info):
                if isinstance(info, str):
                    print("    " + str(info))

            with active_port:
                fpga = TinyProg(active_port, progress)
                force = False

                if args.program is not None:
                    print("    Programming %s with %s" %
                          (active_port, args.program))

                    bitstream = fpga.slurp(args.program)

                    if args.addr is not None:
                        addr = parse_int(args.addr)
                        force = True
                    else:
                        addr = fpga.meta.userimage_addr_range()[0]

                    if addr < 0:
                        print("    Negative write addr: {}".format(addr))
                        sys.exit(1)
                    if not fpga.is_bootloader_active():
                        print("    Bootloader not active")
                        sys.exit(1)

                    if force or check_if_overwrite_bootloader(
                            addr, len(bitstream),
                            fpga.meta.userimage_addr_range()):
                        boot_fpga = True
                        print("    Programming at addr {:06x}".format(addr))
                        if not fpga.program_bitstream(addr, bitstream):
                            sys.exit(1)

                # program user flash area
                if args.program_userdata is not None:
                    print("    Programming %s with %s" %
                          (active_port, args.program_userdata))

                    bitstream = fpga.slurp(args.program_userdata)

                    if args.addr is not None:
                        addr = parse_int(args.addr)
                        force = True
                    else:
                        addr = fpga.meta.userdata_addr_range()[0]

                    if addr < 0:
                        print("    Negative write addr: {}".format(addr))
                        sys.exit(1)
                    if not fpga.is_bootloader_active():
                        print("    Bootloader not active")
                        sys.exit(1)

                    if force or check_if_overwrite_bootloader(
                            addr, len(bitstream),
                            fpga.meta.userdata_addr_range()):
                        boot_fpga = True
                        print("    Programming at addr {:06x}".format(addr))
                        if not fpga.program_bitstream(addr, bitstream):
                            sys.exit(1)

                # program user image and data area
                if args.program_image is not None:
                    print("    Programming %s with %s" %
                          (active_port, args.program_image))

                    bitstream = fpga.slurp(args.program_image)

                    if args.addr is not None:
                        addr = parse_int(args.addr)
                        force = True
                    else:
                        addr = fpga.meta.userimage_addr_range()[0]

                    if addr < 0:
                        print("    Negative write addr: {}".format(addr))
                        sys.exit(1)
                    if not fpga.is_bootloader_active():
                        print("    Bootloader not active")
                        sys.exit(1)

                    if force or check_if_overwrite_bootloader(
                            addr, len(bitstream),
                        (fpga.meta.userimage_addr_range()[0],
                         fpga.meta.userdata_addr_range()[1])):
                        boot_fpga = True
                        print("    Programming at addr {:06x}".format(addr))
                        if not fpga.program_bitstream(addr, bitstream):
                            sys.exit(1)

                if args.security is not None:
                    print("    Programming %s security page with %s" %
                          (active_port, args.security))

                    data = open(args.security, 'rb').read()

                    if args.addr is not None:
                        addr = parse_int(args.addr)
                    else:
                        addr = 1

                    if addr < 0:
                        print("    Negative write addr: {}".format(addr))
                        sys.exit(1)
                    if not fpga.is_bootloader_active():
                        print("    Bootloader not active")
                        sys.exit(1)

                    if not fpga.program_security_page(addr, data):
                        sys.exit(1)

                if boot_fpga:
                    fpga.boot()
                    print("")
                    sys.exit(0)

        # boot the FPGA
        if args.boot:
            print("    Booting " + str(active_port))
            with active_port:
                fpga = TinyProg(active_port)
                fpga.boot()
    except PortError as e:
        print(str(e), file=sys.stderr)
        sys.exit(1)

    print("")
Ejemplo n.º 5
0
def perform_bootloader_update(port):
    uuid = None

    with port:
        p = TinyProg(port)
        m = p.meta.root

        uuid = m[u"boardmeta"][u"uuid"]

        # download bootloader update information
        bootloader_json_data = urlopen(m[u"bootmeta"][u"update"] +
                                       "/bootloader.json").read()
        if isinstance(bootloader_json_data, bytes):
            bootloader_json_data = bootloader_json_data.decode('utf-8')
        bootloader_update_info = json.loads(bootloader_json_data)

        # ask permission to update the board
        print("")
        print("    The following update:")
        print("")
        print("        New Version: %s" % bootloader_update_info[u"version"])
        print("        Notes: %s" % bootloader_update_info[u"notes"])
        print("")
        print("    is available for this board:")
        print_board(port, m)
        print("")

        if query_user("    Would you like to perform the update?"):
            ####################
            # STAGE ONE
            ####################
            print("    Fetching stage one...")
            bitstream = urlopen(
                bootloader_update_info[u"stage_one_url"]).read()

            print("    Programming stage one...")
            userimage_addr = p.meta.userimage_addr_range()[0]
            if p.program_bitstream(userimage_addr, bitstream):
                p.boot()
                print("    ...Success!")
            else:
                print("    ...Failure, try again!")
                return False
        else:
            print("    Update cancelled by user.")
            return False

    sys.stdout.write("    Waiting for stage one to reconnect...")
    sys.stdout.flush()

    new_port = None

    for x in range(20):
        time.sleep(1)
        sys.stdout.write(".")
        sys.stdout.flush()
        new_port = get_port_by_uuid("1d50:6130", uuid)
        if new_port is not None:
            print("connected!")
            break

    with new_port:
        p = TinyProg(new_port)

        ####################
        # STAGE TWO
        ####################
        print("    Fetching stage two...")
        bitstream = urlopen(bootloader_update_info[u"stage_two_url"]).read()

        print("    Programming stage two...")
        if p.program_bitstream(0, bitstream):
            p.boot()
            print("    ...Success!\n")
            return True
        else:
            print("    ...Failure, try again!")
            return False