Files
micropython/ports/rp2/boards/make-pins.py
Jim Mussared 4bd6ec9ae4 tools/boardgen.py: Add initial implementation of a common make-pins.py.
For now, this implements the functionality required for esp32 and rp2,
including support for numeric pins, rp2 alternate functions, and rp2
extended pins.

This also updates the rp2 port to use the same structure for pins.h and
pins.csv as for esp32, and moves the pin definitions directly into the
table (rather than having a table of pointers), which is a small code size
improvement.

Support for "hidden" pins in pins.csv is added (matching the stm32
implementation).

This work was funded through GitHub Sponsors.

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

134 lines
4.9 KiB
Python
Executable File

#!/usr/bin/env python
"""Creates the pin file for the RP2."""
import os
import re
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../../../tools"))
import boardgen
# This is NUM_BANK0_GPIOS. Pin indices are 0 to 29 (inclusive).
NUM_GPIOS = 30
# Up to 10 additional extended pins (e.g. via the wifi chip).
NUM_EXT_GPIOS = 10
class Rp2Pin(boardgen.Pin):
def __init__(self, cpu_pin_name):
super().__init__(cpu_pin_name)
self._afs = []
if self.name().startswith("EXT_"):
self._index = None
self._ext_index = int(self.name()[8:]) # "EXT_GPIOn"
else:
self._index = int(self.name()[4:]) # "GPIOn"
self._ext_index = None
# Required by NumericPinGenerator.
def index(self):
return self._index
# Use the PIN() macro defined in rp2_prefix.c for defining the pin
# objects.
def definition(self):
if self._index is not None:
return "PIN({:d}, GPIO{:d}, 0, {:d}, pin_GPIO{:d}_af)".format(
self._index, self._index, len(self._afs), self.index()
)
else:
return "PIN({:d}, EXT_GPIO{:d}, 1, 0, NULL)".format(self._ext_index, self._ext_index)
# External pins need to be mutable (because they track the output state).
def is_const(self):
return self._index is not None
# Add conditional macros only around the external pins based on how many
# are enabled.
def enable_macro(self):
if self._ext_index is not None:
return "(MICROPY_HW_PIN_EXT_COUNT > {:d})".format(self._ext_index)
def add_af(self, af_idx, _af_name, af):
if self._index is None:
raise boardgen.PinGeneratorError(
"Cannot add AF for ext pin '{:s}'".format(self.name())
)
# <af><unit>_<pin>
m = re.match("([A-Z][A-Z0-9][A-Z]+)(([0-9]+)(_.*)?)?", af)
af_fn = m.group(1)
af_unit = int(m.group(3)) if m.group(3) is not None else 0
if af_fn == "PIO":
# Pins can be either PIO unit (unlike, say, I2C where a
# pin can only be I2C0 _or_ I2C1, both sharing the same AF
# index), so each PIO unit has a distinct AF index.
af_fn = "{:s}{:d}".format(af_fn, af_unit)
self._afs.append((af_idx + 1, af_fn, af_unit, af))
# This will be called at the start of the output (after the prefix). Use
# it to emit the af objects (via the AF() macro in rp2_prefix.c).
def print_source(self, out_source):
if self._index is not None:
print(
"const machine_pin_af_obj_t pin_GPIO{:d}_af[] = {{".format(self.index()),
file=out_source,
)
for af_idx, af_fn, af_unit, af in self._afs:
print(
" AF({:d}, {:4s}, {:d}), // {:s}".format(af_idx, af_fn, af_unit, af),
file=out_source,
)
print("};", file=out_source)
print(file=out_source)
# rp2 cpu names must be "GPIOn" or "EXT_GPIOn".
@staticmethod
def validate_cpu_pin_name(cpu_pin_name):
boardgen.Pin.validate_cpu_pin_name(cpu_pin_name)
if cpu_pin_name.startswith("GPIO") and cpu_pin_name[4:].isnumeric():
if not (0 <= int(cpu_pin_name[4:]) < NUM_GPIOS):
raise boardgen.PinGeneratorError("Unknown cpu pin '{}'".format(cpu_pin_name))
elif cpu_pin_name.startswith("EXT_GPIO") and cpu_pin_name[8:].isnumeric():
if not (0 <= int(cpu_pin_name[8:]) < NUM_EXT_GPIOS):
raise boardgen.PinGeneratorError("Unknown ext pin '{}'".format(cpu_pin_name))
else:
raise boardgen.PinGeneratorError(
"Invalid cpu pin name '{}', must be 'GPIOn' or 'EXT_GPIOn'".format(cpu_pin_name)
)
class Rp2PinGenerator(boardgen.NumericPinGenerator):
def __init__(self):
# Use custom pin type above, and also enable the --af-csv argument.
super().__init__(
pin_type=Rp2Pin,
enable_af=True,
)
# Pre-define the pins (i.e. don't require them to be listed in pins.csv).
for i in range(NUM_GPIOS):
self.add_cpu_pin("GPIO{}".format(i))
for i in range(NUM_EXT_GPIOS):
self.add_cpu_pin("EXT_GPIO{}".format(i))
# Provided by pico-sdk.
def cpu_table_size(self):
return "NUM_BANK0_GPIOS"
# Only use pre-defined cpu pins (do not let board.csv create them).
def find_pin_by_cpu_pin_name(self, cpu_pin_name, create=True):
return super().find_pin_by_cpu_pin_name(cpu_pin_name, create=False)
# NumericPinGenerator doesn't include the cpu dict by default (only the
# board dict), so add that to the output for rp2.
def print_source(self, out_source):
super().print_source(out_source)
self.print_cpu_locals_dict(out_source)
if __name__ == "__main__":
Rp2PinGenerator().main()