artiq/artiq/frontend/artiq_flash.py

147 lines
5.1 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
2016-01-05 07:50:59 +08:00
# Copyright (C) 2015 Robert Jordens <jordens@gmail.com>
import argparse
import os
import subprocess
import tempfile
import shutil
2016-01-05 07:50:59 +08:00
from artiq import __artiq_dir__ as artiq_dir
2016-01-05 07:50:59 +08:00
from artiq.frontend.bit2bin import bit2bin
def scripts_path():
2017-01-27 04:52:59 +08:00
p = ["share", "openocd", "scripts"]
if os.name == "nt":
2017-01-27 04:52:59 +08:00
p.insert(0, "Library")
p = os.path.abspath(os.path.join(
os.path.dirname(shutil.which("openocd")),
2017-01-27 04:52:59 +08:00
"..", *p))
return p
2016-07-25 10:05:10 +08:00
2016-01-19 12:41:42 +08:00
def get_argparser():
2016-01-05 07:50:59 +08:00
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description="ARTIQ flashing/deployment tool",
epilog="""\
Valid actions:
2016-03-01 03:45:41 +08:00
* proxy: load the flash proxy gateware bitstream
* gateware: write gateware bitstream to flash
2016-01-05 07:50:59 +08:00
* bios: write bios to flash
* runtime: write runtime to flash
* storage: write storage image to flash
2016-03-01 03:45:41 +08:00
* load: load gateware bitstream into device (volatile but fast)
* start: trigger the target to (re)load its gateware bitstream from flash
2016-01-05 07:50:59 +08:00
Prerequisites:
* Connect the board through its/a JTAG adapter.
* Have OpenOCD installed and in your $PATH.
* Have access to the JTAG adapter's devices. Udev rules from OpenOCD:
'sudo cp openocd/contrib/99-openocd.rules /etc/udev/rules.d'
and replug the device. Ensure you are member of the
plugdev group: 'sudo adduser $USER plugdev' and re-login.
""")
parser.add_argument("-t", "--target", default="kc705",
help="target board, default: %(default)s")
parser.add_argument("-m", "--adapter", default="nist_clock",
2016-01-05 07:50:59 +08:00
help="target adapter, default: %(default)s")
parser.add_argument("--target-file", default=None,
help="use alternative OpenOCD target file")
2016-01-05 07:50:59 +08:00
parser.add_argument("-f", "--storage", help="write file to storage area")
parser.add_argument("-d", "--dir", help="look for files in this directory")
parser.add_argument("action", metavar="ACTION", nargs="*",
2016-03-01 03:45:41 +08:00
default="proxy gateware bios runtime start".split(),
2016-01-05 07:50:59 +08:00
help="actions to perform, default: %(default)s")
2016-01-19 12:41:42 +08:00
return parser
def main():
parser = get_argparser()
2016-01-05 07:50:59 +08:00
opts = parser.parse_args()
config = {
"kc705": {
"chip": "xc7k325t",
"start": "xc7_program xc7.tap",
2016-03-01 03:45:41 +08:00
"gateware": 0x000000,
2016-01-05 07:50:59 +08:00
"bios": 0xaf0000,
"runtime": 0xb00000,
2016-01-31 05:50:15 +08:00
"storage": 0xb80000,
2016-01-05 07:50:59 +08:00
},
}[opts.target]
if opts.dir is None:
opts.dir = os.path.join(artiq_dir, "binaries",
2016-01-05 07:50:59 +08:00
"{}-{}".format(opts.target, opts.adapter))
if not os.path.exists(opts.dir) and opts.action != ["start"]:
raise SystemExit("Binaries directory '{}' does not exist"
.format(opts.dir))
2016-01-05 07:50:59 +08:00
conv = False
prog = []
prog.append("init")
for action in opts.action:
2016-01-05 07:50:59 +08:00
if action == "proxy":
proxy_base = "bscan_spi_{}.bit".format(config["chip"])
proxy = None
for p in [opts.dir, os.path.expanduser("~/.migen"),
2016-03-01 03:45:41 +08:00
"/usr/local/share/migen", "/usr/share/migen"]:
2016-01-05 07:50:59 +08:00
proxy_ = os.path.join(p, proxy_base)
if os.access(proxy_, os.R_OK):
2016-05-17 05:15:12 +08:00
proxy = "jtagspi_init 0 {{{}}}".format(proxy_)
2016-01-05 07:50:59 +08:00
break
if not proxy:
raise SystemExit(
2016-03-01 03:45:41 +08:00
"proxy gateware bitstream {} not found".format(proxy_base))
2016-01-05 07:50:59 +08:00
prog.append(proxy)
2016-03-01 03:45:41 +08:00
elif action == "gateware":
2016-01-05 07:50:59 +08:00
bin = os.path.join(opts.dir, "top.bin")
if not os.access(bin, os.R_OK):
2016-05-17 03:30:16 +08:00
bin_handle, bin = tempfile.mkstemp()
2016-01-05 07:50:59 +08:00
bit = os.path.join(opts.dir, "top.bit")
conv = True
2016-05-17 05:15:12 +08:00
prog.append("jtagspi_program {{{}}} 0x{:x}".format(
2016-03-01 03:45:41 +08:00
bin, config["gateware"]))
2016-01-05 07:50:59 +08:00
elif action == "bios":
2016-05-17 05:15:12 +08:00
prog.append("jtagspi_program {{{}}} 0x{:x}".format(
2016-01-05 07:50:59 +08:00
os.path.join(opts.dir, "bios.bin"), config["bios"]))
elif action == "runtime":
2016-05-17 05:15:12 +08:00
prog.append("jtagspi_program {{{}}} 0x{:x}".format(
2016-01-05 07:50:59 +08:00
os.path.join(opts.dir, "runtime.fbi"), config["runtime"]))
elif action == "storage":
2016-05-17 05:15:12 +08:00
prog.append("jtagspi_program {{{}}} 0x{:x}".format(
2016-01-05 07:50:59 +08:00
opts.storage, config["storage"]))
elif action == "load":
2016-05-17 05:15:12 +08:00
prog.append("pld load 0 {{{}}}".format(
2016-01-05 07:50:59 +08:00
os.path.join(opts.dir, "top.bit")))
elif action == "start":
prog.append(config["start"])
else:
raise ValueError("invalid action", action)
prog.append("exit")
try:
if conv:
2016-05-17 04:02:11 +08:00
bit2bin(bit, bin_handle)
if opts.target_file is None:
target_file = os.path.join("board", opts.target + ".cfg")
else:
target_file = opts.target_file
2016-01-05 07:50:59 +08:00
subprocess.check_call([
"openocd",
"-s", scripts_path(),
"-f", target_file,
2016-01-05 07:50:59 +08:00
"-c", "; ".join(prog),
])
finally:
if conv:
os.unlink(bin)
if __name__ == "__main__":
main()