#!/usr/bin/env python3 # # Copyright (c) 2017 Intel Corporation # SPDX-License-Identifier: Apache-2.0 # import argparse import struct import sys import os ISR_FLAG_DIRECT = (1 << 0) def debug(text): if not args.debug: return sys.stdout.write(os.path.basename(sys.argv[0]) + ": " + text + "\n") def error(text): sys.stderr.write(os.path.basename(sys.argv[0]) + ": " + text + "\n") raise Exception() def endian_prefix(): if args.big_endian: return ">" else: return "<" def read_intlist(intlist_path): """read a binary file containing the contents of the kernel's .intList section. This is an instance of a header created by include/linker/intlist.ld: struct { void * spurious_irq_handler; void * sw_irq_handler; u32_t num_isrs; u32_t num_vectors; <- typically CONFIG_NUM_IRQS struct _isr_list isrs[]; <- of size num_isrs } Followed by instances of struct _isr_list created by IRQ_CONNECT() calls: struct _isr_list { /** IRQ line number */ s32_t irq; /** Flags for this IRQ, see ISR_FLAG_* definitions */ s32_t flags; /** ISR to call */ void *func; /** Parameter for non-direct IRQs */ void *param; }; """ intlist = {} prefix = endian_prefix() intlist_header_fmt = prefix + "IIIII" intlist_entry_fmt = prefix + "iiII" with open(intlist_path, "rb") as fp: intdata = fp.read() header_sz = struct.calcsize(intlist_header_fmt) header = struct.unpack_from(intlist_header_fmt, intdata, 0) intdata = intdata[header_sz:] debug(str(header)) intlist["spurious_handler"] = header[0] intlist["sw_irq_handler"] = header[1] intlist["num_vectors"] = header[2] intlist["offset"] = header[3] intlist["num_isrs"] = header[4] debug("spurious handler: %s" % hex(header[0])) intlist["interrupts"] = [i for i in struct.iter_unpack(intlist_entry_fmt, intdata)] debug("Configured interrupt routing") debug("handler irq flags param") debug("--------------------------") for irq in intlist["interrupts"]: debug("{0:<10} {1:<3} {2:<3} {3}".format( hex(irq[2]), irq[0], irq[1], hex(irq[3]))) return intlist def parse_args(): global args parser = argparse.ArgumentParser(description = __doc__, formatter_class = argparse.RawDescriptionHelpFormatter) parser.add_argument("-e", "--big-endian", action="store_true", help="Target encodes data in big-endian format (little endian is " "the default)") parser.add_argument("-d", "--debug", action="store_true", help="Print additional debugging information") parser.add_argument("-o", "--output-source", required=True, help="Output source file") parser.add_argument("-s", "--sw-isr-table", action="store_true", help="Generate SW ISR table") parser.add_argument("-V", "--vector-table", action="store_true", help="Generate vector table") parser.add_argument("-i", "--intlist", required=True, help="Zephyr intlist binary for intList extraction") args = parser.parse_args() source_header = """ /* AUTO-GENERATED by gen_isr_tables.py, do not edit! */ #include #include #include """ def write_source_file(fp, vt, swt, intlist): fp.write(source_header) nv = intlist["num_vectors"] if vt: fp.write("u32_t __irq_vector_table _irq_vector_table[%d] = {\n" % nv) for i in range(nv): fp.write("\t0x%x,\n" % vt[i]) fp.write("};\n") if not swt: return fp.write("struct _isr_table_entry __sw_isr_table _sw_isr_table[%d] = {\n" % nv) for i in range(nv): param, func = swt[i] fp.write("\t{(void *)0x%x, (void *)0x%x},\n" % (param, func)) fp.write("};\n") def main(): parse_args() intlist = read_intlist(args.intlist) nvec = intlist["num_vectors"] offset = intlist["offset"] prefix = endian_prefix() # Set default entries in both tables if args.sw_isr_table: # All vectors just jump to the common sw_irq_handler. If some entries # are used for direct interrupts, they will be replaced later. if args.vector_table: vt = [intlist["sw_irq_handler"] for i in range(nvec)] else: vt = None # Default to spurious interrupt handler. Configured interrupts # will replace these entries. swt = [(0, intlist["spurious_handler"]) for i in range(nvec)] else: if args.vector_table: vt = [intlist["spurious_handler"] for i in range(nvec)] else: error("one or both of -s or -V needs to be specified on command line") swt = None for irq, flags, func, param in intlist["interrupts"]: if (flags & ISR_FLAG_DIRECT): if (param != 0): error("Direct irq %d declared, but has non-NULL parameter" % irq) vt[irq - offset] = func else: # Regular interrupt if not swt: error("Regular Interrupt %d declared with parameter 0x%x " "but no SW ISR_TABLE in use" % (irq, param)) swt[irq - offset] = (param, func) with open(args.output_source, "w") as fp: write_source_file(fp, vt, swt, intlist) if __name__ == "__main__": main()