Files
edgetx/radio/util/gen_vectors.py
2026-08-03 16:37:20 +08:00

136 lines
3.4 KiB
Python

#!/usr/bin/env python3
# Copyright (C) 2020 Inria
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
"""Generate the vectors table for a given STM32 CPU line."""
import os
import argparse
import re
VECTORS_FORMAT = """
#include "{cpu_line}.h"
#include "cortex_m_isr.h"
void Default_Handler() {{ default_isr_handler(); }}
/* {cpu_line} specific interrupt vectors */
{isr_lines}
/* CPU specific interrupt vector table */
const isr_t _isr_vector[] ISR_VECTOR = {{
[0] = (isr_t)&_estack,
{irq_lines}
}};
"""
def parse_cmsis(cmsis_dir, cpu_line):
"""Parse the CMSIS to get the list IRQs."""
cpu_line_cmsis = os.path.join("{}/{}.h".format(cmsis_dir, cpu_line.lower()))
with open(cpu_line_cmsis, "rb") as cmsis:
cmsis_content = cmsis.readlines()
irq_lines = []
use_line = False
for line in cmsis_content:
try:
line = line.decode()
except UnicodeDecodeError:
# skip line that contains non unicode characters
continue
# start filling lines after interrupt Doxygen comment
if "typedef enum" in line:
irq_lines = [] # Cleanup any previous content
use_line = True
# enum not yet detected: skip
if not use_line:
continue
# Stop at the end of the IRQn_Type enum definition
if "IRQn_Type" in line:
break
# use a regexp to get the available IRQs
match = re.match(r"[ ]+([a-zA-Z0-9_]+_IRQn)[ ]+= \d+", line)
# Skip lines that don't match
if match:
irq_lines.append(match.group(1).strip())
isrs = [
{"irq": irq + " + 16", "func": irq.rsplit("_", 1)[0] + "_IRQHandler"}
for irq in irq_lines
]
return {"isrs": isrs, "cpu_line": cpu_line}
def generate_vectors(context):
"""Use vector template string to generate the vectors C file."""
isr_line_format = "WEAK_DEFAULT void {func}();"
irq_line_format = " [{irq:<35}] = {func},"
isr_lines = []
irq_lines = []
cortex_m_irqs = [
"Reset_Handler",
"NMI_Handler",
"HardFault_Handler",
"MemManage_Handler",
"BusFault_Handler",
"UsageFault_Handler",
"0",
"0",
"0",
"0",
"SVC_Handler",
"DebugMon_Handler",
"0",
"PendSV_Handler",
"SysTick_Handler",
]
irqn = 1
for isr in cortex_m_irqs:
if isr != "0":
isr_lines.append(isr_line_format.format(func=isr))
irq_lines.append(irq_line_format.format(irq=irqn, func=isr))
irqn += 1
for isr in context["isrs"]:
isr_line = isr_line_format.format(**isr)
if isr_line not in isr_lines:
isr_lines.append(isr_line)
irq_lines.append(irq_line_format.format(**isr))
vectors_content = VECTORS_FORMAT.format(
cpu_line=context["cpu_line"],
isr_lines="\n".join(isr_lines),
irq_lines="\n".join(irq_lines),
)
print(vectors_content)
def main(args):
"""Main function."""
context = parse_cmsis(args.cmsis_dir, args.cpu_line)
generate_vectors(context)
PARSER = argparse.ArgumentParser()
PARSER.add_argument("cmsis_dir", help="CMSIS directory")
PARSER.add_argument("cpu_line", help="STM32 CPU line")
if __name__ == "__main__":
main(PARSER.parse_args())