blob: 5ae7dcf914a0060ecbe4f7eae579aee147628600 [file] [log] [blame]
Andrew Boie9280e712016-05-26 14:45:52 -07001#!/usr/bin/env python3
2
3import subprocess
4import tempfile
5import argparse
6import os
7import string
8import sys
Andrew Boie9280e712016-05-26 14:45:52 -07009
10quartus_cpf_template = """<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>
11<cof>
12 <output_filename>${OUTPUT_FILENAME}</output_filename>
13 <n_pages>1</n_pages>
14 <width>1</width>
15 <mode>14</mode>
16 <sof_data>
17 <user_name>Page_0</user_name>
18 <page_flags>1</page_flags>
19 <bit0>
20 <sof_filename>${SOF_FILENAME}<compress_bitstream>1</compress_bitstream></sof_filename>
21 </bit0>
22 </sof_data>
23 <version>10</version>
24 <create_cvp_file>0</create_cvp_file>
25 <create_hps_iocsr>0</create_hps_iocsr>
26 <auto_create_rpd>0</auto_create_rpd>
27 <rpd_little_endian>1</rpd_little_endian>
28 <options>
29 <map_file>1</map_file>
30 </options>
31 <MAX10_device_options>
32 <por>0</por>
33 <io_pullup>1</io_pullup>
34 <config_from_cfm0_only>0</config_from_cfm0_only>
35 <isp_source>0</isp_source>
36 <verify_protect>0</verify_protect>
37 <epof>0</epof>
38 <ufm_source>2</ufm_source>
39 <ufm_filepath>${KERNEL_FILENAME}</ufm_filepath>
40 </MAX10_device_options>
41 <advanced_options>
42 <ignore_epcs_id_check>2</ignore_epcs_id_check>
43 <ignore_condone_check>2</ignore_condone_check>
44 <plc_adjustment>0</plc_adjustment>
45 <post_chain_bitstream_pad_bytes>-1</post_chain_bitstream_pad_bytes>
46 <post_device_bitstream_pad_bytes>-1</post_device_bitstream_pad_bytes>
47 <bitslice_pre_padding>1</bitslice_pre_padding>
48 </advanced_options>
49</cof>
50"""
51
52# XXX Do we care about FileRevision, DefaultMfr, PartName? Do they need
53# to be parameters? So far seems to work across 2 different boards, leave
54# this alone for now.
55quartus_pgm_template = """/* Quartus Prime Version 16.0.0 Build 211 04/27/2016 SJ Lite Edition */
56JedecChain;
57 FileRevision(JESD32A);
58 DefaultMfr(6E);
59
60 P ActionCode(Cfg)
61 Device PartName(10M50DAF484ES) Path("${POF_DIR}/") File("${POF_FILE}") MfrSpec(OpMask(1));
62
63ChainEnd;
64
65AlteraBegin;
66 ChainType(JTAG);
67AlteraEnd;"""
68
69
70def create_pof(input_sof, kernel_hex):
71 """given an input CPU .sof file and a kernel binary, return a file-like
72 object containing .pof data suitable for flashing onto the device"""
73
74 t = string.Template(quartus_cpf_template)
75 output_pof = tempfile.NamedTemporaryFile(suffix=".pof")
76
77 input_sof = os.path.abspath(input_sof)
78 kernel_hex = os.path.abspath(kernel_hex)
79
80 # These tools are very stupid and freak out if the desired filename
81 # extensions are used. The kernel image must have extension .hex
82
83 with tempfile.NamedTemporaryFile(suffix=".cof") as temp_xml:
84
85 xml = t.substitute(SOF_FILENAME=input_sof,
86 OUTPUT_FILENAME=output_pof.name,
87 KERNEL_FILENAME=kernel_hex)
88
89 temp_xml.write(bytes(xml, 'UTF-8'))
90 temp_xml.flush()
91
92 cmd = ["quartus_cpf", "-c", temp_xml.name]
93 try:
94 subprocess.check_output(cmd)
95 except subprocess.CalledProcessError as cpe:
96 print(cpe.output.decode("UTF-8"))
97 print("Failed to create POF file")
98 sys.exit(1)
99
100 return output_pof
101
102
103def flash_kernel(device_id, input_sof, kernel_hex):
104 pof_file = create_pof(input_sof, kernel_hex)
105
106 with tempfile.NamedTemporaryFile(suffix=".cdf") as temp_cdf:
107 dname, fname = os.path.split(pof_file.name)
108 t = string.Template(quartus_pgm_template)
109 cdf = t.substitute(POF_DIR=dname, POF_FILE=fname)
110 temp_cdf.write(bytes(cdf, 'UTF-8'))
111 temp_cdf.flush()
112 cmd = ["quartus_pgm", "-c", device_id, temp_cdf.name]
113 try:
114 subprocess.check_output(cmd)
115 except subprocess.CalledProcessError as cpe:
116 print(cpe.output.decode("UTF-8"))
117 print("Failed to flash image")
118 sys.exit(1)
119 pof_file.close()
120
121def main():
122 parser = argparse.ArgumentParser(description="Flash zephyr onto Altera boards")
123 parser.add_argument("-s", "--sof",
124 help=".sof file with Nios II CPU configuration")
125 parser.add_argument("-k", "--kernel",
126 help="Zephyr kernel image to place into UFM in Intel HEX format")
127 parser.add_argument("-d", "--device",
128 help="Remote device identifier / cable name. Default is "
129 "USB-BlasterII. Run jtagconfig -n if unsure.",
130 default="USB-BlasterII")
131
132 args = parser.parse_args()
133
134 flash_kernel(args.device, args.sof, args.kernel)
135
136
137if __name__ == "__main__":
138 main()