diff --git a/boards/bw15.json b/boards/bw15.json deleted file mode 100644 index c6fe9a6..0000000 --- a/boards/bw15.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "_base": [ - "realtek-ambz2", - "realtek-ambz2-8720", - "realtek-ambz2-2mb-992k", - "ic/rtl8720cf", - "pcb/bw15" - ], - "build": { - "mcu": "rtl8720cf", - "variant": "bw15" - }, - "name": "BW15", - "url": "https://docs.ai-thinker.com/_media/rtl8710/docs/bw15_datasheet_en.pdf", - "vendor": "Ai-Thinker Co., Ltd.", - "pcb": { - "symbol": "BW15" - }, - "doc": { - "fccid": "2AXVG-BW15", - "links": { - "Vendor datasheet": "https://docs.ai-thinker.com/_media/rtl8710/docs/bw15_datasheet_en.pdf" - } - } -} diff --git a/boards/generic-rtl8720cf-2mb-992k.json b/boards/generic-rtl8720cf-2mb-992k.json deleted file mode 100644 index c187d41..0000000 --- a/boards/generic-rtl8720cf-2mb-992k.json +++ /dev/null @@ -1,101 +0,0 @@ -{ - "_base": [ - "generic", - "realtek-ambz2", - "realtek-ambz2-8720", - "realtek-ambz2-2mb-992k", - "ic/rtl8720cf" - ], - "build": { - "mcu": "rtl8720cf", - "variant": "generic-rtl8720cf-2mb-992k" - }, - "name": "Generic - RTL8720CF (2M/992k)", - "symbol": "RTL8720CF (2M/992k)", - "url": "https://docs.libretiny.eu/boards/generic-rtl8720cf-2mb-992k/", - "vendor": "Generic", - "pcb": { - "pinout": { - "1": { - "IC": 15, - "ARD": "D0" - }, - "2": { - "IC": 16, - "ARD": "D1" - }, - "3": { - "IC": 18, - "ARD": "D2" - }, - "4": { - "IC": 19, - "ARD": "D3" - }, - "5": { - "IC": 20, - "ARD": "D4" - }, - "6": { - "IC": 21, - "ARD": "D5" - }, - "7": { - "IC": 22, - "ARD": "D6" - }, - "8": { - "IC": 23, - "ARD": "D7" - }, - "9": { - "IC": 24, - "ARD": "D8" - }, - "10": { - "IC": 25, - "ARD": "D9" - }, - "11": { - "IC": 26, - "ARD": "D10" - }, - "12": { - "IC": 33, - "ARD": "D11" - }, - "13": { - "IC": 34, - "ARD": "D12" - }, - "14": { - "IC": 36, - "ARD": "D13" - }, - "15": { - "IC": 37, - "ARD": "D14" - }, - "16": { - "IC": 38, - "ARD": "D15" - }, - "17": { - "IC": 39, - "ARD": "D16" - }, - "18": { - "IC": 40, - "ARD": "D17" - }, - "19": { - "IC": 1, - "ARD": "D18" - }, - "20": { - "IC": 3, - "ARD": "D19" - } - } - } -} diff --git a/cores/common/base/lt_types.h b/cores/common/base/lt_types.h index 6d4e623..eab0f69 100644 --- a/cores/common/base/lt_types.h +++ b/cores/common/base/lt_types.h @@ -38,11 +38,15 @@ typedef enum { RTL8710L0 = CPU_MODEL(F_RTL8710B, 0xFB), // CHIPID_8710BN_L0 / QFN32 RTL8711BN = CPU_MODEL(F_RTL8710B, 0xFD), // CHIPID_8711BN / QFN48 RTL8711BU = CPU_MODEL(F_RTL8710B, 0xFC), // CHIPID_8711BG / QFN68 + MX1290 = RTL8710BN, + MX1290V2 = RTL8710BX, // Beken 72XX BK7231T = CPU_MODEL(F_BK7231U, 0x1A), // *SCTRL_CHIP_ID = 0x7231a BK7231N = CPU_MODEL(F_BK7231N, 0x1C), // *SCTRL_CHIP_ID = 0x7231c - BL2028N = CPU_MODEL(F_BK7231N, 0x1C), // *SCTRL_CHIP_ID = 0x7231c BK7252 = CPU_MODEL(F_BK7251, 0x00), // TODO + BL2028N = BK7231N, + BK7231S = BK7231T, + BK7231U = BK7231T, } lt_cpu_model_t; /** diff --git a/docs/scripts/update_docs.py b/docs/scripts/update_docs.py index a35241c..27f2529 100644 --- a/docs/scripts/update_docs.py +++ b/docs/scripts/update_docs.py @@ -1,12 +1,7 @@ # Copyright (c) Kuba Szczodrzyński 2022-05-31. -import sys -from os.path import dirname, isfile, join - -sys.path.append(join(dirname(__file__), "..", "..")) - import re -from typing import Dict, List, Set +from os.path import dirname, isfile, join import colorama from colorama import Fore, Style @@ -35,56 +30,69 @@ def load_chip_type_h() -> str: return code -def check_mcus(boards: List[Board]) -> bool: - for board in boards: - # check if all boards' MCUs are defined in families.json - mcu_name: str = board["build.mcu"] - mcus = [mcu.lower() for mcu in board.family.mcus] - if mcu_name not in mcus: - print( - Fore.RED - + f"ERROR: MCU '{mcu_name}' of board '{board.name}' is not defined for family '{board.family.name}'" - + Style.RESET_ALL - ) - return False - return True - - -def get_family_mcus() -> Set[str]: - out = [] - for family in Family.get_all(): - out += family.mcus - return set(out) - - -def get_family_names() -> Set[str]: - return set(family.short_name for family in Family.get_all() if family.is_chip) - - -def get_board_mcus(boards: List[Board]) -> Set[str]: - out = set() - for board in boards: - mcu_name: str = board["build.mcu"] - out.add(mcu_name.upper()) - return out - - -def get_enum_keys(code: str, name: str) -> Set[str]: +def parse_enum(code: str, name: str) -> dict[str, str]: code = code.replace("\t", " ") code = code.partition(f"{name};")[0] code = code.rpartition("{")[2] code = code.strip().strip("{}").strip() code = [line.strip().strip(",").strip() for line in code.split("\n")] code = filter(None, code) - return set(line.partition(" ")[0].strip() for line in code) + code = [line.partition("=") for line in code] + code = {key.strip(): value.strip() for key, _, value in code} + return code -def get_enum_mcus(code: str) -> Set[str]: - return get_enum_keys(code, "lt_cpu_model_t") +def get_families_json() -> dict[str, int]: + return { + family.short_name: family.id for family in Family.get_all() if family.is_chip + } -def get_enum_families(code: str) -> Set[str]: - return set(family[2:] for family in get_enum_keys(code, "lt_cpu_family_t")) +def get_mcus_boards(boards: list[Board]) -> dict[str, str]: + out = {} + for board in boards: + mcu_name: str = board["build.mcu"].upper() + family_name: str = board.family.short_name + if mcu_name in out and out[mcu_name] != family_name: + print( + Fore.RED + + f"ERROR: MCU '{mcu_name}' of board '{board.name}' belongs to multiple families: '{out[mcu_name]}' and '{family_name}'" + + Style.RESET_ALL + ) + continue + out[mcu_name] = family_name + return out + + +def get_families_enum(code: str) -> dict[str, int]: + return { + family[2:]: int(family_id, 16) + for family, family_id in parse_enum(code, "lt_cpu_family_t").items() + } + + +def get_mcus_enum(code: str) -> tuple[dict[str, str], dict[str, str]]: + mcus = {} + aliases = {} + enum = parse_enum(code, "lt_cpu_model_t") + for mcu, mcu_id in enum.items(): + while mcu_id in enum: + aliases[mcu] = mcu_id + mcu_id = enum[mcu_id] + mcus[mcu] = mcu_id.split("(")[1].split(",")[0][2:] + return mcus, aliases + + +def get_readme_family_link(family: Family) -> str | None: + for f in family.inheritance[::-1]: + path = f"../platform/{f.name}/README.md" + if isfile(join(dirname(__file__), path)): + return path + return None + + +def get_readme_board_link(board: Board) -> str: + return f"../../boards/{board.name}/README.md" def board_json_sort(tpl): @@ -110,13 +118,25 @@ def get_board_symbol(board: Board) -> str: return board.symbol or board.generic_name or board.name.upper() -def write_chips(mcus: List[str]): +def write_chips(mcus: dict[str, Family], aliases: dict[str, str]): md = Markdown(OUTPUT, "supported_chips") - md.add_list(*mcus) + chips = [] + clones = [] + for mcu, family in sorted(mcus.items()): + docs = get_readme_family_link(family) + target = chips + if mcu in aliases: + mcu = f"{mcu} ({aliases[mcu]})" + target = clones + if docs: + target.append(md.get_link(mcu, docs)) + else: + target.append(mcu) + md.add_list(*chips, *clones) md.write() -def write_boards(boards: List[Board]): +def write_boards(boards: list[Board]): md = Markdown(OUTPUT, "supported_boards") header = [ "Name", @@ -140,7 +160,7 @@ def write_boards(boards: List[Board]): vendor_prev = vendor # count total pin count & IO count pins = "-" - pinout: Dict[str, dict] = board["pcb.pinout"] + pinout: dict[str, dict] = board["pcb.pinout"] if pinout: pinout = [pin for name, pin in pinout.items() if name.isnumeric()] pins_total = len(pinout) @@ -148,7 +168,8 @@ def write_boards(boards: List[Board]): pins = f"{pins_total} ({pins_io} I/O)" # format row values symbol = get_board_symbol(board) - board_url = f"[{symbol}](../../boards/{board.name}/README.md)" + docs = get_readme_board_link(board) + board_url = f"[{symbol}]({docs})" row = [ board_url, board["build.mcu"].upper(), @@ -166,9 +187,11 @@ def write_boards(boards: List[Board]): def write_unsupported_boards( - series: Dict[str, Dict[str, dict]], + series: dict[str, dict[str, dict]], name: str, - supported: List[str], + supported: list[str], + mcus: dict[str, Family], + generics: dict[str, list[Board]], ): md = Markdown(OUTPUT, name) header = [ @@ -189,9 +212,18 @@ def write_unsupported_boards( for board_name, board in sorted(boards.items(), key=board_json_sort): if board_name in supported: continue + board_text = board_name.upper() + mcu_text = mcu = board["mcu"].upper() + if mcu in generics: + generic = generics[mcu][0] + board_text += f' :material-information-outline:{{ title="You can use {generic.name} board instead" }}' + if mcu in mcus: + docs = get_readme_family_link(mcus[mcu]) + if docs: + mcu_text = md.get_link(mcu, docs) row = [ - board_name.upper(), - board["mcu"].upper(), + board_text, + mcu_text, sizeof(board["flash"]) if board["flash"] else "?", sizeof(board["ram"]) if board["ram"] else "?", str(board["pins_total"]), @@ -206,14 +238,14 @@ def write_unsupported_boards( md.write() -def write_families(): +def write_families(supported: list[Family]): md = Markdown(OUTPUT, "supported_families") header = [ "Title", - "Name (parent)", + "Name", "Code", "Short name & ID", - "Arduino Core", + "Supported?", "Source SDK", ] rows = [] @@ -222,11 +254,7 @@ def write_families(): # TODO update the table to support parent-child relationship if not family.is_chip: continue - docs = None - for f in family.inheritance: - readme = join(dirname(__file__), "..", "platform", f.name, "README.md") - if isfile(readme): - docs = f"../{f.name}/" + docs = get_readme_family_link(family) row = [ # Title "[{}]({})".format( @@ -235,29 +263,19 @@ def write_families(): ) if docs else family.description, - # Name (parent) - family.is_supported - and ( - f"`{family.name}`" - if not family.parent - else f"`{family.name}` (`{family.parent_name}`)" - ) - or "`-`", + # Name + family.is_supported and f"`{family.name}`" or "`-`", # Code - family.is_supported - and ( - f"`{family.code}`" - if not family.parent - else f"`{family.code}` (`{family.parent_code}`)" - ) - or "`-`", + family.is_supported and f"`{family.code}`" or "`-`", # Short name & ID "`{}` (0x{:X})".format( family.short_name, family.id, ), # Arduino Core - "✔️" if family.is_supported and family.has_arduino_core else "❌", + "✔️" + if family in supported and family.is_supported and family.has_arduino_core + else "❌", # Source SDK "[`{}`]({})".format( family.target_package, @@ -271,7 +289,7 @@ def write_families(): md.write() -def write_boards_list(boards: List[Board]): +def write_boards_list(boards: list[Board]): md = Markdown(join(dirname(__file__), ".."), join("..", "boards", "SUMMARY")) items = [] for board in boards: @@ -301,47 +319,118 @@ if __name__ == "__main__": ) errors = True - families_json = get_family_names() - families_enum = get_enum_families(code) - if families_json != families_enum: - print(Fore.RED + f"ERROR: Inconsistent JSON families vs ChipType.h families:") - print("- Missing in JSON: " + ", ".join(families_enum - families_json)) - print("- Missing in enum: " + ", ".join(families_json - families_enum)) - print(Style.RESET_ALL, end="") - errors = True + families_json = get_families_json() + families_enum = get_families_enum(code) + families_json_keys = set(families_json.keys()) + families_enum_keys = set(families_enum.keys()) + mcus_boards = get_mcus_boards(boards) + mcus_enum, mcu_aliases = get_mcus_enum(code) + mcus_boards_keys = set(mcus_boards.keys()) + mcus_enum_keys = set(mcus_enum.keys()) + mcus_missing_in_boards = mcus_enum_keys - mcus_boards_keys + mcus_missing_in_enum = mcus_boards_keys - mcus_enum_keys - mcus_json = get_family_mcus() - mcus_enum = get_enum_mcus(code) - mcus_boards = get_board_mcus(boards) - if mcus_json != mcus_enum: + # check if all families are defined in lt_types.h and families.json + if families_json_keys != families_enum_keys: + print(Fore.RED + f"ERROR: Inconsistent lt_types.h vs families.json:") print( - Fore.YELLOW + f"NOTICE: Inconsistent JSON family MCUs vs ChipType.h MCUs:" + "- Missing in JSON: " + ", ".join(families_enum_keys - families_json_keys) + ) + print( + "- Missing in enum: " + ", ".join(families_json_keys - families_enum_keys) ) - print("- Missing in JSON: " + ", ".join(mcus_enum - mcus_json)) - print("- Missing in enum: " + ", ".join(mcus_json - mcus_enum)) print(Style.RESET_ALL, end="") - # this is not considered an error (for now) - # errors = True - - if not check_mcus(boards): errors = True + # verify that family IDs match + for family in families_json_keys.union(families_enum_keys): + if ( + family in families_json + and family in families_enum + and families_json[family] != families_enum[family] + ): + print( + Fore.RED + + f"ERROR: Family ID mismatch for '{family}': 0x{families_json[family]:08X} vs 0x{families_enum[family]:08X}" + + Style.RESET_ALL + ) + errors = True + + # warn if any enum MCUs are unused in boards + if mcus_missing_in_boards: + print( + Fore.YELLOW + + f"NOTICE: Unused MCUs: " + + ", ".join(mcus_missing_in_boards) + + Style.RESET_ALL + ) + + # fail if any board MCUs are undefined in enum + if mcus_missing_in_enum: + print( + Fore.RED + + f"ERROR: Undefined MCUs in lt_types.h: " + + ", ".join(mcus_missing_in_enum) + + Style.RESET_ALL + ) + errors = True + + # check if all MCUs belong to the correct family + for mcu in mcus_boards_keys.union(mcus_enum_keys): + if ( + mcu in mcus_boards + and mcu in mcus_enum + and mcus_boards[mcu] != mcus_enum[mcu] + ): + print( + Fore.RED + + f"ERROR: MCU family mismatch for '{mcu}': '{mcus_boards[mcu]}' vs '{mcus_enum[mcu]}'" + + Style.RESET_ALL + ) + errors = True + if errors: exit(1) - write_chips(sorted(mcus_boards.union(mcus_json))) + # check all supported families by MCU presence in enum + families_supported = sorted(families_enum_keys.intersection(mcus_enum.values())) + families_supported = [Family.get(f) for f in families_supported] + # filter out MCUs of unsupported families + mcus_boards.update(mcus_enum) + mcus_all = {} + for mcu, family in mcus_boards.items(): + family = Family.get(family) + if family not in families_supported: + continue + mcus_all[mcu] = family + # remove boards of unsupported families + boards = [board for board in boards if board.family in families_supported] + + # find generic variants of boards + generics: dict[str, list[Board]] = {} + for board in boards: + if not board.is_generic: + continue + mcu: str = board["build.mcu"].upper() + if mcu not in generics: + generics[mcu] = [] + generics[mcu].append(board) + + write_chips(mcus_all, mcu_aliases) write_boards(boards) write_boards_list(boards) - write_families() + write_families(families_supported) - boards_all = [ + board_lists = [ "boards_tuya_all", ] - for name in boards_all: + for name in board_lists: file = join(dirname(__file__), "..", f"{name}.json") data = readjson(file) write_unsupported_boards( series=data, name=f"unsupported_{name}", supported=[board.name for board in boards], + mcus=mcus_all, + generics=generics, ) diff --git a/docs/status/supported.md b/docs/status/supported.md index a7ec757..a012c47 100644 --- a/docs/status/supported.md +++ b/docs/status/supported.md @@ -26,7 +26,7 @@ A list of chip families currently supported by this project. !!! note The term *family* was chosen over *platform*, in order to reduce possible confusion between LibreTiny supported "platforms" and PlatformIO's "platform", as an entire package. *Family* is also more compatible with the UF2 term. -The following list corresponds to UF2 OTA format family names, and is also [available as JSON](../../families.json). The IDs are also present in [lt_Types.h](../../ltapi/lt__types_8h.md). +The following list corresponds to UF2 OTA format family names, and is also [available as JSON](../../families.json). The IDs are also present in [lt_types.h](../../ltapi/lt__types_8h.md). {% include-markdown "supported_families.md" diff --git a/families.json b/families.json index 3cbbd3a..2d68612 100644 --- a/families.json +++ b/families.json @@ -10,8 +10,7 @@ "code": "amb1", "description": "Realtek Ameba1", "id": "0x9FFFD543", - "short_name": "RTL8710A", - "mcus": [] + "short_name": "RTL8710A" }, "realtek-ambz": { "parent": "realtek-amb", @@ -19,11 +18,7 @@ "description": "Realtek AmebaZ", "id": "0x22E0D6FC", "short_name": "RTL8710B", - "package": "framework-realtek-amb1", - "mcus": [ - "RTL8710BN", - "RTL8710BX" - ] + "package": "framework-realtek-amb1" }, "realtek-ambz2": { "parent": "realtek-amb", @@ -31,18 +26,14 @@ "description": "Realtek AmebaZ2", "id": "0xE08F7564", "short_name": "RTL8720C", - "package": "framework-realtek-ambz2", - "mcus": [ - "RTL8720CF" - ] + "package": "framework-realtek-ambz2" }, "realtek-ambd": { "parent": "realtek-amb", "code": "ambd", "description": "Realtek AmebaD", "id": "0x3379CFE2", - "short_name": "RTL8720D", - "mcus": [] + "short_name": "RTL8720D" }, "beken-72xx": { "parent": null, @@ -65,34 +56,21 @@ "code": "bk7231u", "description": "Beken 7231U/7231T", "id": "0x675A40B0", - "short_name": "BK7231U", - "mcus": [ - "BK7231T", - "BK7231S", - "BK7231U" - ] + "short_name": "BK7231U" }, "beken-7231n": { "parent": "beken-72xx-gen1", "description": "Beken 7231N", "code": "bk7231n", "id": "0x7B3EF230", - "short_name": "BK7231N", - "mcus": [ - "BK7231N", - "BL2028N" - ] + "short_name": "BK7231N" }, "beken-7251": { "parent": "beken-72xx-gen1", "code": "bk7251", "description": "Beken 7251/7252", "id": "0x6A82CC42", - "short_name": "BK7251", - "mcus": [ - "BK7251", - "BK7252" - ] + "short_name": "BK7251" }, "boufallo-bl678": { "parent": null, @@ -104,8 +82,7 @@ "code": "bl60x", "description": "Boufallo BL602/BL604", "id": "0xDE1270B7", - "short_name": "BL60X", - "mcus": [] + "short_name": "BL60X" }, "winnermicro-iot": { "parent": null, diff --git a/families.schema.json b/families.schema.json index 0254022..6c0f060 100644 --- a/families.schema.json +++ b/families.schema.json @@ -34,13 +34,6 @@ "package": { "type": "string", "pattern": "^framework-[a-z0-9-]+$" - }, - "mcus": { - "type": "array", - "items": { - "type": "string", - "pattern": "^[A-Z0-9]+$" - } } }, "additionalProperties": false,