diff --git a/ports/psoc6/Makefile b/ports/psoc6/Makefile index d4a60c0669d28..751bdcb0c4f2c 100644 --- a/ports/psoc6/Makefile +++ b/ports/psoc6/Makefile @@ -198,7 +198,6 @@ $(MPY_MAIN_BUILD_DIR)/firmware.elf: $(OBJ) $(MPY_MTB_LIBRARIES) $(LIBS) $(MPY_MAIN_BUILD_DIR)/firmware.hex: $(MPY_MAIN_BUILD_DIR)/firmware.elf $(Q) $(OBJCOPY) -O ihex $^ $@ - # include adapter makefile include mtb-libs/makefile_mtb.mk @@ -207,7 +206,7 @@ include $(TOP)/py/mkrules.mk MPY_CROSS_FLAGS += -march=armv7m -build: mtb_get_build_flags $(MPY_PATH_TO_MAIN_MAKEFILE) $(MPY_MAIN_BUILD_DIR)/firmware.hex +build: mtb_get_build_flags $(MPY_PATH_TO_MAIN_MAKEFILE) $(MPY_MAIN_BUILD_DIR)/firmware.hex make_pins all: build @@ -235,6 +234,44 @@ test_multi: $(Q) cd ../../tests ; ./run-multitests.py -i pyb:$(DEV0) -i pyb:$(DEV1) $(MULTI_TESTS) +# Supporting variables for make-pins.py script execution +MAKE_PINS = boards/make-pins.py + +ifeq ($(BOARD), CY8CPROTO-062-4343W) +PIN_PACKAGE_FILE = cyhal_psoc6_02_124_bga.h +endif +ifeq ($(BOARD), CY8CPROTO-063-BLE) +PIN_PACKAGE_FILE = cyhal_psoc6_03_68_qfn.h #ToDo: Check the right file and replace +endif + +#ToDo: Post adding af functionality, refactor to minimize dependent variables in py script if possible +GEN_PINS_SRC := $(BUILD)/pins_$(BOARD).c +GEN_PINS_HDR := $(HEADER_BUILD)/pins.h +GEN_PINS_QSTR := $(BUILD)/pins_qstr.h +BOARD_PINS := ./pins.csv +BOARD_AF_PINS := ./pins_af.csv +PREFIX_FILE := psoc6_prefix.c +HEADER_BUILD := $(BUILD)/genhdr + +# Rule to generate pins.csv +#ToDo: Move to python script when af completed +$(BOARD_PINS): + @echo "Creating $(BOARD_PINS)" + @touch $(BOARD_PINS) + +$(BOARD_AF_PINS): + @echo "Creating $(BOARD_AF_PINS)" + @touch $(BOARD_AF_PINS) + +$(HEADER_BUILD): + @mkdir -p $(HEADER_BUILD) + @chmod +w -R $(HEADER_BUILD) + +make_pins: + @echo "Generating pin structures" + $(PYTHON) $(MAKE_PINS) --gen-pin-for $(PIN_PACKAGE_FILE) --save-pins-csv-at $(BOARD_PINS) --save-pins-af-csv-at $(BOARD_AF_PINS) --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) --qstr $(GEN_PINS_QSTR) > $(GEN_PINS_SRC) + rm -rf $(BOARD_PINS) $(BOARD_AF_PINS) + help: @: $(info ) diff --git a/ports/psoc6/boards/make-pins.py b/ports/psoc6/boards/make-pins.py new file mode 100755 index 0000000000000..9551574710a01 --- /dev/null +++ b/ports/psoc6/boards/make-pins.py @@ -0,0 +1,313 @@ +from __future__ import print_function +import argparse +import sys +import csv +import re +import os + + +def get_pin_addr_helper(pin_def): + pattern = r"CYHAL_PORT_(\d+),\s*(\d+)" + match = re.search(pattern, pin_def) + port_number = match.group(1) + pin_number = match.group(2) + return (int(port_number) << 3) + int(pin_number) + + +def get_pin_package_path(filename): + root_dir = "./mtb_shared/mtb-hal-cat1" + mid_dir = "COMPONENT_CAT1A/include/pin_packages" + for dirpath, dirnames, filenames in os.walk(root_dir): + for dirname in dirnames: + if dirname.startswith("release-"): + release_version = dirname + file_path = os.path.join(root_dir, release_version, mid_dir, filename) + if os.path.isfile(file_path): + return file_path + return None + + +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 Pin(object): + def __init__(self, name, pin_addr): + self._name = name + self._pin_addr = pin_addr + self._board_pin = False + + def cpu_pin_name(self): + return self._name + + def is_board_pin(self): + return self._board_pin + + def set_is_board_pin(self): + self._board_pin = True + + def print(self): + print( + "const machine_pin_obj_t pin_{:s}_obj = PIN({:s}, {:s});".format( + self._name, + self._name, + self._pin_addr, + ) + ) + print("") + + def print_header(self, hdr_file): + n = self.cpu_pin_name() + hdr_file.write("extern const machine_pin_obj_t pin_{:s}_obj;\n".format(n)) + hdr_file.write("#define pin_{:s} (&pin_{:s}_obj)\n".format(n, n)) + + def qstr_list(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.board_pin_csv_path = "" + + def find_pin(self, cpu_pin_name): + for named_pin in self.cpu_pins: + pin = named_pin.pin() + if pin.cpu_pin_name() == cpu_pin_name: + return pin + + def generate_pins_csv(self, pin_package_filename, pins_csv_filename): + file_path = get_pin_package_path(pin_package_filename) + + if file_path is None: + sys.exit(1) + + # Read the header file + with open(file_path, "r") as file: + content = file.read() + + # Find the starting and ending points of the enum declaration + enum_start = content.find("typedef enum {") + enum_end = content.find("}") + + if enum_start != -1 and enum_end != -1: + enum_content = content[enum_start:enum_end] + + # Extract enum values using regex + enum_values = re.findall(r"\b(\w+)\s*=", enum_content) + + # Write enum values to a CSV file + with open("./" + pins_csv_filename, "w", newline="") as csv_file: + csv_writer = csv.writer(csv_file) + csv_writer.writerows([[value, value] for value in enum_values]) + self.board_pin_csv_path = pins_csv_filename + + print("// pins.csv generated successfully") + else: + print("// Error: pins.csv generation failed") + + def generate_af_pins_csv(self, pin_package_filename, pins_af_csv_filename): + file_path = get_pin_package_path(pin_package_filename) + + if file_path is None: + sys.exit(1) + # Read the header file + with open(file_path, "r") as file: + content = file.read() + + # Find the starting and ending points of the enum declaration + enum_start = content.find("typedef enum {") + enum_end = content.find("}") + + if enum_start != -1 and enum_end != -1: + enum_content = content[enum_start:enum_end] + + # Extract enum values using regex + pin_name = re.findall(r"\b(?!NC\b)(\w+)\s*=", enum_content) + pin_def = re.findall(r"=\s*(.*?\))", enum_content) + # Write enum values to a CSV file + with open("./" + pins_af_csv_filename, "w", newline="") as csv_file: + csv_writer = csv.writer(csv_file) + for pname, pdef in zip(pin_name, pin_def): + val = get_pin_addr_helper(pdef) + csv_writer.writerow([pname, val]) + + print("// pins_af.csv generated successfully") + else: + print("Error: pins_af.csv generation failed") + + # ToDo: Complete for alternate functions + def parse_af_file(self, filename): + with open("./" + filename, "r") as csvfile: + rows = csv.reader(csvfile) + for row in rows: + try: + pin_name = row[0] + pin_addr = row[1] + except: + continue + pin = Pin(pin_name, pin_addr) + self.cpu_pins.append(NamedPin(pin_name, pin)) + + def parse_board_file(self): + with open(self.board_pin_csv_path, "r") as csvfile: + rows = csv.reader(csvfile) + for row in rows: + try: + board_pin_name = row[0] + cpu_pin_name = row[1] + except: + continue + pin = self.find_pin(cpu_pin_name) + if pin: + pin.set_is_board_pin() + self.board_pins.append(NamedPin(board_pin_name, pin)) + + def print_named(self, label, named_pins): + 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_board_pin(): + print( + " {{ MP_ROM_QSTR(MP_QSTR_{:s}), MP_ROM_PTR(&pin_{:s}_obj) }},".format( + named_pin.name(), pin.cpu_pin_name() + ) + ) + print("};") + print( + "MP_DEFINE_CONST_DICT(pin_{:s}_pins_locals_dict, pin_{:s}_pins_locals_dict_table);".format( + label, label + ) + ) + + def print(self): + for named_pin in self.cpu_pins: + pin = named_pin.pin() + if pin.is_board_pin(): + pin.print() + self.print_named("cpu", self.cpu_pins) + print("") + + def print_header(self, hdr_filename): + with open(hdr_filename, "wt") as hdr_file: + for named_pin in self.cpu_pins: + pin = named_pin.pin() + if pin.is_board_pin(): + pin.print_header(hdr_file) + + 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): + # cond_var = None + + # ToDO: For next iteration + """if qstr.startswith("AF"): + af_words = qstr.split("_") + cond_var = conditional_var(af_words[1]) + print_conditional_if(cond_var, file=qstr_file)""" + print("Q({})".format(qstr), file=qstr_file) + + +def main(): + parser = argparse.ArgumentParser( + prog="make-pins.py", + usage="%(prog)s [options] [command]", + description="Generate board specific pin file", + ) + + parser.add_argument( + "-g", + "--gen-pin-for", + dest="pin_package_filename", + help="Specifies the pin package file from mtb assets to generate pins.csv", + ) + + parser.add_argument( + "-p", + "--save-pins-csv-at", + dest="pins_csv", + help="Specifies name of generated pins csv file", + ) + + parser.add_argument( + "-gaf", + "--save-pins-af-csv-at", + dest="pins_af_csv", + help="Specifies name of generated alternate functions pins csv file", + ) + + parser.add_argument( + "-pr", + "--prefix", + dest="prefix_filename", + help="Specifies beginning portion of generated pins file", + default="psoc6_prefix.c", + ) + + parser.add_argument( + "-q", + "--qstr", + dest="qstr_filename", + help="Specifies name of generated qstr header file", + ) + + parser.add_argument( + "-r", + "--hdr", + dest="hdr_filename", + help="Specifies name of generated pin header file", + ) + + args = parser.parse_args(sys.argv[1:]) + + pins = Pins() + + if args.pin_package_filename and args.pins_csv: + print("// Generating pins csv file with following parsed arguments") + print("// - --gen-pin-for {:s}".format(args.pin_package_filename)) + print("// - --save-pins-csv-at {:s}".format(args.pins_csv)) + pins.generate_pins_csv(args.pin_package_filename, args.pins_csv) + + if args.pin_package_filename and args.pins_af_csv: + print("// Generating alternate functions pins csv file with following parsed arguments") + print("// - --save-pins-csv-at {:s}".format(args.pins_af_csv)) + pins.generate_af_pins_csv(args.pin_package_filename, args.pins_af_csv) + + if args.pins_af_csv: + print("// --save-pins-af-csv-at {:s}".format(args.pins_af_csv)) + pins.parse_af_file(args.pins_af_csv) + + 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.parse_board_file() + + pins.print() + pins.print_header(args.hdr_filename) + pins.print_qstr(args.qstr_filename) + + +if __name__ == "__main__": + main() diff --git a/ports/psoc6/psoc6_prefix.c b/ports/psoc6/psoc6_prefix.c new file mode 100644 index 0000000000000..937ca1879ef09 --- /dev/null +++ b/ports/psoc6/psoc6_prefix.c @@ -0,0 +1,14 @@ +// psoc6_prefix.c becomes the initial portion of the generated pins file. + +#include + +#include "py/obj.h" +#include "py/mphal.h" +#include "pins.h" + +#define PIN(p_name, pin_addr, pin_name) \ + { \ + { &machine_pin_type }, \ + .pin_addr = pin_addr, \ + .pin_name = pin_name, \ + } diff --git a/tools/codeformat.py b/tools/codeformat.py index 681b084f0e713..7426b75745922 100755 --- a/tools/codeformat.py +++ b/tools/codeformat.py @@ -74,7 +74,8 @@ "ports/nrf/modules/uos/*.[ch]", "ports/nrf/modules/utime/*.[ch]", # PSoC 3rd party - "ports/psoc6/boards/**/*.[ch]", + "ports/psoc6/mtb-libs/**/*.[ch]", + "ports/psoc6/mtb_shared/**/*.[ch]", # STM32 USB dev/host code is mostly 3rd party. "ports/stm32/usbdev/**/*.[ch]", "ports/stm32/usbhost/**/*.[ch]",