192 lines
5.4 KiB
Python
Executable File
192 lines
5.4 KiB
Python
Executable File
#!/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 args.debug:
|
|
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 <toolchain.h>
|
|
#include <linker/sections.h>
|
|
#include <sw_isr_table.h>
|
|
|
|
"""
|
|
|
|
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()
|
|
|