diff --git a/builder/family/beken-72xx.py b/builder/family/beken-72xx.py index 12cd0bd..b54e22b 100644 --- a/builder/family/beken-72xx.py +++ b/builder/family/beken-72xx.py @@ -535,7 +535,7 @@ image_app_rblh = "${BUILD_DIR}/image_${MCULC}_app.${FLASH_RBL_OFFSET}.rblh" image_ota_rbl = "${BUILD_DIR}/image_${MCULC}_app.ota.rbl" env.Replace( # linker command (encryption + packaging) - LINK="${LTCHIPTOOL} link2bin ${VARIANT} '' ''", + LINK="${LTCHIPTOOL} link2bin ${BOARD_JSON} '' ''", # UF2OTA input list UF2OTA=[ # app binary image (enc+crc) for flasher diff --git a/builder/family/realtek-ambz.py b/builder/family/realtek-ambz.py index 67a6bb8..2a44ec3 100644 --- a/builder/family/realtek-ambz.py +++ b/builder/family/realtek-ambz.py @@ -296,7 +296,7 @@ image_ota1 = "${BUILD_DIR}/image_ota1.${FLASH_OTA1_OFFSET}.bin" image_ota2 = "${BUILD_DIR}/image_ota2.${FLASH_OTA2_OFFSET}.bin" env.Replace( # linker command (dual .bin outputs) - LINK="${LTCHIPTOOL} link2bin ${VARIANT} xip1 xip2", + LINK="${LTCHIPTOOL} link2bin ${BOARD_JSON} xip1 xip2", # UF2OTA input list UF2OTA=[ # same OTA images for flasher and device diff --git a/builder/frameworks/base.py b/builder/frameworks/base.py index 9d4011b..5d97c4a 100644 --- a/builder/frameworks/base.py +++ b/builder/frameworks/base.py @@ -14,10 +14,16 @@ board: PlatformBoardConfig = env.BoardConfig() platform: PlatformBase = env.PioPlatform() family: Family = env["FAMILY_OBJ"] +# Parse custom options +env.ParseCustomOptions(platform) +# Add flash layout C defines +env.AddFlashLayout(board) +# Write custom header options +env.ApplyCustomOptions(platform) +# Export board manifest for ltchiptool +env.ExportBoardData(board) # Print information about versions and custom options env.PrintInfo(platform) -# Apply custom header options -env.ApplyCustomOptions(platform) # TODO remove include path prepending ("!<...>") # Move common core sources (env.AddCoreSources()) and Arduino libs diff --git a/builder/main.py b/builder/main.py index b3223c8..36ad3ae 100644 --- a/builder/main.py +++ b/builder/main.py @@ -49,10 +49,6 @@ env.Replace( # Environment variables, include paths, etc. env.ConfigureEnvironment(platform, board) -# Flash layout defines -env.AddFlashLayout(board) -# Parse custom options -env.ParseCustomOptions(platform) # Family builders details: # - call env.AddLibrary("lib name", "base dir", [sources]) to add lib sources @@ -72,7 +68,7 @@ env.ParseCustomOptions(platform) # Framework builder (base.py/arduino.py) is executed in BuildProgram() # Force including the base framework in case no other is specified -if not env.get("PIOFRAMEWORK"): +if "nobuild" not in COMMAND_LINE_TARGETS and not env.get("PIOFRAMEWORK"): env.SConscript("frameworks/base.py") # diff --git a/builder/utils/env.py b/builder/utils/env.py index f50281d..700ebc1 100644 --- a/builder/utils/env.py +++ b/builder/utils/env.py @@ -96,7 +96,7 @@ def env_print_info(env: Environment, platform: PlatformBase): k = k.replace("#", ".") if isinstance(v, dict): print(f"{indent} - {k}:") - for k, v in v.items(): + for k, v in sorted(v.items()): dump(k, v, indent + TAB) elif isinstance(v, list): print(f"{indent} - {k}:") @@ -112,7 +112,7 @@ def env_print_info(env: Environment, platform: PlatformBase): # Print custom platformio.ini options if platform.custom_opts: print("CUSTOM OPTIONS:") - for k, v in platform.custom_opts.items(): + for k, v in sorted(platform.custom_opts.items()): dump(k, v) diff --git a/builder/utils/flash.py b/builder/utils/flash.py index a25c63f..82593a9 100644 --- a/builder/utils/flash.py +++ b/builder/utils/flash.py @@ -17,10 +17,12 @@ def env_add_flash_layout(env: Environment, board): for name, layout in flash_layout.items(): name = name.upper() (offset, _, length) = layout.partition("+") - defines[f"FLASH_{name}_OFFSET"] = offset - defines[f"FLASH_{name}_LENGTH"] = length + offset = int(offset, 16) + length = int(length, 16) + defines[f"FLASH_{name}_OFFSET"] = f"0x{offset:06X}" + defines[f"FLASH_{name}_LENGTH"] = f"0x{length:06X}" fal_items += f"FAL_PART_TABLE_ITEM({name.lower()},{name})" - flash_size = max(flash_size, int(offset, 16) + int(length, 16)) + flash_size = max(flash_size, offset + length) defines["FLASH_LENGTH"] = f"0x{flash_size:06X}" # for "root" partition defines["FLASH_ROOT_OFFSET"] = "0x000000" diff --git a/builder/utils/ltchiptool.py b/builder/utils/ltchiptool.py index 10b765b..fc1238d 100644 --- a/builder/utils/ltchiptool.py +++ b/builder/utils/ltchiptool.py @@ -1,9 +1,11 @@ # Copyright (c) Kuba SzczodrzyƄski 2022-06-02. +import json from datetime import datetime from os.path import basename, join, normpath from platformio.platform.base import PlatformBase +from platformio.platform.board import PlatformBoardConfig from SCons.Script import Builder, DefaultEnvironment, Environment env: Environment = DefaultEnvironment() @@ -43,13 +45,12 @@ def env_uf2ota(env: Environment, *args, **kwargs): cmd = [ "@${LTCHIPTOOL} uf2 write", *output_opts, - "--family ${FAMILY_SHORT_NAME}", - "--board ${VARIANT}", + "--board ${BOARD_JSON}", f"--lt-version {lt_version}", f'--fw "{project_name}:{project_version}"', f"--date {int(now.timestamp())}", "--legacy", - *env["UF2OTA"], + *(f'"{arg}"' for arg in env["UF2OTA"]), ] for output in outputs: @@ -72,6 +73,13 @@ def env_flash_write(env: Environment): return [] +def env_export_board_data(env: Environment, board: PlatformBoardConfig): + output = join("${BUILD_DIR}", "board.json") + with open(env.subst(output), "w") as f: + json.dump(board.manifest, f, indent="\t") + env["BOARD_JSON"] = output + + env.Append( BUILDERS=dict( BuildUF2OTA=Builder( @@ -80,3 +88,4 @@ env.Append( ) ) env.AddMethod(env_flash_write, "GetLtchiptoolWriteFlags") +env.AddMethod(env_export_board_data, "ExportBoardData") diff --git a/docs/TODO.md b/docs/TODO.md index 68aee23..937adbc 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -30,6 +30,12 @@ Explicit is better than implicit. - write OpenOCD flashers, using uf2ota library + FAL for partitions (in ltchiptool repository) +### Development + +- write Contributor's Guide +- export LT cores in an Arduino IDE-compatible format (automatically - GitHub Actions) +- consider using precompiled SDK blobs for improved build speed (especially on e.g. Raspberry Pi) + ### Serial - configuration of RX/TX pins diff --git a/platform.py b/platform.py index 18256a1..e5248ea 100644 --- a/platform.py +++ b/platform.py @@ -2,11 +2,12 @@ import importlib import json +import os import platform import sys from os import system from os.path import dirname -from typing import Dict +from typing import Dict, List import click from platformio.debug.config.base import DebugConfigBase @@ -114,7 +115,10 @@ class LibretuyaPlatform(PlatformBase): def print(self, *args, **kwargs): if not self.verbose: return - print(*args, **kwargs) + print(f"platform.py({os.getpid()}):", *args, **kwargs) + + def custom(self, key: str) -> object: + return self.custom_opts.get(key, None) def get_package_spec(self, name, version=None): # make PlatformIO detach existing package versions instead of overwriting @@ -124,12 +128,13 @@ class LibretuyaPlatform(PlatformBase): spec._name_is_custom = False return spec - def configure_default_packages(self, options, targets): + def configure_default_packages(self, options: dict, targets: List[str]): from ltchiptool.util.dict import RecursiveDict self.verbose = ( "-v" in sys.argv or "--verbose" in sys.argv or "PIOVERBOSE=1" in sys.argv ) + self.print(f"configure_default_packages(targets={targets})") pioframework = options.get("pioframework") or ["base"] if not pioframework: @@ -272,10 +277,8 @@ class LibretuyaPlatform(PlatformBase): return super().configure_default_packages(options, targets) - def custom(self, key: str) -> object: - return self.custom_opts.get(key, None) - def get_boards(self, id_=None): + self.print(f"get_boards(id_={id_})") result = PlatformBase.get_boards(self, id_) if not result: return result @@ -289,6 +292,14 @@ class LibretuyaPlatform(PlatformBase): def update_board(self, board: PlatformBoardConfig): if "_base" in board: board._manifest = ltchiptool.Board.get_data(board._manifest) + board._manifest.pop("_base") + + if self.custom("board"): + from ltchiptool.util.dict import merge_dicts + + with open(self.custom("board"), "r") as f: + custom_board = json.load(f) + board._manifest = merge_dicts(board._manifest, custom_board) family = board.get("build.family") family = ltchiptool.Family.get(short_name=family) @@ -310,7 +321,8 @@ class LibretuyaPlatform(PlatformBase): if "custom" not in debug["tools"]: debug["tools"]["custom"] = {} init = debug.get("gdb_init", []) - init += ["set mem inaccessible-by-default off"] + if "set mem inaccessible-by-default off" not in init: + init += ["set mem inaccessible-by-default off"] for link in protocols: if link == "openocd":