예제 #1
0
def load_bitfile(bitfile: Path, ltxfile: Path, fu: FileSystemUtils):
    if shutil.which("vivado") is None:
        fatal_error("vivado not in $PATH, cannot continue")
    if bitfile is None or not bitfile.exists():
        fatal_error("Missing bitfile:", bitfile)
    if ltxfile is None or not ltxfile.exists():
        fatal_error("Missing ltx file:", ltxfile)
    with tempfile.NamedTemporaryFile() as t:
        t.write(VIVADO_SCRIPT)
        t.flush()
        args = [
            "vivado", "-nojournal", "-notrace", "-nolog", "-source", t.name,
            "-mode", "batch", "-tclargs",
            str(bitfile),
            str(ltxfile)
        ]
        print_command(args, config=get_global_config())
        if get_global_config().pretend:
            vivado = PretendSpawn(args[0], args[1:])
        else:
            vivado = pexpect.spawn(args[0],
                                   args[1:],
                                   logfile=sys.stdout,
                                   encoding="utf-8")
        vivado_exit_str = "Exiting Vivado at"
        if vivado.expect_exact(["****** Vivado", vivado_exit_str]) != 0:
            failure("Vivado failed to start", exit=True)
        success("Vivado started")
        if vivado.expect_exact(["Programming...", vivado_exit_str]) != 0:
            failure("Vivado failed to start programming", exit=True)
        success("Vivado started programming FPGA")
        # 5 minutes should be enough time to programt the FPGA
        if vivado.expect_exact(["Done!", vivado_exit_str],
                               timeout=5 * 60) != 0:
            failure("Vivado failed to program FPGA", exit=True)
        success("Vivado finished programming FPGA")
        vivado.expect_exact([vivado_exit_str])
        vivado.wait()
        fu.delete_file(Path("webtalk.log"), print_verbose_only=True)
        fu.delete_file(Path("webtalk.jou"), print_verbose_only=True)
        if not get_global_config().pretend:
            # wait for 3 seconds to avoid 'Error: libusb_claim_interface() failed with LIBUSB_ERROR_BUSY'
            time.sleep(3)
예제 #2
0
def load_and_start_kernel(*,
                          gdb_cmd: Path,
                          openocd_cmd: Path,
                          bios_image: Path,
                          kernel_image: Path = None,
                          kernel_debug_file: Path = None,
                          tty_info: ListPortInfo,
                          num_cores: int) -> FpgaConnection:
    # Open the serial connection first to check that it's available:
    serial_conn = get_console(tty_info)
    success("Connected to TTY")
    if bios_image is None or not bios_image.exists():
        failure("Missing bios image: ", bios_image)
    # First start openocd
    gdb_start_time = datetime.datetime.utcnow()
    openocd, openocd_gdb_port = start_openocd(openocd_cmd, num_cores)
    # openocd is running, now start GDB
    args = [
        str(Path(bios_image).absolute()), "-ex",
        "target extended-remote :" + str(openocd_gdb_port)
    ]
    args += ["-ex", "set confirm off"]  # avoid interactive prompts
    args += ["-ex",
             "set pagination off"]  # avoid paginating output, requiring input
    args += ["-ex", "set style enabled off"
             ]  # disable colours since they break the matcher strings
    args += ["-ex", "monitor reset init"]  # reset and go back to boot room
    args += ["-ex", "si 5"
             ]  # we need to run the first few instructions to get a valid DTB
    args += ["-ex", "set disassemble-next-line on"]
    # Load the kernel image first since load changes the next PC to the entry point
    if kernel_image is not None:
        kernel_image = kernel_image.absolute()
        if kernel_debug_file is None:
            # If there is a .full image use that to get debug symbols:
            full_file = kernel_image.with_name(kernel_image.name + ".full")
            if full_file.exists():
                kernel_debug_file = full_file
            else:
                # Fall back to the kernel image without debug info.
                kernel_debug_file = kernel_image
        args += [
            "-ex",
            "symbol-file " + shlex.quote(str(kernel_debug_file.absolute()))
        ]
        args += ["-ex", "load " + shlex.quote(str(kernel_image.absolute()))]
    args += ["-ex", "load " + shlex.quote(str(Path(bios_image).absolute()))]
    if num_cores > 1:
        args += ["-ex", "set $entry_point = $pc"
                 ]  # Record the entry point to the bios
        for core in range(1, num_cores):
            args += ["-ex", "thread {:d}".format(core + 1)
                     ]  # switch to thread (core + 1) (GDB counts from 1)
            args += ["-ex", "si 5"]  # execute bootrom on every other core
            args += ["-ex", "set $pc=$entry_point"
                     ]  # set every other core to the start of the bios
        args += ["-ex", "thread 1"]  # switch back to core 0
    print_command(str(gdb_cmd), *args, config=get_global_config())
    if get_global_config().pretend:
        gdb = PretendSpawn(str(gdb_cmd), args, timeout=60)
    else:
        gdb = pexpect.spawn(str(gdb_cmd),
                            args,
                            timeout=60,
                            logfile=sys.stdout,
                            encoding="utf-8")
    gdb.expect_exact(["Reading symbols from"])
    # openOCD should acknowledge the GDB connection:
    openocd.expect_exact([
        "Info : accepting 'gdb' connection on tcp/{}".format(openocd_gdb_port)
    ])
    success("openocd accepted GDB connection")
    gdb.expect_exact(["Remote debugging using :" + str(openocd_gdb_port)])
    success("GDB connected to openocd")
    # XXX: doesn't match with recent GDB:  gdb.expect_exact(["0x0000000070000000 in ??"])
    gdb.expect_exact(["0x0000000070000000"])
    success("PC set to bootrom")
    # XXX: doesn't match with recent GDB: gdb.expect_exact(["0x0000000044000000 in ??"])
    gdb.expect_exact(["0x0000000044000000"])
    success("Done executing bootrom")
    if kernel_image is not None:
        gdb.expect_exact(["Loading section .text"])
        load_start_time = datetime.datetime.utcnow()
        success("Started loading kernel image (this may take a long time)")
        gdb.expect_exact(["Transfer rate:"], timeout=120 *
                         60)  # XXX: is 2 hours a sensible timeout?
        load_end_time = datetime.datetime.utcnow()
        success("Finished loading kernel image in ",
                load_end_time - load_start_time)
    # Now load the bootloader
    gdb.expect_exact(["Loading section .text"])
    load_start_time = datetime.datetime.utcnow()
    success("Started loading bootloader image")
    gdb.expect_exact(["Transfer rate:"],
                     timeout=10 * 60)  # XXX: is 10 minutes a sensible timeout?
    load_end_time = datetime.datetime.utcnow()
    success("Finished loading bootloader image in ",
            load_end_time - load_start_time)
    gdb_finish_time = load_end_time
    if num_cores > 1:
        for core in range(1, num_cores):
            gdb.expect_exact(["0x0000000044000000"])
        success("Done executing bootrom on all other cores")
    gdb.sendline("continue")
    success("Starting CheriBSD after ",
            datetime.datetime.utcnow() - gdb_start_time)
    i = serial_conn.cheribsd.expect_exact(
        ["bbl loader", "---<<BOOT>>---", pexpect.TIMEOUT], timeout=30)
    if i == 0:
        success("bbl loader started")
    elif i == 1:
        success("FreeBSD boot started")
    else:
        failure("Did not get expected boot output", exit=True)
    # TODO: network_iface="xae0", but DHCP doesn't work
    boot_and_login(serial_conn.cheribsd,
                   starttime=gdb_finish_time,
                   network_iface=None)
    return FpgaConnection(gdb, openocd, serial_conn)