a56174dc10
This prevents running into the pins that cannot be reset. On 1011 it was off by one pin that isn't attached to the package. So, having the USB pins forbidden prevented resetting to a NULL address. Fixes #7952
377 lines
15 KiB
Python
377 lines
15 KiB
Python
import sys
|
|
import pathlib
|
|
import xml.etree.ElementTree as ET
|
|
|
|
SIGNALS = {
|
|
"LPI2C": ["SDA", "SCL"],
|
|
"LPSPI": ["SCK", "SDO", "SDI"],
|
|
"LPUART": ["RX", "TX", "RTS", "CTS"],
|
|
"I2S": ["RX_DATA0", "RX_SYNC", "TX_BCLK", "TX_DATA0", "TX_SYNC"],
|
|
"MQS": ["LEFT", "RIGHT"],
|
|
}
|
|
|
|
SIGNAL_RENAME = {
|
|
"CTS_B": "CTS",
|
|
"RTS_B": "RTS",
|
|
"RXD": "RX",
|
|
"TXD": "TX",
|
|
"TX_DATA00": "TX_DATA0",
|
|
"RX_DATA00": "RX_DATA0",
|
|
"TX_DATA": "TX_DATA0",
|
|
"RX_DATA": "RX_DATA0",
|
|
}
|
|
|
|
SKIP_LPSR = True
|
|
|
|
svd_folder = pathlib.Path(sys.argv[1])
|
|
|
|
# Download and extract config tools data from https://mcuxpresso.nxp.com/en/select_config_tools_data
|
|
config_data_folder = pathlib.Path(sys.argv[2])
|
|
devices = sys.argv[3:]
|
|
|
|
peripherals_dir = pathlib.Path("peripherals/mimxrt10xx")
|
|
|
|
copyright = """/*
|
|
* This file is part of the MicroPython project, http://micropython.org/
|
|
*
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
|
|
* Copyright (c) 2019 Artur Pacholec
|
|
* Copyright (c) 2023 Scott Shawcroft for Adafruit Industries
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
"""
|
|
|
|
autogen_warning_template = """/*
|
|
* This file is autogenerated! Do NOT hand edit it. Instead, edit tools/gen_peripherals_data.py and
|
|
* then rerun the script. You'll need to 1) clone https://github.com/nxp-mcuxpresso/mcux-soc-svd/
|
|
* and 2) download and extract config tools data from https://mcuxpresso.nxp.com/en/select_config_tools_data.
|
|
*
|
|
* Run `python tools/gen_peripherals_data.py <svd dir> <config dir> {}` to update this file.
|
|
*/
|
|
"""
|
|
|
|
for device in devices:
|
|
print(device)
|
|
autogen_warning = autogen_warning_template.format(device)
|
|
svd_fn = svd_folder / device / (device + ".xml")
|
|
if not svd_fn.exists():
|
|
svd_fn = svd_folder / device / (device + "_cm7.xml")
|
|
|
|
pin_to_analog = {}
|
|
out_dir = peripherals_dir / device
|
|
largest_signals = None
|
|
for signal_file in config_data_folder.glob(
|
|
f"{device}*ConfigTools_data*/**/signal_configuration.xml"
|
|
):
|
|
if largest_signals is None or signal_file.stat().st_size > largest_signals.stat().st_size:
|
|
largest_signals = signal_file
|
|
|
|
# Use the signal file to find analog connections
|
|
signal_tree = ET.parse(largest_signals)
|
|
signal_root = signal_tree.getroot()
|
|
for connection in signal_root.iter("connections"):
|
|
if "name_part" not in connection.attrib or not connection.attrib["name_part"].startswith(
|
|
"ADC"
|
|
):
|
|
continue
|
|
name_part = connection.attrib["name_part"]
|
|
try:
|
|
assign = next(connection.iter("assign"))
|
|
except StopIteration:
|
|
continue
|
|
split_pin = assign.attrib["register"].split("_")
|
|
pin_name = "_".join(split_pin[split_pin.index("GPIO") :])
|
|
adc_instance, adc_channel = name_part.split("_")
|
|
|
|
try:
|
|
adc_channel = int(adc_channel[2:])
|
|
except ValueError:
|
|
continue
|
|
pin_to_analog[pin_name] = (adc_instance, adc_channel)
|
|
|
|
# Find USB pins
|
|
usb_pins = []
|
|
all_pins = set()
|
|
for pin in signal_root.iter("pin"):
|
|
pin_name = pin.get("name")
|
|
if SKIP_LPSR and "LPSR" in pin_name:
|
|
continue
|
|
all_pins.add(pin_name)
|
|
if not pin_name.startswith("USB_OTG"):
|
|
continue
|
|
if not pin_name.endswith(("DN", "DP")):
|
|
continue
|
|
usb_pins.append(pin_name)
|
|
|
|
# Find peripherals
|
|
all_peripherals = {}
|
|
for peripheral in signal_root.iter("peripheral"):
|
|
ptype = peripheral.get("peripheral_type")
|
|
if ptype not in all_peripherals:
|
|
all_peripherals[ptype] = []
|
|
all_peripherals[ptype].append(peripheral.get("id"))
|
|
|
|
print(svd_fn)
|
|
tree = ET.parse(svd_fn)
|
|
root = tree.getroot()
|
|
pin_number = 0
|
|
last_gpio_base = None
|
|
mux_register_base = None
|
|
|
|
pins_h = [
|
|
copyright,
|
|
autogen_warning,
|
|
"#pragma once",
|
|
"",
|
|
"#define FORMAT_PIN(pin_name) extern const mcu_pin_obj_t pin_##pin_name;",
|
|
'#include "pin_names.h"',
|
|
"#undef FORMAT_PIN",
|
|
]
|
|
pins_c = [
|
|
copyright,
|
|
autogen_warning,
|
|
'#include "py/obj.h"',
|
|
'#include "py/mphal.h"',
|
|
'#include "mimxrt10xx/pins.h"',
|
|
"",
|
|
]
|
|
pin_names_h = [copyright, "", "// define FORMAT_PIN(pin_name) and then include this file."]
|
|
mux_registers_by_pin = {}
|
|
peripheral_inputs = {}
|
|
pwm_outputs = []
|
|
for register in root.iter("register"):
|
|
name = register.find("name").text
|
|
if name.endswith("SELECT_INPUT"):
|
|
name_split = name.split("_")
|
|
instance = name_split[0]
|
|
signal = "_".join(name_split[1:-2])
|
|
signal = SIGNAL_RENAME.get(signal, signal)
|
|
if instance not in peripheral_inputs:
|
|
peripheral_inputs[instance] = {}
|
|
if signal not in peripheral_inputs[instance]:
|
|
peripheral_inputs[instance][signal] = {}
|
|
for evalue in register.iter("enumeratedValue"):
|
|
ename = evalue.find("name").text.strip("_")
|
|
if "_ALT" in ename:
|
|
pin_name, alt = ename.rsplit("_", maxsplit=1)
|
|
else:
|
|
pin_name = ename
|
|
alt = evalue.find("description").text.rsplit(maxsplit=1)[1]
|
|
if SKIP_LPSR and "LPSR" in pin_name:
|
|
continue
|
|
alt = int(alt[3:])
|
|
value = int(evalue.find("value").text, 0)
|
|
peripheral_inputs[instance][signal][pin_name] = [alt, name, value]
|
|
# Mux registers come before PAD registers.
|
|
elif name.startswith("SW_MUX_CTL_PAD_GPIO"):
|
|
address_offset = int(register.find("addressOffset").text, 16)
|
|
if mux_register_base is None:
|
|
mux_register_base = address_offset
|
|
|
|
split_pin = name.split("_")
|
|
pin_name = "_".join(split_pin[4:])
|
|
if pin_name not in all_pins:
|
|
print("skip", pin_name)
|
|
continue
|
|
gpio_base = "_".join(split_pin[4:-1])
|
|
|
|
mux_registers_by_pin[pin_name] = register
|
|
|
|
if last_gpio_base != gpio_base:
|
|
pin_names_h.append("")
|
|
last_gpio_base = gpio_base
|
|
|
|
pin_number += 1
|
|
|
|
pin_names_h.append(f"FORMAT_PIN({pin_name})")
|
|
elif name.startswith("SW_PAD_CTL_PAD_GPIO"):
|
|
split_pin = name.split("_")
|
|
pin_name = "_".join(split_pin[4:])
|
|
if pin_name not in all_pins:
|
|
continue
|
|
mux_register = mux_registers_by_pin[pin_name]
|
|
mux_reset = int(mux_register.find("resetValue").text, 16)
|
|
|
|
pad_reset = int(register.find("resetValue").text, 16)
|
|
|
|
# Look through alt modes to find GPIO.
|
|
mux_field = mux_register.find("fields").find("field")
|
|
assert mux_field.find("name").text == "MUX_MODE"
|
|
for alt in mux_field.iter("enumeratedValue"):
|
|
desc = alt.find("description").text
|
|
if "FLEXPWM" in desc:
|
|
desc_split = desc.split()
|
|
alt = desc_split[3]
|
|
connection = desc_split[6]
|
|
pwm_instance = int(connection[7:8])
|
|
if connection.count("_") == 1:
|
|
# Form: FLEXPWM#_PWMC##
|
|
channel = connection[-3:-2]
|
|
module = int(connection[-2:])
|
|
else: # two _
|
|
# Form: FLEXPWM#_PWM#_C
|
|
channel = connection[-1:]
|
|
module = int(connection[-3:-2])
|
|
pwm_outputs.append((pwm_instance, module, channel, connection, pin_name))
|
|
elif "GPIO" in desc:
|
|
alt_name = desc.split()[-4]
|
|
# The 117x has a GPIO mux between GPIOn and CM7_GPIOn. For now,
|
|
# we use the the slow, default GPIOn.
|
|
if alt_name.startswith("GPIO_MUX"):
|
|
alt_name = alt_name.replace("GPIO_MUX", "GPIO")
|
|
gpio_instance, gpio_number = alt_name.split("_")
|
|
if gpio_instance == "GPIOMUX":
|
|
gpio_instance = "GPIO1"
|
|
gpio_number = int(gpio_number[2:])
|
|
else:
|
|
desc_split = desc.split()
|
|
alt = desc_split[3]
|
|
connection = desc_split[6]
|
|
alt = int(alt[3:])
|
|
if "_" not in connection:
|
|
print("skipping", pin_name, connection)
|
|
continue
|
|
instance, signal = connection.split("_", maxsplit=1)
|
|
signal = SIGNAL_RENAME.get(signal, signal)
|
|
if instance not in peripheral_inputs:
|
|
peripheral_inputs[instance] = {}
|
|
if signal not in peripheral_inputs[instance]:
|
|
peripheral_inputs[instance][signal] = {}
|
|
peripheral_inputs[instance][signal][pin_name] = [alt, None, 0]
|
|
|
|
if pin_name in pin_to_analog:
|
|
adc_instance, adc_channel = pin_to_analog[pin_name]
|
|
else:
|
|
adc_instance = "NO_ADC"
|
|
adc_channel = 0
|
|
|
|
pins_c.append(
|
|
f"const mcu_pin_obj_t pin_{pin_name} = PIN({gpio_instance}, {gpio_number}, {pin_name}, {adc_instance}, {adc_channel}, 0x{mux_reset:08X}, 0x{pad_reset:08X});"
|
|
)
|
|
|
|
if usb_pins:
|
|
pins_c.append("")
|
|
|
|
for pin_name in sorted(usb_pins):
|
|
pin_names_h.append(f"FORMAT_PIN({pin_name})")
|
|
pins_c.append(f"const mcu_pin_obj_t pin_{pin_name} = {{ {{ &mcu_pin_type }}, }};")
|
|
|
|
pin_names_h.append("")
|
|
pins_c.append("")
|
|
|
|
pins_h.append("")
|
|
|
|
pins_h.append("// Pads can be reset. Other pins like USB cannot be.")
|
|
pins_h.append(f"#define PAD_COUNT ({pin_number})")
|
|
pins_h.append(f"#define PIN_COUNT (PAD_COUNT + {len(usb_pins)})")
|
|
pins_h.append(f"extern const mcu_pin_obj_t mcu_pin_list[PIN_COUNT];")
|
|
pins_h.append("")
|
|
|
|
out_dir.mkdir(exist_ok=True)
|
|
|
|
(out_dir / "pin_names.h").write_text("\n".join(pin_names_h))
|
|
(out_dir / "pins.h").write_text("\n".join(pins_h))
|
|
(out_dir / "pins.c").write_text("\n".join(pins_c))
|
|
|
|
periph_h = [copyright, autogen_warning, "#pragma once"]
|
|
periph_c = [
|
|
copyright,
|
|
autogen_warning,
|
|
'#include "py/obj.h"',
|
|
'#include "py/mphal.h"',
|
|
'#include "mimxrt10xx/periph.h"',
|
|
"",
|
|
]
|
|
|
|
for ptype in SIGNALS:
|
|
instances = all_peripherals[ptype]
|
|
short_name = ptype.lower()
|
|
if short_name.startswith("lp"):
|
|
short_name = short_name[2:]
|
|
# Only one MQS exists and it is related to SAI3
|
|
if ptype != "MQS":
|
|
periph_h.append(
|
|
f"extern {ptype}_Type *const mcu_{short_name}_banks[{len(instances)}];"
|
|
)
|
|
joined_instances = ", ".join(instances)
|
|
periph_c.append(
|
|
f"{ptype}_Type *const mcu_{short_name}_banks[{len(instances)}] = {{ {joined_instances} }};"
|
|
)
|
|
periph_c.append("")
|
|
for signal in SIGNALS[ptype]:
|
|
pin_count = 0
|
|
for instance in instances:
|
|
if instance not in peripheral_inputs or signal not in peripheral_inputs[instance]:
|
|
continue
|
|
pin_count += len(peripheral_inputs[instance][signal])
|
|
periph_h.append(
|
|
f"extern const mcu_periph_obj_t mcu_{short_name}_{signal.lower()}_list[{pin_count}];"
|
|
)
|
|
periph_c.append(
|
|
f"const mcu_periph_obj_t mcu_{short_name}_{signal.lower()}_list[{pin_count}] = {{"
|
|
)
|
|
for instance in instances:
|
|
if instance not in peripheral_inputs or signal not in peripheral_inputs[instance]:
|
|
continue
|
|
# MQS is tied to SAI3
|
|
if instance == "MQS":
|
|
instance_number = 3
|
|
else:
|
|
instance_number = int(instance[len(ptype) :])
|
|
if instance_number > 1:
|
|
periph_c.append("")
|
|
pins = peripheral_inputs[instance][signal]
|
|
pin_names = list(pins.keys())
|
|
pin_names.sort(key=lambda x: pins[x][-1])
|
|
for pin_name in pin_names:
|
|
alt, select_input, input_value = pins[pin_name]
|
|
if select_input:
|
|
select_input = f"kIOMUXC_{select_input}"
|
|
else:
|
|
select_input = "0"
|
|
periph_c.append(
|
|
f" PERIPH_PIN({instance_number}, {alt}, {select_input}, {input_value}, &pin_{pin_name}),"
|
|
)
|
|
periph_c.append(f"}};")
|
|
periph_c.append(f"")
|
|
periph_h.append("")
|
|
|
|
pwm_outputs.sort(key=lambda x: x[:3])
|
|
periph_c.append(f"const mcu_pwm_obj_t mcu_pwm_list[{len(pwm_outputs)}] = {{")
|
|
periph_h.append(f"extern const mcu_pwm_obj_t mcu_pwm_list[{len(pwm_outputs)}];")
|
|
last_channel = None
|
|
for pwm_instance, module, channel, connection, pin_name in pwm_outputs:
|
|
this_channel = (pwm_instance, module, channel)
|
|
if last_channel is not None and last_channel != this_channel:
|
|
periph_c.append("")
|
|
last_channel = this_channel
|
|
periph_c.append(
|
|
f" PWM_PIN(PWM{pwm_instance}, kPWM_Module_{module}, kPWM_Pwm{channel}, IOMUXC_{pin_name}_{connection}, &pin_{pin_name}),"
|
|
)
|
|
periph_c.append(f"}};")
|
|
periph_c.append("")
|
|
|
|
periph_h.append("")
|
|
|
|
(out_dir / "periph.h").write_text("\n".join(periph_h))
|
|
(out_dir / "periph.c").write_text("\n".join(periph_c))
|