Jim Mussared c0b64a3f23 mimxrt/boards/make-pins.py: Update to use tools/boardgen.py.
Minor change to remove support for using numeric IDs for machine.Pin.  This
was previously based on the index of the pin in the board csv, but this is
different (and incompatible) with other ports.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 14:18:54 +11:00

223 lines
10 KiB
Python

#!/usr/bin/env python
from collections import defaultdict
import os
import re
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../../../tools"))
import boardgen
IOMUX_REGEXS = [
r"IOMUXC_(?P<pin>GPIO_SD_B\d_\d\d)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_(?P<pin>GPIO_AD_B\d_\d\d)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_(?P<pin>GPIO_EMC_\d\d)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_(?P<pin>GPIO_B\d_\d\d)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_(?P<pin>GPIO_\d\d)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_(?P<pin>GPIO_AD_\d\d)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_(?P<pin>GPIO_SD_\d\d)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_(?P<pin>GPIO_EMC_B\d_\d\d)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_(?P<pin>GPIO_DISP_B\d_\d\d)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_(?P<pin>GPIO_LPSR_\d\d)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_[SNVS_]*(?P<pin>WAKEUP[_DIG]*)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_[SNVS_]*(?P<pin>PMIC_ON_REQ[_DIG]*)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_[SNVS_]*(?P<pin>PMIC_STBY_REQ[_DIG]*)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_(?P<pin>GPIO_SNVS_\d\d_DIG)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
]
SUPPORTED_AF_FNS = {"GPIO", "USDHC", "FLEXPWM", "TMR"}
class MimxrtPin(boardgen.Pin):
def __init__(self, cpu_pin_name):
super().__init__(cpu_pin_name)
self._afs = []
self._adc_fns = []
# Called for each AF defined in the csv file for this pin.
def add_af(self, af_idx, af_name, af):
# mimxrt-specific: Any pin in the af.csv is implicitly part of the board
# pins.csv and will therefore be in the Pin.cpu dict. This is
# equivalent to adding `,CPUNAME` to the board.csv for every pin in the
# af.csv.
self._available = True
if af_name == "ALT5":
m = re.match("GPIO([0-9]+)_IO([0-9]+)", af)
self._port = int(m.group(1))
self._pin = int(m.group(2))
if af_name.startswith("ALT"):
instance = af.split("_")[0]
fn = re.match("^([A-Z][A-Z0-9]+[A-Z])[0-9]*$", instance).group(1)
if fn not in SUPPORTED_AF_FNS:
return
iomux_config = self._generator._iomux_pin_config[self.name()]
input_reg = iomux_config[af_idx]["inputRegister"].strip("U")
input_daisy = int(iomux_config[af_idx]["inputDaisy"].strip("U"), 16)
self._afs.append((af_idx, input_reg, input_daisy, instance, fn, af))
elif af_name == "ADC":
adc_regex = r"ADC(?P<instance>\d*)_IN(?P<channel>\d*)"
lpadc_regex = r"ADC(?P<instance>\d*)_CH(?P<channel>\d*)" # LPADC for MIMXRT11xx chips
matches = re.finditer(adc_regex, af, re.MULTILINE)
for match in matches:
self._adc_fns.append(
(int(match.group("instance")), int(match.group("channel")), "ADC")
)
matches = re.finditer(lpadc_regex, af, re.MULTILINE)
for match in matches:
self._adc_fns.append(
(int(match.group("instance")), int(match.group("channel")), "LPADC")
)
# Use the PIN() macro defined in samd_prefix.c for defining the pin
# objects.
def definition(self):
if "_LPSR_" in self.name():
macro = "PIN_LPSR"
elif (
"_SNVS_" in self.name()
or self.name().startswith("PMIC_")
or self.name().startswith("WAKEUP")
):
macro = "PIN_SNVS"
else:
macro = "PIN"
# PIN(_name, _gpio, _pin, _af_list, _adc_list_len, _adc_list)
return "{:s}({:s}, GPIO{:d}, {:d}, pin_{:s}_af, {:d}, {:s})".format(
macro,
self.name(),
self._port,
self._pin,
self.name(),
len(self._adc_fns),
"pin_{:s}_adc".format(self.name()) if self._adc_fns else "NULL",
)
# This will be called at the start of the output (after the prefix) for
# each pin. Use it to emit the af and adc objects.
def print_source(self, out_source):
print(
"static const machine_pin_af_obj_t pin_{:s}_af[] = {{".format(self.name()),
file=out_source,
)
for af_idx, input_reg, input_daisy, instance, _fn, af in self._afs:
print(
" PIN_AF({:s}, PIN_AF_MODE_ALT{:d}, {:d}, {:s}, {:s}, {:s}),".format(
af, af_idx, input_daisy, instance, input_reg, "0x10B0U"
),
file=out_source,
)
print("};", file=out_source)
print(file=out_source)
if self._adc_fns:
print(
"static const machine_pin_adc_obj_t pin_{:s}_adc[] = {{".format(self.name()),
file=out_source,
)
for instance, channel, peripheral in self._adc_fns:
print(
" PIN_ADC({:s}{:d}, {:d}),".format(peripheral, instance, channel),
file=out_source,
)
print("};", file=out_source)
# mimxrt cpu names must be "GPIO_<funcs>_<num>", with zero-prefixed two-digit <num>.
@staticmethod
def validate_cpu_pin_name(cpu_pin_name):
boardgen.Pin.validate_cpu_pin_name(cpu_pin_name)
if not re.match(
"^((GPIO_((SNVS|EMC|LPSR|DISP)_)?([AS]D_)?(B[012]_)?[0-9][0-9])|WAKEUP|PMIC_(ON|STBY)_REQ)(_DIG)?$",
cpu_pin_name,
):
raise boardgen.PinGeneratorError("Invalid cpu pin name '{}'".format(cpu_pin_name))
class MimxrtPinGenerator(boardgen.PinGenerator):
def __init__(self):
# Use custom pin type above, and also enable the --af-csv argument so
# that add_af gets called on each pin.
super().__init__(
pin_type=MimxrtPin,
enable_af=True,
)
self._iomux_pin_config = {}
# Load the iomux configuration from fsl_iomuxc.h.
def load_iomux_header(self, iomux_filename):
with open(iomux_filename, "r") as ipt:
input_str = ipt.read()
for regex in IOMUX_REGEXS:
matches = re.finditer(regex, input_str, re.MULTILINE)
for match in matches:
if match.group("pin") not in self._iomux_pin_config:
self._iomux_pin_config[match.group("pin")] = {
int((match.groupdict()["muxMode"].strip("U")), 16): match.groupdict()
}
else:
self._iomux_pin_config[match.group("pin")][
int((match.groupdict()["muxMode"].strip("U")), 16)
] = match.groupdict()
# Also load the iomux header.
def load_inputs(self, out_source):
if self.args.iomux_header:
print("// --iomux-header {:s}".format(self.args.iomux_header), file=out_source)
self.load_iomux_header(self.args.iomux_header)
super().load_inputs(out_source)
# Provide a macro for each supported (pin,af) that can be used to
# initialise a struct containing a machine_pin_obj_t* and the
# corresponding af for that pin. e.g. A mimxrt_sdcard_pin_t instance can
# be initialised with GPIO_SD_B0_00_USDHC1_CMD which tells it how to get
# the CMD pin of the USDHC1 function on the GPIO_SD_B0_00 pin.
def print_module_instances(self, out_header):
print(file=out_header)
for match_fn in ("USDHC", "FLEXPWM", "TMR"):
module_instances = defaultdict(list)
for pin in self.available_pins():
for i, (_af_idx, _input_reg, _input_daisy, instance, fn, af) in enumerate(
pin._afs
):
if fn == match_fn:
module_instances[instance].append(
"#define {:s}_{:s} pin_{:s}, {:d}".format(
pin.name(), af, pin.name(), i
)
)
for k, v in module_instances.items():
print("// {:s}".format(k), file=out_header)
print("#define {:s}_AVAIL (1)".format(k), file=out_header)
if match_fn == "FLEXPWM":
print("#define {:s} {:s}".format(k, k[-4:]), file=out_header)
for i in v:
print(i, file=out_header)
# Override to also print the module instances.
def print_header(self, out_header):
super().print_header(out_header)
self.print_module_instances(out_header)
# Override the default implementation just to change the default arguments
# (extra header row, skip first column).
def parse_af_csv(self, filename):
return super().parse_af_csv(filename, header_rows=1, pin_col=0, af_col=1)
# We need to know the mcu to emit the correct AF list.
def extra_args(self, parser):
parser.add_argument("--iomux-header")
if __name__ == "__main__":
MimxrtPinGenerator().main()