nios2: add flashing/debug scripts

For the moment, NIOS2_CPU_SOF must be set with the path to the
CPU configuration. We are checking with Altera on whether we
can directly check in the binary to the source tree.

These scripts depend on tools provided by the Altera Quartus
Prime Lite Edition. This is available for free but requires
registration on Altera's website to obtain.

Change-Id: Ia6cb6c9e43c3e141807a887cb25c47b370a7d8e9
Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2016-05-26 14:45:52 -07:00 committed by Anas Nashif
parent fe6f178a3b
commit 9280e71ea4
4 changed files with 196 additions and 0 deletions

View file

@ -43,3 +43,4 @@ $(KERNEL_HEX_NAME): $(KERNEL_ELF_NAME)
zephyr: $(KERNEL_HEX_NAME)
all: $(KERNEL_HEX_NAME)
export KERNEL_HEX_NAME

View file

@ -0,0 +1,2 @@
FLASH_SCRIPT = nios2.sh

53
scripts/support/nios2.sh Executable file
View file

@ -0,0 +1,53 @@
#!/bin/bash
set -e
HEX_NAME=${O}/${KERNEL_HEX_NAME}
ELF_NAME=${O}/${KERNEL_ELF_NAME}
GDB_TCP_PORT=1234
REQUIRED_PROGRAMS="quartus_cpf quartus_pgm nios2-gdb-server"
for pgm in ${REQUIRED_PROGRAMS}; do
type -P $pgm > /dev/null 2>&1 || { echo >&2 "$pgm not found in PATH"; exit 1; }
done
do_flash() {
if [ -z "${NIOS2_CPU_SOF}" ]; then
echo "Please set NIOS2_CPU_SOF variable to location of CPU .sof data"
exit 1
fi
${ZEPHYR_BASE}/scripts/support/quartus-flash.py \
--sof ${NIOS2_CPU_SOF} \
--kernel ${HEX_NAME}
}
do_debug() {
do_debugserver &
# connect to the GDB server
${GDB} ${TUI} -ex "target remote :${GDB_TCP_PORT}" ${ELF_NAME}
}
do_debugserver() {
nios2-gdb-server --tcpport ${GDB_TCP_PORT}
}
CMD="$1"
shift
case "${CMD}" in
flash)
do_flash "$@"
;;
debugserver)
do_debugserver "$@"
;;
debug)
do_debug "$@"
;;
esac

140
scripts/support/quartus-flash.py Executable file
View file

@ -0,0 +1,140 @@
#!/usr/bin/env python3
import subprocess
import tempfile
import argparse
import os
import string
import sys
import shutil
quartus_cpf_template = """<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>
<cof>
<output_filename>${OUTPUT_FILENAME}</output_filename>
<n_pages>1</n_pages>
<width>1</width>
<mode>14</mode>
<sof_data>
<user_name>Page_0</user_name>
<page_flags>1</page_flags>
<bit0>
<sof_filename>${SOF_FILENAME}<compress_bitstream>1</compress_bitstream></sof_filename>
</bit0>
</sof_data>
<version>10</version>
<create_cvp_file>0</create_cvp_file>
<create_hps_iocsr>0</create_hps_iocsr>
<auto_create_rpd>0</auto_create_rpd>
<rpd_little_endian>1</rpd_little_endian>
<options>
<map_file>1</map_file>
</options>
<MAX10_device_options>
<por>0</por>
<io_pullup>1</io_pullup>
<config_from_cfm0_only>0</config_from_cfm0_only>
<isp_source>0</isp_source>
<verify_protect>0</verify_protect>
<epof>0</epof>
<ufm_source>2</ufm_source>
<ufm_filepath>${KERNEL_FILENAME}</ufm_filepath>
</MAX10_device_options>
<advanced_options>
<ignore_epcs_id_check>2</ignore_epcs_id_check>
<ignore_condone_check>2</ignore_condone_check>
<plc_adjustment>0</plc_adjustment>
<post_chain_bitstream_pad_bytes>-1</post_chain_bitstream_pad_bytes>
<post_device_bitstream_pad_bytes>-1</post_device_bitstream_pad_bytes>
<bitslice_pre_padding>1</bitslice_pre_padding>
</advanced_options>
</cof>
"""
# XXX Do we care about FileRevision, DefaultMfr, PartName? Do they need
# to be parameters? So far seems to work across 2 different boards, leave
# this alone for now.
quartus_pgm_template = """/* Quartus Prime Version 16.0.0 Build 211 04/27/2016 SJ Lite Edition */
JedecChain;
FileRevision(JESD32A);
DefaultMfr(6E);
P ActionCode(Cfg)
Device PartName(10M50DAF484ES) Path("${POF_DIR}/") File("${POF_FILE}") MfrSpec(OpMask(1));
ChainEnd;
AlteraBegin;
ChainType(JTAG);
AlteraEnd;"""
def create_pof(input_sof, kernel_hex):
"""given an input CPU .sof file and a kernel binary, return a file-like
object containing .pof data suitable for flashing onto the device"""
t = string.Template(quartus_cpf_template)
output_pof = tempfile.NamedTemporaryFile(suffix=".pof")
input_sof = os.path.abspath(input_sof)
kernel_hex = os.path.abspath(kernel_hex)
# These tools are very stupid and freak out if the desired filename
# extensions are used. The kernel image must have extension .hex
with tempfile.NamedTemporaryFile(suffix=".cof") as temp_xml:
xml = t.substitute(SOF_FILENAME=input_sof,
OUTPUT_FILENAME=output_pof.name,
KERNEL_FILENAME=kernel_hex)
temp_xml.write(bytes(xml, 'UTF-8'))
temp_xml.flush()
cmd = ["quartus_cpf", "-c", temp_xml.name]
try:
subprocess.check_output(cmd)
except subprocess.CalledProcessError as cpe:
print(cpe.output.decode("UTF-8"))
print("Failed to create POF file")
sys.exit(1)
return output_pof
def flash_kernel(device_id, input_sof, kernel_hex):
pof_file = create_pof(input_sof, kernel_hex)
with tempfile.NamedTemporaryFile(suffix=".cdf") as temp_cdf:
dname, fname = os.path.split(pof_file.name)
t = string.Template(quartus_pgm_template)
cdf = t.substitute(POF_DIR=dname, POF_FILE=fname)
temp_cdf.write(bytes(cdf, 'UTF-8'))
temp_cdf.flush()
cmd = ["quartus_pgm", "-c", device_id, temp_cdf.name]
try:
subprocess.check_output(cmd)
except subprocess.CalledProcessError as cpe:
print(cpe.output.decode("UTF-8"))
print("Failed to flash image")
sys.exit(1)
pof_file.close()
def main():
parser = argparse.ArgumentParser(description="Flash zephyr onto Altera boards")
parser.add_argument("-s", "--sof",
help=".sof file with Nios II CPU configuration")
parser.add_argument("-k", "--kernel",
help="Zephyr kernel image to place into UFM in Intel HEX format")
parser.add_argument("-d", "--device",
help="Remote device identifier / cable name. Default is "
"USB-BlasterII. Run jtagconfig -n if unsure.",
default="USB-BlasterII")
args = parser.parse_args()
flash_kernel(args.device, args.sof, args.kernel)
if __name__ == "__main__":
main()