forked from M-Labs/artiq
artiq_flash: Sayma support
This commit is contained in:
parent
bee4902323
commit
9f4c9fc14b
|
@ -1,5 +1,4 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# Copyright (C) 2015 Robert Jordens <jordens@gmail.com>
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
|
@ -11,16 +10,6 @@ from artiq import __artiq_dir__ as artiq_dir
|
||||||
from artiq.frontend.bit2bin import bit2bin
|
from artiq.frontend.bit2bin import bit2bin
|
||||||
|
|
||||||
|
|
||||||
def scripts_path():
|
|
||||||
p = ["share", "openocd", "scripts"]
|
|
||||||
if os.name == "nt":
|
|
||||||
p.insert(0, "Library")
|
|
||||||
p = os.path.abspath(os.path.join(
|
|
||||||
os.path.dirname(shutil.which("openocd")),
|
|
||||||
"..", *p))
|
|
||||||
return p
|
|
||||||
|
|
||||||
|
|
||||||
def get_argparser():
|
def get_argparser():
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
@ -47,8 +36,8 @@ Prerequisites:
|
||||||
""")
|
""")
|
||||||
parser.add_argument("-t", "--target", default="kc705",
|
parser.add_argument("-t", "--target", default="kc705",
|
||||||
help="target board, default: %(default)s")
|
help="target board, default: %(default)s")
|
||||||
parser.add_argument("-m", "--adapter", default="nist_clock",
|
parser.add_argument("-m", "--adapter", default=None,
|
||||||
help="target adapter, default: %(default)s")
|
help="target adapter, default: board-dependent")
|
||||||
parser.add_argument("--target-file", default=None,
|
parser.add_argument("--target-file", default=None,
|
||||||
help="use alternative OpenOCD target file")
|
help="use alternative OpenOCD target file")
|
||||||
parser.add_argument("-f", "--storage", help="write file to storage area")
|
parser.add_argument("-f", "--storage", help="write file to storage area")
|
||||||
|
@ -59,84 +48,210 @@ Prerequisites:
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
def scripts_path():
|
||||||
|
p = ["share", "openocd", "scripts"]
|
||||||
|
if os.name == "nt":
|
||||||
|
p.insert(0, "Library")
|
||||||
|
p = os.path.abspath(os.path.join(
|
||||||
|
os.path.dirname(shutil.which("openocd")),
|
||||||
|
"..", *p))
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
|
class Programmer:
|
||||||
|
def __init__(self, target_file):
|
||||||
|
self.target_file = target_file
|
||||||
|
self.prog = []
|
||||||
|
|
||||||
|
def load(self, bitfile):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def proxy(self, proxy_bitfile):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def flash_binary(self, flashno, address, filename):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def do(self):
|
||||||
|
self.prog.append("exit")
|
||||||
|
cmdline = [
|
||||||
|
"openocd",
|
||||||
|
"-s", scripts_path()
|
||||||
|
]
|
||||||
|
if self.target_file is not None:
|
||||||
|
cmdline += ["-f", target_file]
|
||||||
|
cmdline += ["-c", "; ".join(self.prog)]
|
||||||
|
subprocess.check_call(cmdline)
|
||||||
|
|
||||||
|
|
||||||
|
class ProgrammerJtagSpi7(Programmer):
|
||||||
|
def __init__(self, target_file):
|
||||||
|
Programmer.__init__(self, target_file)
|
||||||
|
self.prog.append("init")
|
||||||
|
|
||||||
|
def load(self, bitfile):
|
||||||
|
self.prog.append("pld load 0 " + bitfile)
|
||||||
|
|
||||||
|
def proxy(self, proxy_bitfile):
|
||||||
|
self.prog.append("jtagspi_init 0 {{{}}}".format(proxy_bitfile))
|
||||||
|
|
||||||
|
def flash_binary(self, flashno, address, filename):
|
||||||
|
# jtagspi_program supports only one flash
|
||||||
|
assert flashno == 0
|
||||||
|
self.prog.append("jtagspi_program {{{}}} 0x{:x}".format(
|
||||||
|
filename, address))
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self.prog.append("xc7_program xc7.tap")
|
||||||
|
|
||||||
|
|
||||||
|
class ProgrammerSayma(Programmer):
|
||||||
|
def __init__(self, target_file):
|
||||||
|
# TODO: use target_file
|
||||||
|
# TODO: support Sayma RTM
|
||||||
|
Programmer.__init__(self, None)
|
||||||
|
self.proxy_loaded = False
|
||||||
|
self.prog += [
|
||||||
|
"interface ftdi",
|
||||||
|
"ftdi_device_desc \"Quad RS232-HS\"",
|
||||||
|
"ftdi_vid_pid 0x0403 0x6011",
|
||||||
|
"ftdi_channel 0",
|
||||||
|
# EN_USB_JTAG on ADBUS7: out, high
|
||||||
|
# nTRST on ADBUS4: out, high, but R46 is DNP
|
||||||
|
"ftdi_layout_init 0x0098 0x008b",
|
||||||
|
"ftdi_tdo_sample_edge falling",
|
||||||
|
"ftdi_layout_signal nSRST -data 0x0080",
|
||||||
|
"reset_config srst_only srst_pulls_trst srst_gates_jtag srst_push_pull",
|
||||||
|
|
||||||
|
"adapter_khz 25000",
|
||||||
|
|
||||||
|
"transport select jtag",
|
||||||
|
|
||||||
|
"jtag newtap amc_xcu tap -irlen 6 -ignore-version -expected-id 0x03822093",
|
||||||
|
|
||||||
|
"pld device virtex2 amc_xcu.tap 1",
|
||||||
|
|
||||||
|
"set XILINX_USER1 0x02",
|
||||||
|
"set XILINX_USER2 0x03",
|
||||||
|
"set AMC_DR_LEN 2",
|
||||||
|
|
||||||
|
"target create amc_xcu.proxy testee -chain-position amc_xcu.tap",
|
||||||
|
"flash bank amc_xcu.spi0 jtagspi 0 0 0 0 amc_xcu.proxy $XILINX_USER1 $AMC_DR_LEN",
|
||||||
|
"flash bank amc_xcu.spi1 jtagspi 0 0 0 0 amc_xcu.proxy $XILINX_USER2 $AMC_DR_LEN",
|
||||||
|
|
||||||
|
"init"
|
||||||
|
]
|
||||||
|
|
||||||
|
def load(self, bitfile):
|
||||||
|
self.prog.append("pld load 0 " + bitfile)
|
||||||
|
|
||||||
|
def proxy(self, proxy_bitfile):
|
||||||
|
self.prog += [
|
||||||
|
"pld load 0 " + proxy_bitfile,
|
||||||
|
"reset halt"
|
||||||
|
]
|
||||||
|
|
||||||
|
def flash_binary(self, flashno, address, filename):
|
||||||
|
self.prog += [
|
||||||
|
"flash probe amc_xcu.spi{}".format(flashno),
|
||||||
|
"irscan amc_xcu.tap $XILINX_USER{}".format(flashno+1),
|
||||||
|
"flash write_bank {} {} 0x{:x}".format(flashno, filename, address)
|
||||||
|
]
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self.proxy_loaded = False
|
||||||
|
self.prog.append("xcu_program xcu.tap")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = get_argparser()
|
parser = get_argparser()
|
||||||
opts = parser.parse_args()
|
opts = parser.parse_args()
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
"kc705": {
|
"kc705": {
|
||||||
"chip": "xc7k325t",
|
"programmer_factory": ProgrammerJtagSpi7,
|
||||||
"start": "xc7_program xc7.tap",
|
"proxy_bitfile": "bscan_spi_xc7k325t.bit",
|
||||||
"gateware": 0x000000,
|
"adapters": ["nist_clock", "nist_qc2"],
|
||||||
"bios": 0xaf0000,
|
"gateware": (0, 0x000000),
|
||||||
"runtime": 0xb00000,
|
"bios": (0, 0xaf0000),
|
||||||
"storage": 0xb80000,
|
"runtime": (0, 0xb00000),
|
||||||
|
"storage": (0, 0xb80000),
|
||||||
|
},
|
||||||
|
"sayma": {
|
||||||
|
"programmer_factory": ProgrammerSayma,
|
||||||
|
"proxy_bitfile": "bscan_spi_xcku040_sayma.bit",
|
||||||
|
"adapters": [],
|
||||||
|
"gateware": (0, 0x000000),
|
||||||
|
"bios": (1, 0x010000),
|
||||||
|
"runtime": (1, 0x020000),
|
||||||
|
"storage": (1, 0x0a0000),
|
||||||
},
|
},
|
||||||
}[opts.target]
|
}[opts.target]
|
||||||
|
|
||||||
if opts.dir is None:
|
adapter = opts.adapter
|
||||||
opts.dir = os.path.join(artiq_dir, "binaries",
|
if adapter is not None and adapter not in config["adapters"]:
|
||||||
"{}-{}".format(opts.target, opts.adapter))
|
raise SystemExit("Invalid adapter for this board")
|
||||||
if not os.path.exists(opts.dir) and opts.action != ["start"]:
|
if adapter is None and config["adapters"]:
|
||||||
|
adapter = config["adapters"][0]
|
||||||
|
bin_dir = opts.dir
|
||||||
|
if bin_dir is None:
|
||||||
|
if adapter is None:
|
||||||
|
bin_dir = os.path.join(artiq_dir, "binaries",
|
||||||
|
"{}".format(opts.target))
|
||||||
|
else:
|
||||||
|
bin_dir = os.path.join(artiq_dir, "binaries",
|
||||||
|
"{}-{}".format(opts.target, adapter))
|
||||||
|
if not os.path.exists(bin_dir) and opts.action != ["start"]:
|
||||||
raise SystemExit("Binaries directory '{}' does not exist"
|
raise SystemExit("Binaries directory '{}' does not exist"
|
||||||
.format(opts.dir))
|
.format(bin_dir))
|
||||||
|
|
||||||
|
if opts.target_file is None:
|
||||||
|
target_file = os.path.join("board", opts.target + ".cfg")
|
||||||
|
else:
|
||||||
|
target_file = opts.target_file
|
||||||
|
programmer = config["programmer_factory"](target_file)
|
||||||
|
|
||||||
conv = False
|
conv = False
|
||||||
|
|
||||||
prog = []
|
|
||||||
prog.append("init")
|
|
||||||
for action in opts.action:
|
for action in opts.action:
|
||||||
if action == "proxy":
|
if action == "proxy":
|
||||||
proxy_base = "bscan_spi_{}.bit".format(config["chip"])
|
proxy_found = False
|
||||||
proxy = None
|
for p in [bin_dir, os.path.expanduser("~/.migen"),
|
||||||
for p in [opts.dir, os.path.expanduser("~/.migen"),
|
|
||||||
"/usr/local/share/migen", "/usr/share/migen"]:
|
"/usr/local/share/migen", "/usr/share/migen"]:
|
||||||
proxy_ = os.path.join(p, proxy_base)
|
proxy_bitfile = os.path.join(p, config["proxy_bitfile"])
|
||||||
if os.access(proxy_, os.R_OK):
|
if os.access(proxy_bitfile, os.R_OK):
|
||||||
proxy = "jtagspi_init 0 {{{}}}".format(proxy_)
|
programmer.proxy(proxy_bitfile)
|
||||||
|
proxy_found = True
|
||||||
break
|
break
|
||||||
if not proxy:
|
if not proxy_found:
|
||||||
raise SystemExit(
|
raise SystemExit(
|
||||||
"proxy gateware bitstream {} not found".format(proxy_base))
|
"proxy gateware bitstream {} not found".format(config["proxy_bitfile"]))
|
||||||
prog.append(proxy)
|
|
||||||
elif action == "gateware":
|
elif action == "gateware":
|
||||||
bin = os.path.join(opts.dir, "top.bin")
|
bin = os.path.join(bin_dir, "top.bin")
|
||||||
if not os.access(bin, os.R_OK):
|
if not os.access(bin, os.R_OK):
|
||||||
bin_handle, bin = tempfile.mkstemp()
|
bin_handle, bin = tempfile.mkstemp()
|
||||||
bit = os.path.join(opts.dir, "top.bit")
|
bit = os.path.join(bin_dir, "top.bit")
|
||||||
conv = True
|
conv = True
|
||||||
prog.append("jtagspi_program {{{}}} 0x{:x}".format(
|
programmer.flash_binary(*config["gateware"], bin)
|
||||||
bin, config["gateware"]))
|
|
||||||
elif action == "bios":
|
elif action == "bios":
|
||||||
prog.append("jtagspi_program {{{}}} 0x{:x}".format(
|
programmer.flash_binary(*config["bios"], os.path.join(bin_dir, "bios.bin"))
|
||||||
os.path.join(opts.dir, "bios.bin"), config["bios"]))
|
|
||||||
elif action == "runtime":
|
elif action == "runtime":
|
||||||
prog.append("jtagspi_program {{{}}} 0x{:x}".format(
|
programmer.flash_binary(*config["runtime"], os.path.join(bin_dir, "runtime.fbi"))
|
||||||
os.path.join(opts.dir, "runtime.fbi"), config["runtime"]))
|
|
||||||
elif action == "storage":
|
elif action == "storage":
|
||||||
prog.append("jtagspi_program {{{}}} 0x{:x}".format(
|
programmer.flash_binary(*config["storage"], opts.storage)
|
||||||
opts.storage, config["storage"]))
|
|
||||||
elif action == "load":
|
elif action == "load":
|
||||||
prog.append("pld load 0 {{{}}}".format(
|
programmer.load(os.path.join(bin_dir, "top.bit"))
|
||||||
os.path.join(opts.dir, "top.bit")))
|
|
||||||
elif action == "start":
|
elif action == "start":
|
||||||
prog.append(config["start"])
|
programmer.start()
|
||||||
else:
|
else:
|
||||||
raise ValueError("invalid action", action)
|
raise ValueError("invalid action", action)
|
||||||
prog.append("exit")
|
|
||||||
|
if conv:
|
||||||
|
bit2bin(bit, bin_handle)
|
||||||
try:
|
try:
|
||||||
if conv:
|
programmer.do()
|
||||||
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
|
|
||||||
subprocess.check_call([
|
|
||||||
"openocd",
|
|
||||||
"-s", scripts_path(),
|
|
||||||
"-f", target_file,
|
|
||||||
"-c", "; ".join(prog),
|
|
||||||
])
|
|
||||||
finally:
|
finally:
|
||||||
if conv:
|
if conv:
|
||||||
os.unlink(bin)
|
os.unlink(bin)
|
||||||
|
|
Loading…
Reference in New Issue