diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index 1bedc58101..88971a5c90 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -131,6 +131,7 @@ set(MICROPY_SOURCE_PORT usbd.c msc_disk.c mbedtls/mbedtls_port.c + ${CMAKE_BINARY_DIR}/pins_${MICROPY_BOARD}.c ) set(MICROPY_SOURCE_QSTR @@ -153,6 +154,7 @@ set(MICROPY_SOURCE_QSTR ${PROJECT_SOURCE_DIR}/modutime.c ${PROJECT_SOURCE_DIR}/rp2_flash.c ${PROJECT_SOURCE_DIR}/rp2_pio.c + ${CMAKE_BINARY_DIR}/pins_${MICROPY_BOARD}.c ) set(PICO_SDK_COMPONENTS @@ -257,14 +259,14 @@ if (MICROPY_PY_NETWORK_CYW43) ) endif() - list(APPEND MICROPY_SOURCE_EXTMOD - ${MICROPY_DIR}/extmod/network_cyw43.c - ) - list(APPEND MICROPY_SOURCE_PORT machine_pin_cyw43.c ) + list(APPEND MICROPY_SOURCE_EXTMOD + ${MICROPY_DIR}/extmod/network_cyw43.c + ) + target_link_libraries(${MICROPY_TARGET} cyw43_driver_picow cmsis_core @@ -439,3 +441,37 @@ endforeach() # Include the main MicroPython cmake rules. include(${MICROPY_DIR}/py/mkrules.cmake) + +set(MICROPY_BOARDS_DIR "${MICROPY_PORT_DIR}/boards") +set(GEN_PINS_AF_CSV "${MICROPY_BOARDS_DIR}/rp2_af.csv") +set(GEN_PINS_PREFIX "${MICROPY_BOARDS_DIR}/rp2_prefix.c") +set(GEN_PINS_MKPINS "${MICROPY_BOARDS_DIR}/make-pins.py") +set(GEN_PINS_SRC "${CMAKE_BINARY_DIR}/pins_${MICROPY_BOARD}.c") +set(GEN_PINS_HDR "${MICROPY_GENHDR_DIR}/pins.h") +set(GEN_PINS_QSTR "${CMAKE_BINARY_DIR}/pins_qstr.h") +set(GEN_PINS_AF_CONST "${MICROPY_GENHDR_DIR}/pins_af_const.h") +set(GEN_PINS_AF_PY "${CMAKE_BINARY_DIR}/pins_af.py") + +if(EXISTS "${MICROPY_BOARDS_DIR}/${MICROPY_BOARD}/pins.csv") + set(GEN_PINS_BOARD_CSV "${MICROPY_BOARDS_DIR}/${MICROPY_BOARD}/pins.csv") + set(GEN_PINS_CSV_ARG --board "${GEN_PINS_BOARD_CSV}") +endif() + +target_sources(${MICROPY_TARGET} PRIVATE + ${GEN_PINS_HDR} +) + +# Generate pins +add_custom_command( + OUTPUT ${GEN_PINS_HDR} ${GEN_PINS_SRC} ${GEN_PINS_QSTR} + COMMAND ${Python3_EXECUTABLE} ${GEN_PINS_MKPINS} ${GEN_PINS_CSV_ARG} --af ${GEN_PINS_AF_CSV} --prefix ${GEN_PINS_PREFIX} + --hdr ${GEN_PINS_HDR} --qstr ${GEN_PINS_QSTR} --af-const ${GEN_PINS_AF_CONST} --af-py ${GEN_PINS_AF_PY} > ${GEN_PINS_SRC} + DEPENDS + ${GEN_PINS_AF_CSV} + ${GEN_PINS_BOARD_CSV} + ${GEN_PINS_MKPINS} + ${GEN_PINS_PREFIX} + ${MICROPY_MPVERSION} + VERBATIM + COMMAND_EXPAND_LISTS +) diff --git a/ports/rp2/boards/make-pins.py b/ports/rp2/boards/make-pins.py new file mode 100755 index 0000000000..55e7ebe01f --- /dev/null +++ b/ports/rp2/boards/make-pins.py @@ -0,0 +1,428 @@ +#!/usr/bin/env python +"""Creates the pin file for the RP2.""" + +from __future__ import print_function + +import argparse +import sys +import csv +import re + +SUPPORTED_FN = { + "SPI": ["TX", "RX", "SCK", "CS"], + "UART": ["TX", "RX", "CTS", "RTS"], + "I2C": ["SCL", "SDA"], + "PWM": ["A", "B"], + "SIO": [""], + "PIO0": [""], + "PIO1": [""], + "GPCK": ["GPIN0", "GPOUT0", "GPIN1", "GPOUT1", "GPOUT2", "GPOUT3"], + "USB": ["OVCUR_DET", "VBUS_DET", "VBUS_EN"], +} + + +def parse_pin(name_str): + """Parses a string and returns a pin number.""" + if len(name_str) < 2: + raise ValueError("Expecting pin name to be at least 2 charcters.") + if not name_str.startswith("GPIO") and not name_str.startswith("EXT_GPIO"): + raise ValueError("Expecting pin name to start with EXT_/GPIO") + return int(re.findall(r"\d+$", name_str)[0]) + + +def split_name_num(name_num): + num = None + for num_idx in range(len(name_num) - 1, -1, -1): + if not name_num[num_idx].isdigit(): + name = name_num[0 : num_idx + 1] + num_str = name_num[num_idx + 1 :] + if len(num_str) > 0: + num = int(num_str) + break + if name == "PIO": + name += str(num) + return name, num + + +class AlternateFunction(object): + """Holds the information associated with a pins alternate function.""" + + def __init__(self, idx, af_str): + self.idx = idx + self.af_str = af_str + + self.func = "" + self.fn_num = None + self.pin_type = "" + self.supported = False + + af_words = af_str.split("_", 1) + self.func, self.fn_num = split_name_num(af_words[0]) + if len(af_words) > 1: + self.pin_type = af_words[1] + if self.func in SUPPORTED_FN: + pin_types = SUPPORTED_FN[self.func] + if self.pin_type in pin_types: + self.supported = True + + def is_supported(self): + return self.supported + + def ptr(self): + """Returns the numbered function (i.e. USART6) for this AF.""" + if self.fn_num is None: + return self.func + return "{:s}{:d}".format(self.func, self.fn_num) + + def mux_name(self): + return "AF{:d}_{:s}".format(self.idx, self.ptr()) + + def print(self): + """Prints the C representation of this AF.""" + if self.supported: + print(" AF", end="") + else: + print(" //", end="") + fn_num = self.fn_num + if fn_num is None: + fn_num = 0 + print("({:d}, {:4s}, {:d}), // {:s}".format(self.idx, self.func, fn_num, self.af_str)) + + def qstr_list(self): + return [self.mux_name()] + + +class Pin(object): + """Holds the information associated with a pin.""" + + def __init__(self, pin, is_ext=False): + self.pin = pin + self.alt_fn = [] + self.alt_fn_count = 0 + self.is_board = False + self.is_ext = is_ext + + def cpu_pin_name(self): + return "{:s}GPIO{:d}".format("EXT_" if self.is_ext else "", self.pin) + + def is_board_pin(self): + return self.is_board + + def set_is_board_pin(self): + self.is_board = True + + def parse_af(self, af_idx, af_strs_in): + if len(af_strs_in) == 0: + return + # If there is a slash, then the slash separates 2 aliases for the + # same alternate function. + af_strs = af_strs_in.split("/") + for af_str in af_strs: + alt_fn = AlternateFunction(af_idx, af_str) + self.alt_fn.append(alt_fn) + if alt_fn.is_supported(): + self.alt_fn_count += 1 + + def alt_fn_name(self, null_if_0=False): + if null_if_0 and self.alt_fn_count == 0: + return "NULL" + return "pin_{:s}_af".format(self.cpu_pin_name()) + + def print(self): + if self.is_ext: + print("#if (MICROPY_HW_PIN_EXT_COUNT > {:d})".format(self.pin)) + + if self.alt_fn_count == 0: + print("// ", end="") + print("const machine_pin_af_obj_t {:s}[] = {{".format(self.alt_fn_name())) + for alt_fn in self.alt_fn: + alt_fn.print() + if self.alt_fn_count == 0: + print("// ", end="") + print("};") + print("") + print( + "{:s}machine_pin_obj_t pin_{:s} = PIN({:d}, {:s}, {:d}, {:d}, {:s});".format( + "" if self.is_ext else "const ", + self.cpu_pin_name(), + self.pin, + self.cpu_pin_name(), + self.is_ext, + self.alt_fn_count, + self.alt_fn_name(null_if_0=True), + ) + ) + if self.is_ext: + print("#endif") + print("") + + def print_header(self, hdr_file): + n = self.cpu_pin_name() + hdr_file.write( + "extern{:s}machine_pin_obj_t pin_{:s};\n".format(" " if self.is_ext else " const ", n) + ) + if self.alt_fn_count > 0: + hdr_file.write("extern const machine_pin_af_obj_t pin_{:s}_af[];\n".format(n)) + + def qstr_list(self): + result = [] + for alt_fn in self.alt_fn: + if alt_fn.is_supported(): + result += alt_fn.qstr_list() + return result + + +class NamedPin(object): + def __init__(self, name, pin): + self._name = name + self._pin = pin + + def pin(self): + return self._pin + + def name(self): + return self._name + + +class Pins(object): + def __init__(self): + self.cpu_pins = [] # list of NamedPin objects + self.board_pins = [] # list of NamedPin objects + self.ext_pins = [] # list of NamedPin objects + for i in range(0, 10): + self.ext_pins.append(NamedPin("EXT_GPIO{:d}".format(i), Pin(i, True))) + + def find_pin(self, pin_name): + for pin in self.cpu_pins: + if pin.name() == pin_name: + return pin.pin() + + for pin in self.ext_pins: + if pin.name() == pin_name: + return pin.pin() + + def parse_af_file(self, filename, pinname_col, af_col): + with open(filename, "r") as csvfile: + rows = csv.reader(csvfile) + for row in rows: + try: + pin_num = parse_pin(row[pinname_col]) + except Exception as e: + # import traceback; traceback.print_exc() + continue + pin = Pin(pin_num) + for af_idx in range(af_col, len(row)): + if af_idx >= af_col: + pin.parse_af(af_idx, row[af_idx]) + self.cpu_pins.append(NamedPin(pin.cpu_pin_name(), pin)) + + def parse_board_file(self, filename): + with open(filename, "r") as csvfile: + rows = csv.reader(csvfile) + for row in rows: + if len(row) == 0 or row[0].startswith("#"): + # Skip empty lines, and lines starting with "#" + continue + if len(row) != 2: + raise ValueError("Expecting two entries in a row") + + cpu_pin_name = row[1] + try: + pin_num = parse_pin(cpu_pin_name) + except: + # import traceback; traceback.print_exc() + continue + pin = self.find_pin(cpu_pin_name) + if pin: + pin.set_is_board_pin() + if row[0]: # Only add board pins that have a name + self.board_pins.append(NamedPin(row[0], pin)) + + def print_table(self, label, named_pins): + print("") + print("const machine_pin_obj_t *machine_pin_{:s}_pins[] = {{".format(label)) + for pin in named_pins: + if not pin.pin().is_ext: + print(" &pin_{},".format(pin.name())) + print("};") + print("") + + def print_named(self, label, named_pins): + print("") + print( + "STATIC const mp_rom_map_elem_t pin_{:s}_pins_locals_dict_table[] = {{".format(label) + ) + for named_pin in named_pins: + pin = named_pin.pin() + if pin.is_ext: + print(" #if (MICROPY_HW_PIN_EXT_COUNT > {:d})".format(pin.pin)) + print( + " {{ MP_ROM_QSTR(MP_QSTR_{:s}), MP_ROM_PTR(&pin_{:s}) }},".format( + named_pin.name(), pin.cpu_pin_name() + ) + ) + if pin.is_ext: + print(" #endif") + + print("};") + print( + "MP_DEFINE_CONST_DICT(pin_{:s}_pins_locals_dict, pin_{:s}_pins_locals_dict_table);".format( + label, label + ) + ) + print("") + + def print(self): + for pin in self.cpu_pins: + pin.pin().print() + + for pin in self.ext_pins: + if pin.pin().is_ext: + pin.pin().print() + + self.print_table("cpu", self.cpu_pins) + self.print_named("cpu", self.cpu_pins + self.ext_pins) + self.print_named("board", self.board_pins) + + def print_header(self, hdr_filename, obj_decls): + with open(hdr_filename, "wt") as hdr_file: + if obj_decls: + for named_pin in self.cpu_pins: + pin = named_pin.pin() + pin.print_header(hdr_file) + for named_pin in self.board_pins: + pin = named_pin.pin() + if pin.is_ext: + pin.print_header(hdr_file) + # provide #define's mapping board to cpu name + for named_pin in self.board_pins: + if named_pin.pin().is_board_pin(): + hdr_file.write( + "#define pin_{:s} pin_{:s}\n".format( + named_pin.name(), named_pin.pin().cpu_pin_name() + ) + ) + + def print_qstr(self, qstr_filename): + with open(qstr_filename, "wt") as qstr_file: + qstr_set = set([]) + for named_pin in self.cpu_pins: + pin = named_pin.pin() + if pin.is_board_pin(): + qstr_set |= set(pin.qstr_list()) + qstr_set |= set([named_pin.name()]) + for named_pin in self.board_pins: + qstr_set |= set([named_pin.name()]) + for qstr in sorted(qstr_set): + print("Q({})".format(qstr), file=qstr_file) + + def print_af_hdr(self, af_const_filename): + with open(af_const_filename, "wt") as af_const_file: + af_hdr_set = set([]) + mux_name_width = 0 + for named_pin in self.cpu_pins: + pin = named_pin.pin() + if pin.is_board_pin(): + for af in pin.alt_fn: + if af.is_supported(): + mux_name = af.mux_name() + af_hdr_set |= set([mux_name]) + if len(mux_name) > mux_name_width: + mux_name_width = len(mux_name) + for mux_name in sorted(af_hdr_set): + key = "MP_OBJ_NEW_QSTR(MP_QSTR_{}),".format(mux_name) + val = "MP_OBJ_NEW_SMALL_INT(GPIO_{})".format(mux_name) + print(" { %-*s %s }," % (mux_name_width + 26, key, val), file=af_const_file) + + def print_af_py(self, af_py_filename): + with open(af_py_filename, "wt") as af_py_file: + print("PINS_AF = (", file=af_py_file) + for named_pin in self.board_pins: + print(" ('%s', " % named_pin.name(), end="", file=af_py_file) + for af in named_pin.pin().alt_fn: + if af.is_supported(): + print("(%d, '%s'), " % (af.idx, af.af_str), end="", file=af_py_file) + print("),", file=af_py_file) + print(")", file=af_py_file) + + +def main(): + parser = argparse.ArgumentParser( + prog="make-pins.py", + usage="%(prog)s [options] [command]", + description="Generate board specific pin file", + ) + parser.add_argument( + "-a", + "--af", + dest="af_filename", + help="Specifies the alternate function file for the chip", + default="rp2_af.csv", + ) + parser.add_argument( + "--af-const", + dest="af_const_filename", + help="Specifies header file for alternate function constants.", + default="build/pins_af_const.h", + ) + parser.add_argument( + "--af-py", + dest="af_py_filename", + help="Specifies the filename for the python alternate function mappings.", + default="build/pins_af.py", + ) + parser.add_argument( + "-b", + "--board", + dest="board_filename", + help="Specifies the board file", + ) + parser.add_argument( + "-p", + "--prefix", + dest="prefix_filename", + help="Specifies beginning portion of generated pins file", + default="rp2_prefix.c", + ) + parser.add_argument( + "-q", + "--qstr", + dest="qstr_filename", + help="Specifies name of generated qstr header file", + default="build/pins_qstr.h", + ) + parser.add_argument( + "-r", + "--hdr", + dest="hdr_filename", + help="Specifies name of generated pin header file", + default="build/pins.h", + ) + args = parser.parse_args(sys.argv[1:]) + + pins = Pins() + + print("// This file was automatically generated by make-pins.py") + print("//") + if args.af_filename: + print("// --af {:s}".format(args.af_filename)) + pins.parse_af_file(args.af_filename, 0, 1) + + if args.board_filename: + print("// --board {:s}".format(args.board_filename)) + pins.parse_board_file(args.board_filename) + + if args.prefix_filename: + print("// --prefix {:s}".format(args.prefix_filename)) + print("") + with open(args.prefix_filename, "r") as prefix_file: + print(prefix_file.read()) + pins.print() + pins.print_header(args.hdr_filename, True) + pins.print_qstr(args.qstr_filename) + pins.print_af_hdr(args.af_const_filename) + pins.print_af_py(args.af_py_filename) + + +if __name__ == "__main__": + main() diff --git a/ports/rp2/boards/rp2_af.csv b/ports/rp2/boards/rp2_af.csv new file mode 100644 index 0000000000..454f7ed2d1 --- /dev/null +++ b/ports/rp2/boards/rp2_af.csv @@ -0,0 +1,31 @@ +Pin,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9 +GPIO0,SPI0_RX,UART0_TX,I2C0_SDA,PWM0_A,SIO,PIO0,PIO1,,USB_OVCUR_DET +GPIO1,SPI0_CS,UART0_RX,I2C0_SCL,PWM0_B,SIO,PIO0,PIO1,,USB_VBUS_DET +GPIO2,SPI0_SCK,UART0_CTS,I2C1_SDA,PWM1_A,SIO,PIO0,PIO1,,USB_VBUS_EN +GPIO3,SPI0_TX,UART0_RTS,I2C1_SCL,PWM1_B,SIO,PIO0,PIO1,,USB_OVCUR_DET +GPIO4,SPI0_RX,UART1_TX,I2C0_SDA,PWM2_A,SIO,PIO0,PIO1,,USB_VBUS_DET +GPIO5,SPI0_CS,UART1_RX,I2C0_SCL,PWM2_B,SIO,PIO0,PIO1,,USB_VBUS_EN +GPIO6,SPI0_SCK,UART1_CTS,I2C1_SDA,PWM3_A,SIO,PIO0,PIO1,,USB_OVCUR_DET +GPIO7,SPI0_TX,UART1_RTS,I2C1_SCL,PWM3_B,SIO,PIO0,PIO1,,USB_VBUS_DET +GPIO8,SPI1_RX,UART1_TX,I2C0_SDA,PWM4_A,SIO,PIO0,PIO1,,USB_VBUS_EN +GPIO9,SPI1_CS,UART1_RX,I2C0_SCL,PWM4_B,SIO,PIO0,PIO1,,USB_OVCUR_DET +GPIO10,SPI1_SCK,UART1_CTS,I2C1_SDA,PWM5_A,SIO,PIO0,PIO1,,USB_VBUS_DET +GPIO11,SPI1_TX,UART1_RTS,I2C1_SCL,PWM5_B,SIO,PIO0,PIO1,,USB_VBUS_EN +GPIO12,SPI1_RX,UART0_TX,I2C0_SDA,PWM6_A,SIO,PIO0,PIO1,,USB_OVCUR_DET +GPIO13,SPI1_CS,UART0_RX,I2C0_SCL,PWM6_B,SIO,PIO0,PIO1,,USB_VBUS_DET +GPIO14,SPI1_SCK,UART0_CTS,I2C1_SDA,PWM7_A,SIO,PIO0,PIO1,,USB_VBUS_EN +GPIO15,SPI1_TX,UART0_RTS,I2C1_SCL,PWM7_B,SIO,PIO0,PIO1,,USB_OVCUR_DET +GPIO16,SPI0_RX,UART0_TX,I2C0_SDA,PWM0_A,SIO,PIO0,PIO1,,USB_VBUS_DET +GPIO17,SPI0_CS,UART0_RX,I2C0_SCL,PWM0_B,SIO,PIO0,PIO1,,USB_VBUS_EN +GPIO18,SPI0_SCK,UART0_CTS,I2C1_SDA,PWM1_A,SIO,PIO0,PIO1,,USB_OVCUR_DET +GPIO19,SPI0_TX,UART0_RTS,I2C1_SCL,PWM1_B,SIO,PIO0,PIO1,,USB_VBUS_DET +GPIO20,SPI0_RX,UART1_TX,I2C0_SDA,PWM2_A,SIO,PIO0,PIO1,GPCK_GPIN0,USB_VBUS_EN +GPIO21,SPI0_CS,UART1_RX,I2C0_SCL,PWM2_B,SIO,PIO0,PIO1,GPCK_GPOUT0,USB_OVCUR_DET +GPIO22,SPI0_SCK,UART1_CTS,I2C1_SDA,PWM3_A,SIO,PIO0,PIO1,GPCK_GPIN1,USB_VBUS_DET +GPIO23,SPI0_TX,UART1_RTS,I2C1_SCL,PWM3_B,SIO,PIO0,PIO1,GPCK_GPOUT1,USB_VBUS_EN +GPIO24,SPI1_RX,UART1_TX,I2C0_SDA,PWM4_A,SIO,PIO0,PIO1,GPCK_GPOUT2,USB_OVCUR_DET +GPIO25,SPI1_CS,UART1_RX,I2C0_SCL,PWM4_B,SIO,PIO0,PIO1,GPCK_GPOUT3,USB_VBUS_DET +GPIO26,SPI1_SCK,UART1_CTS,I2C1_SDA,PWM5_A,SIO,PIO0,PIO1,,USB_VBUS_EN +GPIO27,SPI1_TX,UART1_RTS,I2C1_SCL,PWM5_B,SIO,PIO0,PIO1,,USB_OVCUR_DET +GPIO28,SPI1_RX,UART0_TX,I2C0_SDA,PWM6_A,SIO,PIO0,PIO1,,USB_VBUS_DET +GPIO29,SPI1_CS,UART0_RX,I2C0_SCL,PWM6_B,SIO,PIO0,PIO1,,USB_VBUS_EN diff --git a/ports/rp2/boards/rp2_prefix.c b/ports/rp2/boards/rp2_prefix.c new file mode 100644 index 0000000000..50f2852a8a --- /dev/null +++ b/ports/rp2/boards/rp2_prefix.c @@ -0,0 +1,36 @@ +#include +#include "py/obj.h" +#include "py/mphal.h" +#include "machine_pin.h" + +#define AF(af_idx, af_fn, af_unit) \ + { \ + .base = { &machine_pin_af_type }, \ + .name = MP_QSTR_##af_fn, \ + .idx = (af_idx), \ + .fn = GPIO_FUNC_##af_fn, \ + .unit = (af_unit), \ + } + +#if MICROPY_HW_PIN_EXT_COUNT +#define PIN(_id, _name, _is_ext, _af_num, _af_list) \ + { \ + .base = { &machine_pin_type }, \ + .name = MP_QSTR_##_name, \ + .id = (uint8_t)(_id), \ + .is_ext = (_is_ext), \ + .is_output = false, \ + .last_output_value = 0, \ + .af_num = (_af_num), \ + .af = (_af_list), \ + } +#else +#define PIN(_id, _name, _is_ext, _af_num, _af_list) \ + { \ + .base = { &machine_pin_type }, \ + .name = MP_QSTR_##_name, \ + .id = (uint8_t)(_id), \ + .af_num = (_af_num), \ + .af = (_af_list), \ + } +#endif diff --git a/ports/rp2/machine_pin.c b/ports/rp2/machine_pin.c index 4bce0353f1..3de2eaaed8 100644 --- a/ports/rp2/machine_pin.c +++ b/ports/rp2/machine_pin.c @@ -58,6 +58,26 @@ #define MICROPY_HW_PIN_RESERVED(i) (0) #endif +MP_DEFINE_CONST_OBJ_TYPE( + machine_pin_af_type, + MP_QSTR_PinAF, + MP_TYPE_FLAG_NONE + ); + +MP_DEFINE_CONST_OBJ_TYPE( + pin_cpu_pins_obj_type, + MP_QSTR_cpu, + MP_TYPE_FLAG_NONE, + locals_dict, &pin_cpu_pins_locals_dict + ); + +MP_DEFINE_CONST_OBJ_TYPE( + pin_board_pins_obj_type, + MP_QSTR_board, + MP_TYPE_FLAG_NONE, + locals_dict, &pin_board_pins_locals_dict + ); + typedef struct _machine_pin_irq_obj_t { mp_irq_obj_t base; uint32_t flags; @@ -65,63 +85,7 @@ typedef struct _machine_pin_irq_obj_t { } machine_pin_irq_obj_t; STATIC const mp_irq_methods_t machine_pin_irq_methods; - -STATIC const machine_pin_obj_t machine_pin_obj[NUM_BANK0_GPIOS] = { - {{&machine_pin_type}, 0}, - {{&machine_pin_type}, 1}, - {{&machine_pin_type}, 2}, - {{&machine_pin_type}, 3}, - {{&machine_pin_type}, 4}, - {{&machine_pin_type}, 5}, - {{&machine_pin_type}, 6}, - {{&machine_pin_type}, 7}, - {{&machine_pin_type}, 8}, - {{&machine_pin_type}, 9}, - {{&machine_pin_type}, 10}, - {{&machine_pin_type}, 11}, - {{&machine_pin_type}, 12}, - {{&machine_pin_type}, 13}, - {{&machine_pin_type}, 14}, - {{&machine_pin_type}, 15}, - {{&machine_pin_type}, 16}, - {{&machine_pin_type}, 17}, - {{&machine_pin_type}, 18}, - {{&machine_pin_type}, 19}, - {{&machine_pin_type}, 20}, - {{&machine_pin_type}, 21}, - {{&machine_pin_type}, 22}, - {{&machine_pin_type}, 23}, - {{&machine_pin_type}, 24}, - {{&machine_pin_type}, 25}, - {{&machine_pin_type}, 26}, - {{&machine_pin_type}, 27}, - {{&machine_pin_type}, 28}, - {{&machine_pin_type}, 29}, -}; - -#define LED_PIN_NAME "LED" - -#ifndef MICROPY_HW_PIN_ENABLE_LED_PIN -#if defined(MICROPY_HW_PIN_EXT_LED_PIN_NUM) || defined(PICO_DEFAULT_LED_PIN) -#define MICROPY_HW_PIN_ENABLE_LED_PIN 1 -#endif -#endif - -#if MICROPY_HW_PIN_EXT_COUNT -extern machine_pin_obj_t ext_pin_obj[MICROPY_HW_PIN_EXT_COUNT]; -#endif - -#ifdef MICROPY_HW_PIN_ENABLE_LED_PIN -#ifdef MICROPY_HW_PIN_EXT_LED_PIN_NUM -STATIC machine_pin_obj_t *led_pin_obj = &ext_pin_obj[MICROPY_HW_PIN_EXT_LED_PIN_NUM]; -#elif defined(MICROPY_HW_PIN_LED_PIN_NUM) -STATIC machine_pin_obj_t *led_pin_obj = &machine_pin_obj[MICROPY_HW_PIN_LED_PIN_NUM]; -#elif defined(PICO_DEFAULT_LED_PIN) -STATIC const machine_pin_obj_t *led_pin_obj = &machine_pin_obj[PICO_DEFAULT_LED_PIN]; -#else -#error MICROPY_HW_PIN_ENABLE_LED_PIN defined but there is no LED pin -#endif -#endif +extern const machine_pin_obj_t *machine_pin_cpu_pins[NUM_BANK0_GPIOS]; // Mask with "1" indicating that the corresponding pin is in simulated open-drain mode. uint32_t machine_pin_open_drain_mask; @@ -173,6 +137,35 @@ void machine_pin_deinit(void) { irq_remove_handler(IO_IRQ_BANK0, gpio_irq); } +const machine_pin_obj_t *machine_pin_find_named(const mp_obj_dict_t *named_pins, mp_obj_t name) { + const mp_map_t *named_map = &named_pins->map; + mp_map_elem_t *named_elem = mp_map_lookup((mp_map_t *)named_map, name, MP_MAP_LOOKUP); + if (named_elem != NULL && named_elem->value != NULL) { + return MP_OBJ_TO_PTR(named_elem->value); + } + return NULL; +} + +const machine_pin_af_obj_t *machine_pin_find_alt(const machine_pin_obj_t *pin, uint8_t fn) { + const machine_pin_af_obj_t *af = pin->af; + for (mp_uint_t i = 0; i < pin->af_num; i++, af++) { + if (af->fn == fn) { + return af; + } + } + return NULL; +} + +const machine_pin_af_obj_t *machine_pin_find_alt_by_index(const machine_pin_obj_t *pin, mp_uint_t af_idx) { + const machine_pin_af_obj_t *af = pin->af; + for (mp_uint_t i = 0; i < pin->af_num; i++, af++) { + if (af->idx == af_idx) { + return af; + } + } + return NULL; +} + STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_pin_obj_t *self = self_in; uint funcsel = GPIO_GET_FUNCSEL(self->id); @@ -189,7 +182,7 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin } else { mode_qst = MP_QSTR_ALT; } - mp_printf(print, "Pin(%u, mode=%q", self->id, mode_qst); + mp_printf(print, "Pin(%q, mode=%q", self->name, mode_qst); bool pull_up = false; if (GPIO_IS_PULL_UP(self->id)) { mp_printf(print, ", pull=%q", MP_QSTR_PULL_UP); @@ -203,12 +196,17 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin } } if (funcsel != GPIO_FUNC_SIO) { - mp_printf(print, ", alt=%u", funcsel); + const machine_pin_af_obj_t *af = machine_pin_find_alt_by_index(self, funcsel); + if (af == NULL) { + mp_printf(print, ", alt=%u", funcsel); + } else { + mp_printf(print, ", alt=%q", af->name); + } } } else { #if MICROPY_HW_PIN_EXT_COUNT - mode_qst = self->is_output ? MP_QSTR_OUT : MP_QSTR_IN; - mp_printf(print, "Pin(%s%u, mode=%q", MICROPY_HW_PIN_EXT_PREFIX, self->id, mode_qst); + mode_qst = (self->is_output) ? MP_QSTR_OUT : MP_QSTR_IN; + mp_printf(print, "Pin(%q, mode=%q", self->name, mode_qst); #endif } mp_printf(print, ")"); @@ -231,11 +229,11 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (is_ext_pin(self) && args[ARG_pull].u_obj != mp_const_none) { - mp_raise_ValueError("Pulls are not supported for external pins."); + mp_raise_ValueError("pulls are not supported for external pins"); } if (is_ext_pin(self) && args[ARG_alt].u_int != GPIO_FUNC_SIO) { - mp_raise_ValueError("Alternate functions are not supported for external pins."); + mp_raise_ValueError("alternate functions are not supported for external pins"); } int value = -1; @@ -264,7 +262,11 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_ mp_hal_pin_open_drain(self->id); } else { // Configure alternate function. - gpio_set_function(self->id, args[ARG_alt].u_int); + mp_uint_t af = args[ARG_alt].u_int; + if (machine_pin_find_alt(self, af) == NULL) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid pin af: %d"), af); + } + gpio_set_function(self->id, af); machine_pin_open_drain_mask &= ~(1 << self->id); } } @@ -283,35 +285,29 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_ // constructor(id, ...) mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); - const machine_pin_obj_t *self = NULL; + if (mp_obj_is_str(args[0])) { const char *name = mp_obj_str_get_str(args[0]); - #if MICROPY_HW_PIN_ENABLE_LED_PIN - if (!strcmp(name, LED_PIN_NAME)) { - self = led_pin_obj; - } - #endif - #if MICROPY_HW_PIN_EXT_COUNT - static_assert(MICROPY_HW_PIN_EXT_COUNT < 10, ""); // makes parsing name easy! - if (!self && !strncmp(name, MICROPY_HW_PIN_EXT_PREFIX, strlen(MICROPY_HW_PIN_EXT_PREFIX)) && strlen(name) == strlen(MICROPY_HW_PIN_EXT_PREFIX) + 1) { - int num = name[strlen(MICROPY_HW_PIN_EXT_PREFIX)] - '0'; - if (num < MICROPY_HW_PIN_EXT_COUNT) { - self = &ext_pin_obj[num]; - } - } - #endif + // Try to find the pin in the board pins first. + self = machine_pin_find_named(&pin_board_pins_locals_dict, args[0]); if (!self) { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Unknown named pin \"%s\""), name); + // If not found, try to find the pin in the cpu pins which include + // CPU and and externally controlled pins (if any). + self = machine_pin_find_named(&pin_cpu_pins_locals_dict, args[0]); + } + if (!self) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("unknown named pin \"%s\""), name); + } + } else if (mp_obj_is_int(args[0])) { + // get the wanted pin object + int wanted_pin = mp_obj_get_int(args[0]); + if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_cpu_pins)) { + self = machine_pin_cpu_pins[wanted_pin]; } } if (!self) { - // get the wanted pin object - int wanted_pin = mp_obj_get_int(args[0]); - if (!(0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_obj))) { - mp_raise_ValueError("invalid pin"); - } - self = &machine_pin_obj[wanted_pin]; + mp_raise_ValueError("invalid pin"); } if (n_args > 1 || n_kw > 0) { @@ -427,7 +423,7 @@ STATIC machine_pin_irq_obj_t *machine_pin_get_irq(mp_hal_pin_obj_t pin) { irq = m_new_obj(machine_pin_irq_obj_t); irq->base.base.type = &mp_irq_type; irq->base.methods = (mp_irq_methods_t *)&machine_pin_irq_methods; - irq->base.parent = MP_OBJ_FROM_PTR(&machine_pin_obj[pin]); + irq->base.parent = MP_OBJ_FROM_PTR(&machine_pin_cpu_pins[pin]); irq->base.handler = mp_const_none; irq->base.ishard = false; MP_STATE_PORT(machine_pin_irq_obj[pin]) = irq; @@ -493,6 +489,10 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&machine_pin_toggle_obj) }, { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_pin_irq_obj) }, + // class attributes + { MP_ROM_QSTR(MP_QSTR_board), MP_ROM_PTR(&pin_board_pins_obj_type) }, + { MP_ROM_QSTR(MP_QSTR_cpu), MP_ROM_PTR(&pin_cpu_pins_obj_type) }, + // class constants { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(MACHINE_PIN_MODE_IN) }, { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(MACHINE_PIN_MODE_OUT) }, @@ -502,6 +502,17 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULL_DOWN) }, { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_IRQ_EDGE_RISE) }, { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_IRQ_EDGE_FALL) }, + + // Pins alternate functions + { MP_ROM_QSTR(MP_QSTR_ALT_SPI), MP_ROM_INT(GPIO_FUNC_SPI) }, + { MP_ROM_QSTR(MP_QSTR_ALT_UART), MP_ROM_INT(GPIO_FUNC_UART) }, + { MP_ROM_QSTR(MP_QSTR_ALT_I2C), MP_ROM_INT(GPIO_FUNC_I2C) }, + { MP_ROM_QSTR(MP_QSTR_ALT_PWM), MP_ROM_INT(GPIO_FUNC_PWM) }, + { MP_ROM_QSTR(MP_QSTR_ALT_SIO), MP_ROM_INT(GPIO_FUNC_SIO) }, + { MP_ROM_QSTR(MP_QSTR_ALT_PIO0), MP_ROM_INT(GPIO_FUNC_PIO0) }, + { MP_ROM_QSTR(MP_QSTR_ALT_PIO1), MP_ROM_INT(GPIO_FUNC_PIO1) }, + { MP_ROM_QSTR(MP_QSTR_ALT_GPCK), MP_ROM_INT(GPIO_FUNC_GPCK) }, + { MP_ROM_QSTR(MP_QSTR_ALT_USB), MP_ROM_INT(GPIO_FUNC_USB) }, }; STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table); diff --git a/ports/rp2/machine_pin.h b/ports/rp2/machine_pin.h index 83a81007c8..c10dc4f9e8 100644 --- a/ports/rp2/machine_pin.h +++ b/ports/rp2/machine_pin.h @@ -37,19 +37,46 @@ enum { MACHINE_PIN_MODE_ALT = 3 }; +typedef struct _machine_pin_af_obj_t { + mp_obj_base_t base; + qstr name; + uint8_t idx : 4; + uint8_t fn : 4; + uint8_t unit : 8; +} machine_pin_af_obj_t; + typedef struct _machine_pin_obj_t { mp_obj_base_t base; + qstr name; uint8_t id : 5; #if MICROPY_HW_PIN_EXT_COUNT uint8_t is_ext : 1; uint8_t is_output : 1; uint8_t last_output_value : 1; #endif + uint8_t af_num : 4; + const machine_pin_af_obj_t *af; } machine_pin_obj_t; +extern const mp_obj_type_t machine_pin_type; +extern const mp_obj_type_t machine_pin_af_type; + +// Include all of the individual pin objects +#include "genhdr/pins.h" + +extern const mp_obj_type_t pin_cpu_pins_obj_type; +extern const mp_obj_dict_t pin_cpu_pins_locals_dict; + +extern const mp_obj_type_t pin_board_pins_obj_type; +extern const mp_obj_dict_t pin_board_pins_locals_dict; + void machine_pin_ext_init(void); void machine_pin_ext_set(machine_pin_obj_t *self, bool value); bool machine_pin_ext_get(machine_pin_obj_t *self); void machine_pin_ext_config(machine_pin_obj_t *self, int mode, int value); +const machine_pin_obj_t *machine_pin_find_named(const mp_obj_dict_t *named_pins, mp_obj_t name); +const machine_pin_af_obj_t *machine_pin_find_alt(const machine_pin_obj_t *pin, uint8_t fn); +const machine_pin_af_obj_t *machine_pin_find_alt_by_index(const machine_pin_obj_t *pin, mp_uint_t af_idx); + #endif // MICROPY_INCLUDED_RP2_MACHINE_PIN_H diff --git a/ports/rp2/machine_pin_cyw43.c b/ports/rp2/machine_pin_cyw43.c index a41a2f3caa..c09561461f 100644 --- a/ports/rp2/machine_pin_cyw43.c +++ b/ports/rp2/machine_pin_cyw43.c @@ -36,14 +36,7 @@ #include "machine_pin.h" #include "lib/cyw43-driver/src/cyw43.h" -machine_pin_obj_t ext_pin_obj[MICROPY_HW_PIN_EXT_COUNT]; - void machine_pin_ext_init(void) { - for (uint i = 0; i < count_of(ext_pin_obj); i++) { - ext_pin_obj[i].id = i; - ext_pin_obj[i].base.type = &machine_pin_type; - ext_pin_obj[i].is_ext = true; - } } void machine_pin_ext_set(machine_pin_obj_t *self, bool value) {