mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
152 lines
4.3 KiB
Python
152 lines
4.3 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 a header with the number of IRQs for a given STM32 family."""
|
||
|
|
||
|
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_INCLUDE_DIR = os.path.join(RIOTBASE, "cpu/stm32/include")
|
||
|
STM32_CMSIS_INCLUDE_DIR = os.path.join(
|
||
|
RIOTBASE, STM32_INCLUDE_DIR, "vendor/cmsis/{}/Include/")
|
||
|
STM32_CMSIS_HEADER = os.path.join(
|
||
|
RIOTBASE, STM32_CMSIS_INCLUDE_DIR, "{}.h")
|
||
|
STM32_IRQS_DIR = os.path.join(
|
||
|
RIOTBASE, STM32_INCLUDE_DIR, "irqs/{}/irqs.h")
|
||
|
|
||
|
IRQS_FORMAT = """
|
||
|
/*
|
||
|
* PLEASE DON'T EDIT
|
||
|
*
|
||
|
* This file was automatically generated by
|
||
|
* ./cpu/stm32/dist/irqs/gen_irqs.py
|
||
|
*/
|
||
|
|
||
|
#ifndef IRQS_{cpu_fam}_H
|
||
|
#define IRQS_{cpu_fam}_H
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
extern "C" {{
|
||
|
#endif
|
||
|
|
||
|
{irq_lines}
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
}}
|
||
|
#endif
|
||
|
|
||
|
#endif /* IRQS_{cpu_fam}_IRQ_H */
|
||
|
"""
|
||
|
|
||
|
|
||
|
def list_cpu_lines(cpu_fam):
|
||
|
"""Returns the list CPU lines for a given family"""
|
||
|
headers = os.listdir(STM32_CMSIS_INCLUDE_DIR.format(cpu_fam))
|
||
|
headers.remove("stm32{}xx.h".format(cpu_fam))
|
||
|
headers.remove("system_stm32{}xx.h".format(cpu_fam))
|
||
|
return [header.split(".")[0] for header in headers]
|
||
|
|
||
|
|
||
|
def irq_numof(cpu_fam, cpu_line):
|
||
|
"""Parse the CMSIS to get the list IRQs."""
|
||
|
cpu_line_cmsis = STM32_CMSIS_HEADER.format(cpu_fam, cpu_line)
|
||
|
|
||
|
with open(cpu_line_cmsis, 'rb') as cmsis:
|
||
|
cmsis_content = cmsis.readlines()
|
||
|
|
||
|
for line_idx, line in enumerate(cmsis_content):
|
||
|
try:
|
||
|
line = line.decode()
|
||
|
except UnicodeDecodeError:
|
||
|
# skip line that contains non unicode characters
|
||
|
continue
|
||
|
# skip useless lines
|
||
|
if (
|
||
|
# Skip lines with comments
|
||
|
line.startswith("/*") or
|
||
|
# Skip line starting with too many spaces
|
||
|
line.startswith(" " * 8) or
|
||
|
# Skip remapped USB interrupt
|
||
|
# (set as alias for USBWakeUp_IRQn on stm32f3)
|
||
|
"USBWakeUp_RMP_IRQn" in line
|
||
|
):
|
||
|
continue
|
||
|
# Stop at the end of the IRQn_Type enum definition
|
||
|
if "IRQn_Type" in line:
|
||
|
break
|
||
|
|
||
|
# Ensure we are on a valid line, otherwise search in earlier lines
|
||
|
last_irq_line = cmsis_content[line_idx - 1].decode()
|
||
|
while last_irq_line.startswith(" " * 8):
|
||
|
line_idx -= 1
|
||
|
last_irq_line = cmsis_content[line_idx - 1].decode()
|
||
|
|
||
|
# Use a regexp to find the last IRQ line index
|
||
|
irq_numof_match = re.search(r"(= \d+)", last_irq_line).group(0)
|
||
|
|
||
|
return int(irq_numof_match.replace("= ", "").strip()) + 1
|
||
|
|
||
|
|
||
|
def generate_irqs(context):
|
||
|
"""Use irqs template to generate the irqs.h file."""
|
||
|
irq_line_first_format = (
|
||
|
"#if defined({line})\n"
|
||
|
"#define CPU_IRQ_NUMOF ({irq_numof}U)"
|
||
|
)
|
||
|
irq_line_format = (
|
||
|
"#elif defined({line})\n"
|
||
|
"#define CPU_IRQ_NUMOF ({irq_numof}U)")
|
||
|
irq_lines = []
|
||
|
for idx, line in enumerate(context["cpu_lines"]):
|
||
|
if idx == 0:
|
||
|
irq_lines.append(
|
||
|
irq_line_first_format.format(**line))
|
||
|
else:
|
||
|
irq_lines.append(
|
||
|
irq_line_format.format(**line))
|
||
|
irq_lines.append("#endif")
|
||
|
|
||
|
irqs_content = IRQS_FORMAT.format(
|
||
|
cpu_fam=context["cpu_fam"].upper(),
|
||
|
irq_lines="\n".join(irq_lines),
|
||
|
)
|
||
|
dest_file = os.path.join(STM32_IRQS_DIR.format(context["cpu_fam"]))
|
||
|
|
||
|
if not os.path.exists(os.path.dirname(dest_file)):
|
||
|
os.makedirs(os.path.dirname(dest_file))
|
||
|
with open(dest_file, "w") as f_dest:
|
||
|
f_dest.write(irqs_content)
|
||
|
|
||
|
|
||
|
def main(args):
|
||
|
"""Main function."""
|
||
|
cpu_lines = list_cpu_lines(args.cpu_fam)
|
||
|
context = {
|
||
|
"cpu_fam": args.cpu_fam,
|
||
|
"cpu_lines": [
|
||
|
{
|
||
|
"line": cpu_line.upper().replace("X", "x"),
|
||
|
"irq_numof": irq_numof(args.cpu_fam, cpu_line),
|
||
|
}
|
||
|
for cpu_line in cpu_lines
|
||
|
]
|
||
|
}
|
||
|
generate_irqs(context)
|
||
|
|
||
|
|
||
|
PARSER = argparse.ArgumentParser()
|
||
|
PARSER.add_argument("cpu_fam", help="STM32 CPU Family")
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
main(PARSER.parse_args())
|