From 5372c6cb6674971f2396f5bb842eda44712c705a Mon Sep 17 00:00:00 2001 From: Frank Hessel Date: Fri, 2 Dec 2022 11:59:05 +0100 Subject: [PATCH] Add chirpotle.sh flash command --- chirpotle.sh | 96 ++++++++++++++++++++++++++++++++++ scripts/list-used-firmwares.py | 88 +++++++++++++++++-------------- 2 files changed, 146 insertions(+), 38 deletions(-) diff --git a/chirpotle.sh b/chirpotle.sh index e19213e..e080bd7 100755 --- a/chirpotle.sh +++ b/chirpotle.sh @@ -406,6 +406,97 @@ function chirpotle_deploy { echo "Nodes have been stopped during deployment. Remember calling \"chirpotle.sh restartnodes\" before using the framework." } # end of chirpotle_deploy + +function chirpotle_flash { + # Default parameters + FIRMWARE="" + PORT="/dev/ttyUSB0" + + # Parameter parsing + while [[ $# -gt 0 ]] + do + KEY="$1" + case "$KEY" in + -p|--port) + PORT="$2" + shift + shift + ;; + -h|--help) + echo " Usage: chirpotle.sh flash [--port ] " + echo "" + echo " Build the firmware and flash it to a locally connected board." + echo "" + echo " firmware" + echo " The name of the firmware variant." + echo " Currently, the available options are:" + grep -E '^ifeq \(\$\(PRECONF\),([^\)]+)\)' "$REPODIR/node/companion-app/riot-apps/chirpotle-companion/Makefile.preconf" \ + | sed -E 's/^ifeq \(\$\(PRECONF\),([^\)]+)\)$/ - \1/' + echo "" + echo " -p, --port" + echo " The port the board is connected to" + echo " Default: /dev/ttyUSB0" + exit 0 + ;; + *) + if [[ "$FIRMWARE" == "" ]]; then + FIRMWARE="$1" + shift + else + echo "Unexpected argument: $KEY" >&2 + echo "Call chirpotle.sh flash --help for usage information." >&2 + exit 1 + fi + ;; + esac + done + + # Enter virtual environment + source "$ENVDIR/bin/activate" + + # Process localhost configuration + export CONFDIR="$CONFDIR" + export CONFFILE="$CONFFILE" # require original file for the lookup of node configuration files during deployment + TMPCONFFILE="$CONFFILE" + if [[ "$INCLUDE_LOCALHOST" == "0" ]]; then + TMPCONFFILE="/tmp/$CONFIGNAME-$$.tmp" + "$REPODIR/scripts/exclude-localhost.py" "$CONFFILE" > "$TMPCONFFILE" + fi + + # Check dependencies for firmware build + # ------------------------------------- + # Find used platform + PLATFORM=" $($REPODIR/scripts/list-used-firmwares.py platform-for "$FIRMWARE") " + + # Toolchain for ESP32 + if [[ "$PLATFORM" == " esp32 " ]]; then + export ESP32_SDK_DIR="$REPODIR/submodules/esp-idf" + export PATH="$REPODIR/submodules/xtensa-esp32-elf/bin:$PATH" + fi + + # Toolchain for bare-metal ARM + if [[ "$USED_PLATFORMS" == " arm_none " ]]; then + chirpotle_check_req_gcc_arm_none + fi + + # Toolchain for Linux ARM + if [[ "$USED_PLATFORMS" =~ " arm_linux " ]]; then + chirpotle_check_req_gcc_arm_linux + fi + + # Build the companion application for various toolchains + # ------------------------------------------------------ + APPDIR="$REPODIR/node/companion-app/riot-apps/chirpotle-companion" + + # Build LoPy4 (UART mode) + PRECONF="$FIRMWARE" PORT="$PORT" make -C "$APPDIR" clean all flash + if [[ "$?" != "0" ]]; then + echo "Building the companion application failed for $FIRMWARE" >&2 + exit 1 + fi + +} # end of chirpotle_flash + function chirpotle_deploycheck { # Default parameters CONFIGNAME="default" @@ -911,6 +1002,7 @@ function chirpotle_usage { echo " confeditor - Launch interactive configration editor" echo " deploy - Deploy ChirpOTLE to nodes" echo " deploycheck - Check requirements on ChirpOTLE nodes" + echo " flash - Flash a preconfigured firmware to a locally connected board" echo " help - Show this information" echo " install - Install controller on this host in a virtual environment" echo " interactive - Run an interactive evaluation session" @@ -959,6 +1051,10 @@ do shift ACTION=chirpotle_deploycheck ;; + flash) + shift + ACTION=chirpotle_flash + ;; install) shift ACTION=chirpotle_install diff --git a/scripts/list-used-firmwares.py b/scripts/list-used-firmwares.py index c0c388b..5deb38b 100755 --- a/scripts/list-used-firmwares.py +++ b/scripts/list-used-firmwares.py @@ -6,6 +6,19 @@ # Returns a list of unique firmware configurations for a given confname # Call: list-used-firmwares.py confdir confname +# Returns the platform for a specific firmware: +# Call: list-used-firmwares.py platform-for + +# Map firmwares to platforms +pmap = { + "esp32-generic": "esp32", + "lora-feather-m0": "arm_none", + "lopy4-uart": "esp32", + "lopy4": "esp32", + "t-beam-uart": "esp32", + "native-raspi": "arm_linux", +} + def conf_path_to_obj(d): """ Read configuration files from an input directory d into an object @@ -18,43 +31,42 @@ def conf_path_to_obj(d): configs[cfgname] = c return configs -if sys.argv[1] not in ["firmwares", "platforms"]: - print("First parameter must be \"firmwares\" or \"platforms\"") - exit(1) +if sys.argv[1] in ["firmwares", "platforms"]: + + confdir = pathlib.Path(sys.argv[2]) + hostconf = conf_path_to_obj(confdir / "hostconf")[pathlib.Path(sys.argv[3]).stem] + nodeconfs = conf_path_to_obj(confdir / "nodeconf") -confdir = pathlib.Path(sys.argv[2]) -hostconf = conf_path_to_obj(confdir / "hostconf")[pathlib.Path(sys.argv[3]).stem] -nodeconfs = conf_path_to_obj(confdir / "nodeconf") - -# Find all configs that are used -used_nodeconfs = set() -for sec in hostconf.sections(): - if "conf" in hostconf[sec]: - used_nodeconfs.add(hostconf[sec]["conf"]) -used_confs = map(lambda confname: nodeconfs[confname], - [pathlib.Path(c).stem for c in used_nodeconfs]) - -# Find all firmwares -used_firmwares = set() -for conf in used_confs: - for sec in conf.sections(): - if "firmware" in conf[sec]: - used_firmwares.add(conf[sec]["firmware"]) - -if sys.argv[1] == "firmwares": - print(" ".join(used_firmwares)) + # Find all configs that are used + used_nodeconfs = set() + for sec in hostconf.sections(): + if "conf" in hostconf[sec]: + used_nodeconfs.add(hostconf[sec]["conf"]) + used_confs = map(lambda confname: nodeconfs[confname], + [pathlib.Path(c).stem for c in used_nodeconfs]) + + # Find all firmwares + used_firmwares = set() + for conf in used_confs: + for sec in conf.sections(): + if "firmware" in conf[sec]: + used_firmwares.add(conf[sec]["firmware"]) + + if sys.argv[1] == "firmwares": + print(" ".join(used_firmwares)) + else: + used_platforms = set() + for fw in used_firmwares: + if fw in pmap: + used_platforms.add(pmap[fw]) + print(" ".join(used_platforms)) +elif sys.argv[1] == "platform-for": + if sys.argv[2] in pmap: + print(pmap[sys.argv[2]]) + exit(0) + else: + print("unknown firmware:", sys.argv[2], file=sys.stderr) + exit(1) else: - # Map firmwares to platforms - pmap = { - "esp32-generic": "esp32", - "lora-feather-m0": "arm_none", - "lopy4-uart": "esp32", - "lopy4": "esp32", - "t-beam-uart": "esp32", - "native-raspi": "arm_linux", - } - used_platforms = set() - for fw in used_firmwares: - if fw in pmap: - used_platforms.add(pmap[fw]) - print(" ".join(used_platforms)) \ No newline at end of file + print("First parameter must be \"firmwares\", \"platforms\" or \"platform-for\".") + exit(1)