You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

133 lines
4.9 KiB

#!/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()