mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Alexandre Abadie
e6bb1a240e
This script can be used to automatically generate the vectors.c file corresponding to an STM32 cpu line
144 lines
3.9 KiB
Python
Executable File
144 lines
3.9 KiB
Python
Executable File
#!/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
|
|
|
|
|
|
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
RIOTBASE = os.getenv(
|
|
"RIOTBASE", os.path.abspath(os.path.join(CURRENT_DIR, "../../../..")))
|
|
STM32_VECTORS_DIR = os.path.join(RIOTBASE, "cpu/stm32/vectors")
|
|
STM32_VENDOR_DIR = os.path.join(RIOTBASE, "cpu/stm32/include/vendor")
|
|
STM32_CMSIS_FILE = os.path.join(
|
|
RIOTBASE, STM32_VENDOR_DIR, "cmsis/{}/Include/{}.h")
|
|
|
|
VECTORS_FORMAT = """
|
|
/*
|
|
* PLEASE DON'T EDIT
|
|
*
|
|
* This file was automatically generated by
|
|
* ./cpu/stm32/dist/irqs/gen_vectors.py
|
|
*/
|
|
|
|
#include "vectors_cortexm.h"
|
|
|
|
/* define a local dummy handler as it needs to be in the same compilation unit
|
|
* as the alias definition */
|
|
void dummy_handler(void) {{
|
|
dummy_handler_default();
|
|
}}
|
|
|
|
/* {cpu_line} specific interrupt vectors */
|
|
{isr_lines}
|
|
|
|
/* CPU specific interrupt vector table */
|
|
ISR_VECTOR(1) const isr_t vector_cpu[CPU_IRQ_NUMOF] = {{
|
|
{irq_lines}
|
|
}};
|
|
"""
|
|
|
|
|
|
def parse_cmsis(cpu_line):
|
|
"""Parse the CMSIS to get the list IRQs."""
|
|
cpu_fam = cpu_line[5:7]
|
|
if cpu_line == "STM32F030x4":
|
|
# STM32F030x4 is provided in the RIOT codebase in a different location
|
|
cpu_line_cmsis = os.path.join(
|
|
STM32_VENDOR_DIR, "{}.h".format(cpu_line.lower()))
|
|
else:
|
|
cpu_line_cmsis = STM32_CMSIS_FILE.format(
|
|
cpu_fam.lower(), 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 line.startswith("typedef enum"):
|
|
use_line = True
|
|
|
|
# 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 is None:
|
|
continue
|
|
|
|
# Skip remapped USB interrupt
|
|
# (set as alias for USBWakeUp_IRQn on stm32f3)
|
|
if "USBWakeUp_RMP_IRQn" in line:
|
|
continue
|
|
|
|
# Stop at the end of the IRQn_Type enum definition
|
|
if "IRQn_Type" in line:
|
|
break
|
|
|
|
# Only append IRQ line if it should be used and is not empty
|
|
if use_line:
|
|
irq_lines.append(match.group(1).strip())
|
|
|
|
isrs = [
|
|
{
|
|
"irq": irq,
|
|
"func": "exti" if "EXTI" in irq else irq.lower().rsplit("_", 1)[0]
|
|
}
|
|
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 isr_{func}(void);"
|
|
irq_line_format = " [{irq:<35}] = isr_{func},"
|
|
|
|
isr_lines = []
|
|
irq_lines = []
|
|
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),
|
|
)
|
|
|
|
dest_file = os.path.join(
|
|
STM32_VECTORS_DIR, "{}.c".format(context["cpu_line"])
|
|
)
|
|
|
|
with open(dest_file, "w") as f_dest:
|
|
f_dest.write(vectors_content)
|
|
|
|
|
|
def main(args):
|
|
"""Main function."""
|
|
context = parse_cmsis(args.cpu_line)
|
|
generate_vectors(context)
|
|
|
|
|
|
PARSER = argparse.ArgumentParser()
|
|
PARSER.add_argument("cpu_line", help="STM32 CPU line")
|
|
|
|
if __name__ == "__main__":
|
|
main(PARSER.parse_args())
|