forked from M-Labs/artiq
artiq_flash: use openocd, python
This commit is contained in:
parent
b10da212ab
commit
9aff99568d
|
@ -0,0 +1,132 @@
|
||||||
|
#!/usr/bin/env python3.5
|
||||||
|
# Copyright (C) 2015 Robert Jordens <jordens@gmail.com>
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
import artiq
|
||||||
|
from artiq.frontend.bit2bin import bit2bin
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
description="ARTIQ flashing/deployment tool",
|
||||||
|
epilog="""\
|
||||||
|
Valid actions:
|
||||||
|
|
||||||
|
* proxy: load the flash proxy bitstream
|
||||||
|
* bitstream: write bitstream to flash
|
||||||
|
* bios: write bios to flash
|
||||||
|
* runtime: write runtime to flash
|
||||||
|
* storage: write storage image to flash
|
||||||
|
* load: load bitstream into device (volatile but fast)
|
||||||
|
* start: trigger the target to (re)load its bitstream from flash
|
||||||
|
|
||||||
|
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.
|
||||||
|
* Make the matching proxy bitstream accessible in ~/.migen or
|
||||||
|
/usr/local/share/migen or /usr/share/migen. Proxy bitstreams are
|
||||||
|
published at https://github.com/jordens/bscan_spi_bitstreams.
|
||||||
|
This script will tell you which one is needed.
|
||||||
|
""")
|
||||||
|
parser.add_argument("-t", "--target", default="kc705",
|
||||||
|
help="target board, default: %(default)s")
|
||||||
|
parser.add_argument("-m", "--adapter", default="qc2",
|
||||||
|
help="target adapter, default: %(default)s")
|
||||||
|
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", nargs="*",
|
||||||
|
default="proxy bitstream bios runtime start".split(),
|
||||||
|
help="actions to perform, default: %(default)s")
|
||||||
|
opts = parser.parse_args()
|
||||||
|
|
||||||
|
config = {
|
||||||
|
"kc705": {
|
||||||
|
"chip": "xc7k325t",
|
||||||
|
"start": "xc7_program xc7.tap",
|
||||||
|
"bitstream": 0x000000,
|
||||||
|
"bios": 0xaf0000,
|
||||||
|
"runtime": 0xb00000,
|
||||||
|
"storage": 0xb40000,
|
||||||
|
},
|
||||||
|
"pipistrello": {
|
||||||
|
"chip": "xc6slx45",
|
||||||
|
"start": "xc6s_program xc6s.tap",
|
||||||
|
"bitstream": 0x000000,
|
||||||
|
"bios": 0x170000,
|
||||||
|
"runtime": 0x180000,
|
||||||
|
"storage": 0x1c0000,
|
||||||
|
},
|
||||||
|
}[opts.target]
|
||||||
|
|
||||||
|
if opts.dir is None:
|
||||||
|
opts.dir = os.path.join(os.path.dirname(artiq.__file__), "binaries",
|
||||||
|
"{}-{}".format(opts.target, opts.adapter))
|
||||||
|
|
||||||
|
conv = False
|
||||||
|
|
||||||
|
prog = []
|
||||||
|
prog.append("init")
|
||||||
|
for action in opts.ACTION:
|
||||||
|
if action == "proxy":
|
||||||
|
proxy_base = "bscan_spi_{}.bit".format(config["chip"])
|
||||||
|
proxy = None
|
||||||
|
for p in [opts.dir, os.path.expanduser("~/.migen"),
|
||||||
|
"/usr/local/share/migen", "/usr/share/migen"]:
|
||||||
|
proxy_ = os.path.join(p, proxy_base)
|
||||||
|
if os.access(proxy_, os.R_OK):
|
||||||
|
proxy = "jtagspi_init 0 {}".format(proxy_)
|
||||||
|
break
|
||||||
|
if not proxy:
|
||||||
|
raise SystemExit(
|
||||||
|
"proxy bitstream {} not found".format(proxy_base))
|
||||||
|
prog.append(proxy)
|
||||||
|
elif action == "bitstream":
|
||||||
|
bin = os.path.join(opts.dir, "top.bin")
|
||||||
|
if not os.access(bin, os.R_OK):
|
||||||
|
bin = tempfile.mkstemp()[1]
|
||||||
|
bit = os.path.join(opts.dir, "top.bit")
|
||||||
|
conv = True
|
||||||
|
prog.append("jtagspi_program {} 0x{:x}".format(
|
||||||
|
bin, config["bitstream"]))
|
||||||
|
elif action == "bios":
|
||||||
|
prog.append("jtagspi_program {} 0x{:x}".format(
|
||||||
|
os.path.join(opts.dir, "bios.bin"), config["bios"]))
|
||||||
|
elif action == "runtime":
|
||||||
|
prog.append("jtagspi_program {} 0x{:x}".format(
|
||||||
|
os.path.join(opts.dir, "runtime.fbi"), config["runtime"]))
|
||||||
|
elif action == "storage":
|
||||||
|
prog.append("jtagspi_program {} 0x{:x}".format(
|
||||||
|
opts.storage, config["storage"]))
|
||||||
|
elif action == "load":
|
||||||
|
prog.append("pld load 0 {}".format(
|
||||||
|
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:
|
||||||
|
bit2bin(bit, bin)
|
||||||
|
subprocess.check_call([
|
||||||
|
"openocd",
|
||||||
|
"-f", os.path.join("board", opts.target + ".cfg"),
|
||||||
|
"-c", "; ".join(prog),
|
||||||
|
])
|
||||||
|
finally:
|
||||||
|
if conv:
|
||||||
|
os.unlink(bin)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -1,209 +0,0 @@
|
||||||
#!/usr/bin/env python3.5
|
|
||||||
# conda-build requires all scripts to have a python shebang.
|
|
||||||
# see https://github.com/conda/conda-build/blob/6921f067a/conda_build/noarch_python.py#L36-L38
|
|
||||||
|
|
||||||
def run(script):
|
|
||||||
import sys, tempfile, subprocess
|
|
||||||
file = tempfile.NamedTemporaryFile(mode='w+t', suffix='sh')
|
|
||||||
file.write(script)
|
|
||||||
file.flush()
|
|
||||||
subprocess.run(["/bin/bash", file.name] + sys.argv[1:])
|
|
||||||
file.close()
|
|
||||||
|
|
||||||
run("""
|
|
||||||
set -e
|
|
||||||
|
|
||||||
ARTIQ_PREFIX=$(python3.5 -c "import artiq; print(artiq.__path__[0])")
|
|
||||||
|
|
||||||
# Default is kc705
|
|
||||||
BOARD=kc705
|
|
||||||
# Default hardware adapter is qc1
|
|
||||||
HARDWARE_ADAPTER=qc1
|
|
||||||
|
|
||||||
while getopts "bBrht:d:f:m:" opt
|
|
||||||
do
|
|
||||||
case $opt in
|
|
||||||
b)
|
|
||||||
FLASH_BITSTREAM=1
|
|
||||||
;;
|
|
||||||
B)
|
|
||||||
FLASH_BIOS=1
|
|
||||||
;;
|
|
||||||
r)
|
|
||||||
FLASH_RUNTIME=1
|
|
||||||
;;
|
|
||||||
f)
|
|
||||||
if [ -f $OPTARG ]
|
|
||||||
then
|
|
||||||
FILENAME=$OPTARG
|
|
||||||
else
|
|
||||||
echo "You specified a non-existing file to flash: $OPTARG"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
t)
|
|
||||||
if [ "$OPTARG" == "kc705" ]
|
|
||||||
then
|
|
||||||
BOARD=kc705
|
|
||||||
elif [ "$OPTARG" == "pipistrello" ]
|
|
||||||
then
|
|
||||||
BOARD=pipistrello
|
|
||||||
else
|
|
||||||
echo "Supported targets (-t option) are:"
|
|
||||||
echo "kc705 or pipistrello"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
d)
|
|
||||||
if [ -d $OPTARG ]
|
|
||||||
then
|
|
||||||
BIN_PATH=$OPTARG
|
|
||||||
else
|
|
||||||
echo "You specified a non-existing directory: $OPTARG"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
m)
|
|
||||||
if [ "$OPTARG" == "qc1" ]
|
|
||||||
then
|
|
||||||
HARDWARE_ADAPTER=qc1
|
|
||||||
elif [ "$OPTARG" == "qc2" ]
|
|
||||||
then
|
|
||||||
HARDWARE_ADAPTER=qc2
|
|
||||||
else
|
|
||||||
echo "Hardware adapter should be qc1 or qc2"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "ARTIQ flashing tool"
|
|
||||||
echo ""
|
|
||||||
echo "To flash everything, do not use any of the -b|-B|-r option."
|
|
||||||
echo ""
|
|
||||||
echo "usage: artiq_flash.sh [-b] [-B] [-r] [-h] [-m nist_qc1|nist_qc2] [-t kc705|pipistrello] [-d path] [-f path]"
|
|
||||||
echo "-b Flash bitstream"
|
|
||||||
echo "-B Flash BIOS"
|
|
||||||
echo "-r Flash ARTIQ runtime"
|
|
||||||
echo "-h Show this help message"
|
|
||||||
echo "-t Target (kc705/pipistrello, default: kc705)"
|
|
||||||
echo "-m Hardware adapter (qc1/qc2, default: qc1)"
|
|
||||||
echo "-f Flash storage image generated with artiq_mkfs"
|
|
||||||
echo "-d Directory containing the binaries to be flashed"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
function search_for_proxy()
|
|
||||||
{
|
|
||||||
PROXY=$1 # The proxy name
|
|
||||||
if [ -f $HOME/.migen/$PROXY ]
|
|
||||||
then
|
|
||||||
PROXY_PATH=$HOME/.migen/
|
|
||||||
elif [ -f /usr/local/share/migen/$PROXY ]
|
|
||||||
then
|
|
||||||
PROXY_PATH=/usr/local/share/migen/
|
|
||||||
elif [ -f /usr/share/migen/$PROXY ]
|
|
||||||
then
|
|
||||||
PROXY_PATH=/usr/share/migen/
|
|
||||||
elif [ -f $BIN_PREFIX/$PROXY ]
|
|
||||||
then
|
|
||||||
PROXY_PATH=$BIN_PREFIX
|
|
||||||
else
|
|
||||||
echo "$BOARD flash proxy ($PROXY) not found."
|
|
||||||
echo "Please put it in ~/.migen or /usr/local/share/migen or /usr/share/migen"
|
|
||||||
echo "To get the flash proxy, follow the \"Install the required flash proxy bitstreams:\""
|
|
||||||
echo "bullet point from http://m-labs.hk/artiq/manual/installing.html#preparing-the-core-device-fpga-board"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
if ! [ -z "$BIN_PATH" ]
|
|
||||||
then
|
|
||||||
BIN_PREFIX=$BIN_PATH
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$BOARD" == "kc705" ]
|
|
||||||
then
|
|
||||||
UDEV_RULES=99-kc705.rules
|
|
||||||
CABLE=jtaghs1_fast
|
|
||||||
PROXY=bscan_spi_kc705.bit
|
|
||||||
BIOS_ADDR=0xaf0000
|
|
||||||
RUNTIME_ADDR=0xb00000
|
|
||||||
FS_ADDR=0xb40000
|
|
||||||
if [ -z "$BIN_PREFIX" ]
|
|
||||||
then
|
|
||||||
BIN_PREFIX=$ARTIQ_PREFIX/binaries/kc705-$HARDWARE_ADAPTER
|
|
||||||
fi
|
|
||||||
search_for_proxy $PROXY
|
|
||||||
elif [ "$BOARD" == "pipistrello" ]
|
|
||||||
then
|
|
||||||
UDEV_RULES=99-papilio.rules
|
|
||||||
CABLE=papilio
|
|
||||||
PROXY=bscan_spi_lx45_csg324.bit
|
|
||||||
BIOS_ADDR=0x170000
|
|
||||||
RUNTIME_ADDR=0x180000
|
|
||||||
FS_ADDR=0x1c0000
|
|
||||||
if [ -z "$BIN_PREFIX" ];
|
|
||||||
then
|
|
||||||
BIN_PREFIX=$ARTIQ_PREFIX/binaries/pipistrello-$HARDWARE_ADAPTER
|
|
||||||
fi
|
|
||||||
search_for_proxy $PROXY
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if neither of -b|-B|-r have been used
|
|
||||||
if [ -z "$FLASH_RUNTIME" -a -z "$FLASH_BIOS" -a -z "$FLASH_BITSTREAM" -a -z "$FILENAME" ]
|
|
||||||
then
|
|
||||||
FLASH_RUNTIME=1
|
|
||||||
FLASH_BIOS=1
|
|
||||||
FLASH_BITSTREAM=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
set +e
|
|
||||||
xc3sprog -c $CABLE -R > /dev/null 2>&1
|
|
||||||
STATUS=$?
|
|
||||||
set -e
|
|
||||||
if [ "$STATUS" == "127" ]
|
|
||||||
then
|
|
||||||
echo "xc3sprog not found. Please install it or check your PATH."
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
if [ "$STATUS" != "0" ]
|
|
||||||
then
|
|
||||||
echo "Failed to connect to FPGA."
|
|
||||||
echo "Maybe you do not have permission to access the USB device?"
|
|
||||||
echo "To fix this you might want to add a udev rule by doing:"
|
|
||||||
echo "$ sudo cp $ARTIQ_PREFIX/misc/$UDEV_RULES /etc/udev/rules.d"
|
|
||||||
echo "Then unplug/replug your device and try flashing again"
|
|
||||||
echo
|
|
||||||
echo "Other reason could be that you chosed the wrong target"
|
|
||||||
echo "Please make sure you used the correct -t option (currently: $BOARD)"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -z "$FILENAME" ]
|
|
||||||
then
|
|
||||||
echo "Flashing file $FILENAME at address $FS_ADDR"
|
|
||||||
xc3sprog -v -c $CABLE -I$PROXY_PATH/$PROXY $FILENAME:w:$FS_ADDR:BIN
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${FLASH_BITSTREAM}" == "1" ]
|
|
||||||
then
|
|
||||||
echo "Flashing FPGA bitstream..."
|
|
||||||
xc3sprog -v -c $CABLE -I$PROXY_PATH/$PROXY $BIN_PREFIX/top.bit:w:0x0:BIT
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${FLASH_BIOS}" == "1" ]
|
|
||||||
then
|
|
||||||
echo "Flashing BIOS..."
|
|
||||||
xc3sprog -v -c $CABLE -I$PROXY_PATH/$PROXY $BIN_PREFIX/bios.bin:w:$BIOS_ADDR:BIN
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${FLASH_RUNTIME}" == "1" ]
|
|
||||||
then
|
|
||||||
echo "Flashing ARTIQ runtime..."
|
|
||||||
xc3sprog -v -c $CABLE -I$PROXY_PATH/$PROXY $BIN_PREFIX/runtime.fbi:w:$RUNTIME_ADDR:BIN
|
|
||||||
fi
|
|
||||||
echo "Done."
|
|
||||||
xc3sprog -v -c $CABLE -R > /dev/null 2>&1
|
|
||||||
""")
|
|
Loading…
Reference in New Issue