Experiment with OTA support, better mbed upload

This commit is contained in:
unknown 2022-08-21 15:35:33 +02:00
parent 5bb8311544
commit a3c7bc9472

View File

@ -14,7 +14,7 @@
import sys import sys
from platform import system from platform import system
from os import makedirs from os import makedirs, remove
from os.path import isdir, join, isfile from os.path import isdir, join, isfile
import re import re
import time import time
@ -184,6 +184,22 @@ env.Append(
"$TARGET" "$TARGET"
]), "Building $TARGET"), ]), "Building $TARGET"),
suffix=".hex" suffix=".hex"
),
BinToSignedBin=Builder(
action=env.VerboseAction(" ".join([
'"$PYTHONEXE" "%s"' % join(
platform.get_package_dir("framework-arduinopico") or "",
"tools", "signing.py"),
"--mode",
"sign",
"--privatekey",
'"%s"' % join("$PROJECT_SRC_DIR", "private.key"),
"--bin",
"$SOURCES",
"--out",
"$TARGET"
]), "Building $TARGET"),
suffix=".bin.signed"
) )
) )
) )
@ -209,14 +225,35 @@ env.Append(
) )
) )
is_arduino_pico_build = env.BoardConfig().get("build.core", "arduino") == "earlephilhower" and "arduino" in env.get("PIOFRAMEWORK")
target_gen_header = None
if is_arduino_pico_build:
header_file = join(env.subst("$BUILD_DIR"), "core", "Updater_Signing.h")
env.Prepend(CFLAGS=['-I"%s"' % join("$BUILD_DIR", "core")])
signing_header_cmd = env.Command(
join("$BUILD_DIR", "core", "Updater_Signing.h"), # $TARGET
join("$PROJECT_SRC_DIR", "public.key"), # $SOURCE
env.VerboseAction(" ".join([
'"$PYTHONEXE" "%s"' % join(
platform.get_package_dir("framework-arduinopico"), "tools", "signing.py"),
"--mode", "header",
"--publickey", '"$SOURCE"',
"--out", "$TARGET"
]), "Generating $TARGET")
)
target_gen_header = env.Alias("gen_header", signing_header_cmd)
AlwaysBuild(target_gen_header)
# #
# Target: Build executable and linkable firmware # Target: Build executable and linkable firmware
# #
target_elf = None target_elf = None
target_signed_bin = None
if "nobuild" in COMMAND_LINE_TARGETS: if "nobuild" in COMMAND_LINE_TARGETS:
target_elf = join("$BUILD_DIR", "${PROGNAME}.elf") target_elf = join("$BUILD_DIR", "${PROGNAME}.elf")
target_firm = join("$BUILD_DIR", "${PROGNAME}.bin") target_firm = join("$BUILD_DIR", "${PROGNAME}.bin")
target_firm = join("$BUILD_DIR", "${PROGNAME}.bin.signed")
else: else:
target_elf = env.BuildProgram() target_elf = env.BuildProgram()
if set(["buildfs", "uploadfs"]) & set(COMMAND_LINE_TARGETS): if set(["buildfs", "uploadfs"]) & set(COMMAND_LINE_TARGETS):
@ -225,11 +262,14 @@ else:
AlwaysBuild(target_firm) AlwaysBuild(target_firm)
else: else:
target_firm = env.ElfToBin(join("$BUILD_DIR", "${PROGNAME}"), target_elf) target_firm = env.ElfToBin(join("$BUILD_DIR", "${PROGNAME}"), target_elf)
if is_arduino_pico_build:
target_signed_bin = env.BinToSignedBin(join("$BUILD_DIR", "${PROGNAME}"), target_firm)
env.Depends(target_signed_bin, "checkprogsize")
env.Depends(target_firm, "checkprogsize") env.Depends(target_firm, "checkprogsize")
env.AddPlatformTarget("buildfs", target_firm, target_firm, "Build Filesystem Image") env.AddPlatformTarget("buildfs", target_firm, target_firm, "Build Filesystem Image")
AlwaysBuild(env.Alias("nobuild", target_firm)) AlwaysBuild(env.Alias("nobuild", target_firm))
target_buildprog = env.Alias("buildprog", target_firm, target_firm) target_buildprog = env.Alias("buildprog", [target_firm, target_signed_bin], target_firm)
env.AddPostAction( env.AddPostAction(
target_elf, env.VerboseAction(generate_uf2, "Generating UF2 image") target_elf, env.VerboseAction(generate_uf2, "Generating UF2 image")
@ -284,14 +324,93 @@ def UploadUF2ToDisk(target, source, env):
copyfile(fpath, join(env.subst("$UPLOAD_PORT"), "%s.%s" % (progname, ext))) copyfile(fpath, join(env.subst("$UPLOAD_PORT"), "%s.%s" % (progname, ext)))
print( print(
"Firmware has been successfully uploaded.\n" "Firmware has been successfully uploaded.\n"
"(Some boards may require manual hard reset)"
) )
def TryResetPico(target, source, env):
upload_options = {}
if "BOARD" in env:
upload_options = env.BoardConfig().get("upload", {})
ports = list_serial_ports()
if len(ports) != 0:
last_port = ports[-1]["port"]
if upload_options.get("use_1200bps_touch", False):
env.TouchSerialPort(last_port, 1200)
time.sleep(2.0)
from platformio.device.list.util import list_logical_devices
from platformio.device.finder import is_pattern_port
from fnmatch import fnmatch
def find_rpi_disk(initial_port):
msdlabels = ("RPI-RP2")
item:str
for item in list_logical_devices():
if item["path"].startswith("/net"):
continue
if (
initial_port
and is_pattern_port(initial_port)
and not fnmatch(item["path"], initial_port)
):
continue
mbed_pages = [join(item["path"], n) for n in ("INDEX.HTM", "INFO_UF2.TXT")]
if any(isfile(p) for p in mbed_pages):
return item["path"]
if item["name"] and any(l in item["name"].lower() for l in msdlabels):
return item["path"]
return None
def AutodetectPicoDisk(target, source, env):
initial_port = env.subst("$UPLOAD_PORT")
if initial_port and not is_pattern_port(initial_port):
print(env.subst("Using manually specified: $UPLOAD_PORT"))
return
if upload_protocol == "mbed":
env.Replace(UPLOAD_PORT=find_rpi_disk(initial_port))
if env.subst("$UPLOAD_PORT"):
print(env.subst("Auto-detected: $UPLOAD_PORT"))
else:
sys.stderr.write(
"Error: Please specify `upload_port` for environment or use "
"global `--upload-port` option.\n"
"For some development platforms it can be a USB flash "
"drive (i.e. /media/<user>/<device name>)\n"
)
env.Exit(1)
if upload_protocol == "mbed": if upload_protocol == "mbed":
upload_actions = [ upload_actions = [
env.VerboseAction(env.AutodetectUploadPort, "Looking for upload disk..."), env.VerboseAction(TryResetPico, "Trying to reset Pico into bootloader mode..."),
env.VerboseAction(AutodetectPicoDisk, "Looking for upload disk..."),
env.VerboseAction(UploadUF2ToDisk, "Uploading $SOURCE") env.VerboseAction(UploadUF2ToDisk, "Uploading $SOURCE")
] ]
elif upload_protocol == "espota":
if not env.subst("$UPLOAD_PORT"):
sys.stderr.write(
"Error: Please specify IP address or host name of ESP device "
"using `upload_port` for build environment or use "
"global `--upload-port` option.\n"
"See https://docs.platformio.org/page/platforms/"
"espressif8266.html#over-the-air-ota-update\n")
env.Replace(
UPLOADER=join(
platform.get_package_dir("framework-arduinopico") or "",
"tools", "espota.py"),
UPLOADERFLAGS=["--debug", "--progress", "-i", "$UPLOAD_PORT", "-p", "2040"],
UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS -f $SOURCE'
)
if "uploadfs" in COMMAND_LINE_TARGETS:
env.Append(UPLOADERFLAGS=["-s"])
else:
# check if we have a .bin.signed file available.
# since the file may not be build yet, we try to predict that we will
# have that file if they private signing key exists.
if isfile(join(env.subst("$PROJECT_SRC_DIR"), "private.key")):
sys.stdout.write("Using signed OTA update file.")
upload_source = target_signed_bin
upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")]
elif upload_protocol == "picotool": elif upload_protocol == "picotool":
env.Replace( env.Replace(
UPLOADER=join(platform.get_package_dir("tool-rp2040tools") or "", "rp2040load"), UPLOADER=join(platform.get_package_dir("tool-rp2040tools") or "", "rp2040load"),
@ -406,4 +525,4 @@ env.AddPlatformTarget("uploadfs", target_firm, upload_actions, "Upload Filesyste
# Default targets # Default targets
# #
Default([target_buildprog, target_size]) Default([target_gen_header, target_buildprog, target_size])