diff --git a/builder/family/beken-72xx.py b/builder/family/beken-72xx.py index 32d2f33..99fd8f3 100644 --- a/builder/family/beken-72xx.py +++ b/builder/family/beken-72xx.py @@ -533,31 +533,19 @@ env.Append( ) # Main firmware outputs and actions +image_app_crc = "${BUILD_DIR}/image_${MCULC}_app.${FLASH_APP_OFFSET}.crc" +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} '' ''", # UF2OTA input list UF2OTA=[ - # app binary image (enc+crc), OTA1 (uploader) only - ( - "app", - "${BUILD_DIR}/${MCULC}_app_${FLASH_APP_OFFSET}.crc", - "", - "", - ), - # app RBL header (crc), OTA1 (uploader) only - ( - f"app+{rbl_offs}", - "${BUILD_DIR}/${MCULC}_app_${FLASH_RBL_OFFSET}.rblh", - "", # not used for OTA2 - "", - ), - # OTA RBL package, OTA2 (uf2ota lib) only - ( - "", # not used for OTA1 - "", - "download", - "${BUILD_DIR}/${MCULC}_app.ota.rbl", - ), + # app binary image (enc+crc) for flasher + f"{image_app_crc}=flasher:app", + # app RBL header (with crc) for flasher + f"{image_app_rblh}+{rbl_offs}=flasher:app", + # OTA RBL package for device only + f"{image_ota_rbl}=device:download", ], ) diff --git a/builder/family/realtek-ambz.py b/builder/family/realtek-ambz.py index e0bec86..4f8ee4d 100644 --- a/builder/family/realtek-ambz.py +++ b/builder/family/realtek-ambz.py @@ -274,18 +274,14 @@ env.Prepend(LIBS=[target_boot]) queue.BuildLibraries() # Main firmware outputs and actions +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", - # default output .bin name - IMG_FW="image_${FLASH_OTA1_OFFSET}.ota1.bin", # UF2OTA input list UF2OTA=[ - ( - "ota1", - "${BUILD_DIR}/image_${FLASH_OTA1_OFFSET}.ota1.bin", - "ota2", - "${BUILD_DIR}/image_${FLASH_OTA2_OFFSET}.ota2.bin", - ), + # same OTA images for flasher and device + f"{image_ota1},{image_ota2}=device:ota1,ota2;flasher:ota1,ota2", ], ) diff --git a/builder/main.py b/builder/main.py index 0108c7b..cf4f202 100644 --- a/builder/main.py +++ b/builder/main.py @@ -1,10 +1,17 @@ # Copyright (c) Kuba SzczodrzyƄski 2022-04-20. import sys +from os.path import join from platformio.platform.base import PlatformBase from platformio.platform.board import PlatformBoardConfig -from SCons.Script import Default, DefaultEnvironment, Environment +from SCons.Script import ( + COMMAND_LINE_TARGETS, + AlwaysBuild, + Default, + DefaultEnvironment, + Environment, +) env: Environment = DefaultEnvironment() platform: PlatformBase = env.PioPlatform() @@ -21,7 +28,7 @@ env.SConscript("utils/ltchiptool.py", exports="env") # Firmware name if env.get("PROGNAME", "program") == "program": - env.Replace(PROGNAME="firmware") + env.Replace(PROGNAME="raw_firmware") env.Replace(PROGSUFFIX=".elf") # Configure the toolchain @@ -62,19 +69,62 @@ env.AddFlashLayout(board) # - # Main firmware outputs and actions # Framework builder (base.py/arduino.py) is executed in BuildProgram() -target_elf = env.BuildProgram() -targets = [target_elf] +# Force including the base framework in case no other is specified +if not env.get("PIOFRAMEWORK"): + env.SConscript("frameworks/base.py") -if "UF2OTA" in env: - target_uf2 = env.BuildUF2OTA(target_elf) - targets.append(target_uf2) - env.AddFlashWriter(target_uf2) -elif "IMG_FW" in env: - target_fw = env.subst("$IMG_FW") - env.AddPlatformTarget("upload", target_fw, env["UPLOAD_ACTIONS"], "Upload") +# +# Target: Build executable and linkable firmware +# +target_uf2 = join("${BUILD_DIR}", "firmware.uf2") +if "nobuild" in COMMAND_LINE_TARGETS: + target_elf = join("${BUILD_DIR}", "${PROGNAME}.elf") + env["UF2OTA"] = "dummy" # forcefully allow uploading using ltchiptool else: - sys.stderr.write( - "Warning! Firmware outputs not specified. Uploading is not possible.\n" - ) + target_elf = env.BuildProgram() + target_uf2 = env.BuildUF2OTA(target_uf2, target_elf) + env.Depends(target_uf2, "checkprogsize") -Default(targets) +AlwaysBuild(env.Alias("nobuild", target_uf2)) +target_buildprog = env.Alias("buildprog", target_uf2, target_uf2) + +# +# Target: Print binary size +# +target_size = env.Alias( + "size", + target_elf, + env.VerboseAction("${SIZEPRINTCMD}", "Calculating size ${SOURCE}"), +) +AlwaysBuild(target_size) + +# +# Target: Upload firmware +# +upload_protocol = env.subst("${UPLOAD_PROTOCOL}") or "uart" +upload_actions = [] +upload_source = target_uf2 +ltchiptool_flags = "UF2OTA" in env and env.GetLtchiptoolWriteFlags() + +if ltchiptool_flags: + # use ltchiptool for flashing, if available + env.Replace( + LTCHIPTOOL_FLAGS=ltchiptool_flags, + UPLOADER="${LTCHIPTOOL} flash write", + UPLOADCMD="${UPLOADER} ${LTCHIPTOOL_FLAGS} ${UPLOADERFLAGS} ${SOURCE}", + ) + upload_actions = [ + env.VerboseAction(env.AutodetectUploadPort, "Looking for upload port..."), + env.VerboseAction("${UPLOADCMD}", "Uploading ${SOURCE}"), + ] +elif upload_protocol == "custom": + upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")] +else: + sys.stderr.write("Warning! Unknown upload protocol %s\n" % upload_protocol) + +AlwaysBuild(env.Alias("upload", upload_source, upload_actions)) + +# +# Default targets +# +Default([target_buildprog, target_size]) diff --git a/builder/utils/ltchiptool.py b/builder/utils/ltchiptool.py index e83ef32..3af3238 100644 --- a/builder/utils/ltchiptool.py +++ b/builder/utils/ltchiptool.py @@ -1,6 +1,5 @@ # Copyright (c) Kuba SzczodrzyƄski 2022-06-02. -import sys from datetime import datetime from os.path import basename, join, normpath @@ -23,7 +22,6 @@ def env_uf2ota(env: Environment, *args, **kwargs): if platform.custom("fw_version"): project_version = platform.custom("fw_version") - inputs = " ".join(f'"{";".join(input)}"' for input in env["UF2OTA"]) output = [ project_name, project_version, @@ -34,57 +32,46 @@ def env_uf2ota(env: Environment, *args, **kwargs): output = "_".join(output) + ".uf2" if platform.custom("fw_output"): output = platform.custom("fw_output") + output = join("${BUILD_DIR}", output) + output_copy_1 = join("${BUILD_DIR}", "firmware.uf2") + output_copy_2 = join("${BUILD_DIR}", "firmware.bin") + env["UF2OUT"] = output env["UF2OUT_BASE"] = basename(output) cmd = [ "@${LTCHIPTOOL} uf2 write", f'--output "{output}"', + f'--output-copy "{output_copy_1}"', + f'--output-copy "{output_copy_2}"', "--family ${FAMILY}", "--board ${VARIANT}", - f"--version {lt_version}", + f"--lt-version {lt_version}", f'--fw "{project_name}:{project_version}"', f"--date {int(now.timestamp())}", - inputs, + *env["UF2OTA"], ] print(f"|-- {basename(env.subst(output))}") - env.Execute(" ".join(cmd)) + print(f"|-- {basename(env.subst(output_copy_1))}") + print(f"|-- {basename(env.subst(output_copy_2))}") -def env_flash_write(env: Environment, target): +def env_flash_write(env: Environment): protocol = env.subst("${UPLOAD_PROTOCOL}") - actions = [] - # from platform-espressif32/builder/main.py if protocol == "uart": # upload via UART - env["UPLOADERFLAGS_UF2"] = [ - "${UF2OUT}", + return [ "-d", "${UPLOAD_PORT}", "-b", "${UPLOAD_SPEED}", ] - actions = [ - env.VerboseAction(env.AutodetectUploadPort, "Looking for upload port..."), - ] - elif protocol == "custom": - actions = [ - env.VerboseAction("${UPLOADCMD}", "Uploading firmware"), - ] else: - sys.stderr.write("Warning! Unknown upload protocol %s\n" % protocol) - return - - # add main upload target - env.Replace( - UPLOADER="${LTCHIPTOOL} flash write", - UPLOADCMD="${UPLOADER} ${UPLOADERFLAGS_UF2} ${UPLOADERFLAGS}", - ) - actions.append(env.VerboseAction("${UPLOADCMD}", "Uploading ${UF2OUT_BASE}")) - env.AddPlatformTarget("upload", target, actions, "Upload") + # can't upload via ltchiptool + return [] env.Append( @@ -94,4 +81,4 @@ env.Append( ) ) ) -env.AddMethod(env_flash_write, "AddFlashWriter") +env.AddMethod(env_flash_write, "GetLtchiptoolWriteFlags") diff --git a/platform.py b/platform.py index 8b801aa..643d421 100644 --- a/platform.py +++ b/platform.py @@ -94,7 +94,7 @@ class LibretuyaPlatform(PlatformBase): def configure_default_packages(self, options, targets): from ltchiptool.util.dict import RecursiveDict - pioframework = options.get("pioframework") + pioframework = options.get("pioframework") or ["base"] if not pioframework: return framework: str = pioframework[0] @@ -121,7 +121,6 @@ class LibretuyaPlatform(PlatformBase): fg="red", ) exit(1) - options.get("pioframework")[0] = framework # make ArduinoCore-API required if framework == "arduino":