From a1637e9216e98396938debd7ccb4e15cbcb41eb1 Mon Sep 17 00:00:00 2001 From: hedger Date: Tue, 2 Aug 2022 16:46:43 +0300 Subject: [PATCH] fbt fixes & improvements (#1490) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fbt: minimal USB flash mode; scripts: faster storage.py with larger chunks * fbt: fixed creation of temporary file nodes confusing scons * docs: removed refs to --with-updater * fbt: removed splashscreen from minimal update package * fbt: renamed dist arguments for consistency * docs: fixed updater_debug target * fbt: separate target for generating compilation_database.json without building the code. * fbt: added `jflash` target for programming over JLink probe; refactored usb flashing targets * fbt: building updater_app in unit_tests configuration * fbt: fixed reset behavior after flashing with J-Link * fbt: generating .map file for firmware binary & external apps * fbt/core: moved library contents before apps code Co-authored-by: あく --- .github/workflows/build.yml | 4 +- ReadMe.md | 4 +- SConstruct | 66 +++++++++++------ applications/extapps.scons | 2 + debug/fw.jflash | 90 ++++++++++++++++++++++++ documentation/OTA.md | 9 ++- documentation/fbt.md | 14 ++-- fbt_options.py | 1 + firmware.scons | 15 ++-- firmware/targets/f7/stm32wb55xx_flash.ld | 1 + scripts/flipper/storage.py | 11 +-- scripts/selfupdate.py | 11 +-- scripts/storage.py | 11 +-- site_scons/site_tools/fbt_apps.py | 7 +- site_scons/site_tools/fbt_dist.py | 31 ++++++++ site_scons/site_tools/jflash.py | 27 +++++++ 16 files changed, 240 insertions(+), 64 deletions(-) create mode 100644 debug/fw.jflash create mode 100644 site_scons/site_tools/jflash.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d792c127..ab3f5994 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -78,7 +78,7 @@ jobs: set -e for TARGET in ${TARGETS} do - ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` --with-updater updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }} + ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }} done - name: 'Move upload files' @@ -214,5 +214,5 @@ jobs: set -e for TARGET in ${TARGETS} do - ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` --with-updater updater_package DEBUG=0 COMPACT=1 + ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` updater_package DEBUG=0 COMPACT=1 done diff --git a/ReadMe.md b/ReadMe.md index f3a35056..36a887dc 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -29,11 +29,11 @@ They both must be flashed in the order described. With Flipper attached over USB: -`./fbt --with-updater flash_usb` +`./fbt flash_usb` Just building the package: -`./fbt --with-updater updater_package` +`./fbt updater_package` To update, copy the resulting directory to Flipper's SD card and navigate to `update.fuf` file in Archive app. diff --git a/SConstruct b/SConstruct index 7cdf88fc..178ae192 100644 --- a/SConstruct +++ b/SConstruct @@ -33,8 +33,10 @@ coreenv["ROOT_DIR"] = Dir(".") # Create a separate "dist" environment and add construction envs to it distenv = coreenv.Clone( - tools=["fbt_dist", "openocd", "blackmagic"], - OPENOCD_GDB_PIPE=["|openocd -c 'gdb_port pipe; log_output debug/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}"], + tools=["fbt_dist", "openocd", "blackmagic", "jflash"], + OPENOCD_GDB_PIPE=[ + "|openocd -c 'gdb_port pipe; log_output debug/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}" + ], GDBOPTS_BASE=[ "-ex", "target extended-remote ${GDBREMOTE}", @@ -61,6 +63,7 @@ distenv = coreenv.Clone( "-ex", "compare-sections", ], + JFLASHPROJECT="${ROOT_DIR.abspath}/debug/fw.jflash", ENV=os.environ, ) @@ -71,7 +74,9 @@ firmware_env = distenv.AddFwProject( ) # If enabled, initialize updater-related targets -if GetOption("fullenv"): +if GetOption("fullenv") or any( + filter(lambda target: "updater" in target or "flash_usb" in target, BUILD_TARGETS) +): updater_env = distenv.AddFwProject( base_env=coreenv, fw_type="updater", @@ -79,11 +84,11 @@ if GetOption("fullenv"): ) # Target for self-update package - dist_arguments = [ - "-r", - '"${ROOT_DIR.abspath}/assets/resources"', + dist_basic_arguments = [ "--bundlever", '"${UPDATE_VERSION_STRING}"', + ] + dist_radio_arguments = [ "--radio", '"${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}"', "--radiotype", @@ -92,16 +97,34 @@ if GetOption("fullenv"): "--obdata", '"${ROOT_DIR.abspath}/${COPRO_OB_DATA}"', ] - if distenv["UPDATE_SPLASH"]: - dist_arguments += [ + dist_resource_arguments = [ + "-r", + '"${ROOT_DIR.abspath}/assets/resources"', + ] + dist_splash_arguments = ( + [ "--splash", distenv.subst("assets/slideshow/$UPDATE_SPLASH"), ] + if distenv["UPDATE_SPLASH"] + else [] + ) selfupdate_dist = distenv.DistCommand( "updater_package", (distenv["DIST_DEPENDS"], firmware_env["FW_RESOURCES"]), - DIST_EXTRA=dist_arguments, + DIST_EXTRA=[ + *dist_basic_arguments, + *dist_radio_arguments, + *dist_resource_arguments, + *dist_splash_arguments, + ], + ) + + selfupdate_min_dist = distenv.DistCommand( + "updater_minpackage", + distenv["DIST_DEPENDS"], + DIST_EXTRA=dist_basic_arguments, ) # Updater debug @@ -121,18 +144,16 @@ if GetOption("fullenv"): ) # Installation over USB & CLI - usb_update_package = distenv.UsbInstall( - "#build/usbinstall.flag", - ( - distenv["DIST_DEPENDS"], - firmware_env["FW_RESOURCES"], - selfupdate_dist, - ), + usb_update_package = distenv.AddUsbFlashTarget( + "#build/usbinstall.flag", (firmware_env["FW_RESOURCES"], selfupdate_dist) ) - if distenv["FORCE"]: - distenv.AlwaysBuild(usb_update_package) - distenv.Depends(usb_update_package, selfupdate_dist) - distenv.Alias("flash_usb", usb_update_package) + distenv.Alias("flash_usb_full", usb_update_package) + + usb_minupdate_package = distenv.AddUsbFlashTarget( + "#build/minusbinstall.flag", (selfupdate_min_dist,) + ) + distenv.Alias("flash_usb", usb_minupdate_package) + # Target for copying & renaming binaries to dist folder basic_dist = distenv.DistCommand("fw_dist", distenv["DIST_DEPENDS"]) @@ -147,8 +168,9 @@ distenv.Alias("copro_dist", copro_dist) firmware_flash = distenv.AddOpenOCDFlashTarget(firmware_env) distenv.Alias("flash", firmware_flash) -if distenv["FORCE"]: - distenv.AlwaysBuild(firmware_flash) + +firmware_jflash = distenv.AddJFlashTarget(firmware_env) +distenv.Alias("jflash", firmware_jflash) firmware_bm_flash = distenv.PhonyTarget( "flash_blackmagic", diff --git a/applications/extapps.scons b/applications/extapps.scons index a53620b9..11b59757 100644 --- a/applications/extapps.scons +++ b/applications/extapps.scons @@ -38,6 +38,8 @@ appenv.AppendUnique( "-Wl,--no-export-dynamic", "-fvisibility=hidden", "-Wl,-e${APP_ENTRY}", + "-Xlinker", + "-Map=${TARGET}.map", ], ) diff --git a/debug/fw.jflash b/debug/fw.jflash new file mode 100644 index 00000000..8621efb4 --- /dev/null +++ b/debug/fw.jflash @@ -0,0 +1,90 @@ + AppVersion = 76803 + FileVersion = 2 +[GENERAL] + aATEModuleSel[24] = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ConnectMode = 0 + CurrentFile = "..\build\latest\firmware.bin" + DataFileSAddr = 0x08000000 + GUIMode = 0 + HostName = "" + TargetIF = 1 + USBPort = 0 + USBSerialNo = 0x00000000 + UseATEModuleSelection = 0 +[JTAG] + IRLen = 0 + MultipleTargets = 0 + NumDevices = 0 + Speed0 = 8000 + Speed1 = 8000 + TAP_Number = 0 + UseAdaptive0 = 0 + UseAdaptive1 = 0 + UseMaxSpeed0 = 0 + UseMaxSpeed1 = 0 +[CPU] + NumInitSteps = 2 + InitStep0_Action = "Reset" + InitStep0_Value0 = 0x00000000 + InitStep0_Value1 = 0x00000000 + InitStep0_Comment = "" + InitStep1_Action = "Halt" + InitStep1_Value0 = 0xFFFFFFFF + InitStep1_Value1 = 0xFFFFFFFF + InitStep1_Comment = "" + NumExitSteps = 1 + ExitStep0_Action = "Reset" + ExitStep0_Value0 = 0x00000005 + ExitStep0_Value1 = 0x00000032 + ExitStep0_Comment = "" + UseScriptFile = 0 + ScriptFile = "" + UseRAM = 1 + RAMAddr = 0x20000000 + RAMSize = 0x00030000 + CheckCoreID = 1 + CoreID = 0x6BA02477 + CoreIDMask = 0x0F000FFF + UseAutoSpeed = 0x00000001 + ClockSpeed = 0x00000000 + EndianMode = 0 + ChipName = "ST STM32WB55RG" +[FLASH] + aRangeSel[1] = 0-255 + BankName = "Internal flash" + BankSelMode = 1 + BaseAddr = 0x08000000 + NumBanks = 1 +[PRODUCTION] + AutoPerformsDisconnect = 0 + AutoPerformsErase = 1 + AutoPerformsProgram = 1 + AutoPerformsSecure = 0 + AutoPerformsStartApp = 1 + AutoPerformsUnsecure = 0 + AutoPerformsVerify = 0 + EnableFixedVTref = 0 + EnableTargetPower = 0 + EraseType = 1 + FixedVTref = 0x00000CE4 + MonitorVTref = 0 + MonitorVTrefMax = 0x0000157C + MonitorVTrefMin = 0x000003E8 + OverrideTimeouts = 0 + ProgramSN = 0 + SerialFile = "" + SNAddr = 0x00000000 + SNInc = 0x00000001 + SNLen = 0x00000004 + SNListFile = "" + SNValue = 0x00000001 + StartAppType = 1 + TargetPowerDelay = 0x00000014 + TimeoutErase = 0x00003A98 + TimeoutProgram = 0x00002710 + TimeoutVerify = 0x00002710 + VerifyType = 1 +[PERFORMANCE] + DisableSkipBlankDataOnProgram = 0x00000000 + PerfromBlankCheckPriorEraseChip = 0x00000001 + PerfromBlankCheckPriorEraseSelectedSectors = 0x00000001 diff --git a/documentation/OTA.md b/documentation/OTA.md index 3e82336c..2a6b0984 100644 --- a/documentation/OTA.md +++ b/documentation/OTA.md @@ -110,7 +110,12 @@ Even if something goes wrong, Updater gives you an option to retry failed operat ## Full package -To build a basic update package, run `./fbt --with-updater COMPACT=1 DEBUG=0 updater_package` +To build full update package, including firmware, radio stack and resources for SD card, run `./fbt COMPACT=1 DEBUG=0 updater_package` + + +## Minimal package + +To build minimal update package, including only firmware, run `./fbt COMPACT=1 DEBUG=0 updater_minpackage` ## Customizing update bundles @@ -118,7 +123,7 @@ To build a basic update package, run `./fbt --with-updater COMPACT=1 DEBUG=0 upd Default update packages are built with Bluetooth Light stack. You can pick a different stack, if your firmware version supports it, and build a bundle with it passing stack type and binary name to `fbt`: -`./fbt --with-updater updater_package COMPACT=1 DEBUG=0 COPRO_OB_DATA=scripts/ob_custradio.data COPRO_STACK_BIN=stm32wb5x_BLE_Stack_full_fw.bin COPRO_STACK_TYPE=ble_full` +`./fbt updater_package COMPACT=1 DEBUG=0 COPRO_OB_DATA=scripts/ob_custradio.data COPRO_STACK_BIN=stm32wb5x_BLE_Stack_full_fw.bin COPRO_STACK_TYPE=ble_full` Note that `COPRO_OB_DATA` must point to a valid file in `scripts` folder containing reference Option Byte data matching to your radio stack type. diff --git a/documentation/fbt.md b/documentation/fbt.md index af10cd9c..7e56672e 100644 --- a/documentation/fbt.md +++ b/documentation/fbt.md @@ -20,7 +20,7 @@ Make sure that `gcc-arm-none-eabi` toolchain & OpenOCD executables are in system To build with FBT, call it specifying configuration options & targets to build. For example, -`./fbt --with-updater COMPACT=1 DEBUG=0 VERBOSE=1 updater_package copro_dist` +`./fbt COMPACT=1 DEBUG=0 VERBOSE=1 updater_package copro_dist` To run cleanup (think of `make clean`) for specified targets, add `-c` option. @@ -31,13 +31,13 @@ FBT keeps track of internal dependencies, so you only need to build the highest- ### High-level (what you most likely need) - `fw_dist` - build & publish firmware to `dist` folder. This is a default target, when no other are specified -- `updater_package` - build self-update package. _Requires `--with-updater` option_ +- `updater_package`, `updater_minpackage` - build self-update package. Minimal version only inclues firmware's DFU file; full version also includes radio stack & resources for SD card - `copro_dist` - bundle Core2 FUS+stack binaries for qFlipper - `flash` - flash attached device with OpenOCD over ST-Link -- `flash_usb` - build, upload and install update package to device over USB. _Requires `--with-updater` option_ +- `flash_usb`, `flash_usb_full` - build, upload and install update package to device over USB. See details on `updater_package`, `updater_minpackage` - `debug` - build and flash firmware, then attach with gdb with firmware's .elf loaded -- `debug_updater` - attach gdb with updater's .elf loaded. _Requires `--with-updater` option_ -- `debug_other` - attach gdb without loading any .elf. Allows to manually add external elf files with `add-symbol-file` in gdb. +- `debug_other` - attach gdb without loading any .elf. Allows to manually add external elf files with `add-symbol-file` in gdb +- `updater_debug` - attach gdb with updater's .elf loaded - `blackmagic` - debug firmware with Blackmagic probe (WiFi dev board) - `openocd` - just start OpenOCD - `get_blackmagic` - output blackmagic address in gdb remote format. Useful for IDE integration @@ -49,9 +49,11 @@ FBT keeps track of internal dependencies, so you only need to build the highest- - Check out `--extra-ext-apps` for force adding extra apps to external build - `firmware_snake_game_list`, etc - generate source + assembler listing for app's .elf - `flash`, `firmware_flash` - flash current version to attached device with OpenOCD over ST-Link +- `jflash` - flash current version to attached device with JFlash using J-Link probe. JFlash executable must be on your $PATH - `flash_blackmagic` - flash current version to attached device with Blackmagic probe - `firmware_all`, `updater_all` - build basic set of binaries - `firmware_list`, `updater_list` - generate source + assembler listing +- `firmware_cdb`, `updater_cdb` - generate `compilation_database.json` file for external tools and IDEs. It can be created without actually building the firmware. ### Assets @@ -66,7 +68,7 @@ FBT keeps track of internal dependencies, so you only need to build the highest- ## Command-line parameters - `--options optionfile.py` (default value `fbt_options.py`) - load file with multiple configuration values -- `--with-updater` - enables updater-related targets and dependency tracking. Enabling this option introduces extra startup time costs, so use it when bundling update packages. Or if you have a fast computer and don't care about a few extra seconds of startup time +- `--with-updater` - enables updater-related targets and dependency tracking. Enabling this option introduces extra startup time costs, so use it when bundling update packages. _Explicily enabling this should no longer be required, fbt now has specific handling for updater-related targets_ - `--extra-int-apps=app1,app2,appN` - forces listed apps to be built as internal with `firmware` target - `--extra-ext-apps=app1,app2,appN` - forces listed apps to be built as external with `firmware_extapps` target diff --git a/fbt_options.py b/fbt_options.py index fb2a0d36..7276f579 100644 --- a/fbt_options.py +++ b/fbt_options.py @@ -80,6 +80,7 @@ FIRMWARE_APPS = { ], "unit_tests": [ "basic_services", + "updater_app", "unit_tests", ], } diff --git a/firmware.scons b/firmware.scons index 438ac8e7..76f0b52d 100644 --- a/firmware.scons +++ b/firmware.scons @@ -9,7 +9,11 @@ from fbt.util import ( # Building initial C environment for libs env = ENV.Clone( - tools=["compilation_db", "fwbin", "fbt_apps"], + tools=[ + ("compilation_db", {"COMPILATIONDB_COMSTR": "\tCDB\t${TARGET}"}), + "fwbin", + "fbt_apps", + ], COMPILATIONDB_USE_ABSPATH=False, BUILD_DIR=fw_build_meta["build_dir"], IS_BASE_FIRMWARE=fw_build_meta["type"] == "firmware", @@ -76,7 +80,6 @@ if not env["VERBOSE"]: HEXCOMSTR="\tHEX\t${TARGET}", BINCOMSTR="\tBIN\t${TARGET}", DFUCOMSTR="\tDFU\t${TARGET}", - OPENOCDCOMSTR="\tFLASH\t${SOURCE}", ) @@ -139,7 +142,7 @@ apps_c = fwenv.ApplicationsC( Value(fwenv["APPS"]), ) # Adding dependency on manifest files so apps.c is rebuilt when any manifest is changed -fwenv.Depends(apps_c, fwenv.GlobRecursive("*.fam", "applications")) +fwenv.Depends(apps_c, fwenv.GlobRecursive("*.fam", "#/applications")) sources = [apps_c] # Gather sources only from app folders in current configuration @@ -164,6 +167,8 @@ fwenv.AppendUnique( "-u", "_printf_float", "-n", + "-Xlinker", + "-Map=${TARGET}.map", ], ) @@ -202,7 +207,6 @@ fwelf = fwenv["FW_ELF"] = fwenv.Program( ], ) -# Make it depend on everything child builders returned # Firmware depends on everything child builders returned Depends(fwelf, lib_targets) # Output extra details after building firmware @@ -232,7 +236,8 @@ if should_gen_cdb_and_link_dir(fwenv, BUILD_TARGETS): fwcdb = fwenv.CompilationDatabase() # without filtering, both updater & firmware commands would be generated fwenv.Replace(COMPILATIONDB_PATH_FILTER=fwenv.subst("*${FW_FLAVOR}*")) - Depends(fwcdb, fwelf) + AlwaysBuild(fwcdb) + Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_cdb", fwcdb) fw_artifacts.append(fwcdb) # Adding as a phony target, so folder link is updated even if elf didn't change diff --git a/firmware/targets/f7/stm32wb55xx_flash.ld b/firmware/targets/f7/stm32wb55xx_flash.ld index 1d0e916b..20314ba3 100644 --- a/firmware/targets/f7/stm32wb55xx_flash.ld +++ b/firmware/targets/f7/stm32wb55xx_flash.ld @@ -75,6 +75,7 @@ SECTIONS .text : { . = ALIGN(4); + *lib*.a:*(.text .text.*) /* code from libraries before apps */ *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.glue_7) /* glue arm to thumb code */ diff --git a/scripts/flipper/storage.py b/scripts/flipper/storage.py index 3d1b46b9..5fa8a2c8 100644 --- a/scripts/flipper/storage.py +++ b/scripts/flipper/storage.py @@ -53,13 +53,14 @@ class FlipperStorage: CLI_PROMPT = ">: " CLI_EOL = "\r\n" - def __init__(self, portname: str, portbaud: int = 115200): + def __init__(self, portname: str, chunk_size: int = 8192): self.port = serial.Serial() self.port.port = portname self.port.timeout = 2 - self.port.baudrate = portbaud + self.port.baudrate = 115200 # Doesn't matter for VCP self.read = BufferedRead(self.port) self.last_error = "" + self.chunk_size = chunk_size def start(self): self.port.open() @@ -192,7 +193,7 @@ class FlipperStorage: with open(filename_from, "rb") as file: filesize = os.fstat(file.fileno()).st_size - buffer_size = 512 + buffer_size = self.chunk_size while True: filedata = file.read(buffer_size) size = len(filedata) @@ -221,7 +222,7 @@ class FlipperStorage: def read_file(self, filename): """Receive file from Flipper, and get filedata (bytes)""" - buffer_size = 512 + buffer_size = self.chunk_size self.send_and_wait_eol( 'storage read_chunks "' + filename + '" ' + str(buffer_size) + "\r" ) @@ -355,7 +356,7 @@ class FlipperStorage: """Hash of local file""" hash_md5 = hashlib.md5() with open(filename, "rb") as f: - for chunk in iter(lambda: f.read(4096), b""): + for chunk in iter(lambda: f.read(self.chunk_size), b""): hash_md5.update(chunk) return hash_md5.hexdigest() diff --git a/scripts/selfupdate.py b/scripts/selfupdate.py index 6d705747..1c16c5ca 100644 --- a/scripts/selfupdate.py +++ b/scripts/selfupdate.py @@ -14,14 +14,6 @@ import serial.tools.list_ports as list_ports class Main(App): def init(self): self.parser.add_argument("-p", "--port", help="CDC Port", default="auto") - self.parser.add_argument( - "-b", - "--baud", - help="Port Baud rate", - required=False, - default=115200 * 4, - type=int, - ) self.parser.add_argument("manifest_path", help="Manifest path") self.parser.add_argument( @@ -64,7 +56,7 @@ class Main(App): if not (port := resolve_port(self.logger, self.args.port)): return 1 - storage = FlipperStorage(port, self.args.baud) + storage = FlipperStorage(port) storage.start() try: @@ -99,6 +91,7 @@ class Main(App): self.logger.error(f"Error: {storage.last_error}") return -3 + # return -11 storage.send_and_wait_eol( f"update install {flipper_update_path}/{manifest_name}\r" ) diff --git a/scripts/storage.py b/scripts/storage.py index 0ddc2fc0..167ba88e 100755 --- a/scripts/storage.py +++ b/scripts/storage.py @@ -14,14 +14,7 @@ import tempfile class Main(App): def init(self): self.parser.add_argument("-p", "--port", help="CDC Port", default="auto") - self.parser.add_argument( - "-b", - "--baud", - help="Port Baud rate", - required=False, - default=115200 * 4, - type=int, - ) + self.subparsers = self.parser.add_subparsers(help="sub-command help") self.parser_mkdir = self.subparsers.add_parser("mkdir", help="Create directory") @@ -77,7 +70,7 @@ class Main(App): if not (port := resolve_port(self.logger, self.args.port)): return None - storage = FlipperStorage(port, self.args.baud) + storage = FlipperStorage(port) storage.start() return storage diff --git a/site_scons/site_tools/fbt_apps.py b/site_scons/site_tools/fbt_apps.py index a0c43fa7..aaf08bfa 100644 --- a/site_scons/site_tools/fbt_apps.py +++ b/site_scons/site_tools/fbt_apps.py @@ -2,6 +2,7 @@ from SCons.Builder import Builder from SCons.Action import Action from SCons.Warnings import warn, WarningOnByDefault import SCons +import os.path from fbt.appmanifest import ( FlipperAppType, @@ -17,10 +18,12 @@ from fbt.appmanifest import ( def LoadApplicationManifests(env): appmgr = env["APPMGR"] = AppManager() - for entry in env.Glob("#/applications/*", source=True): + for entry in env.Glob("#/applications/*", ondisk=True, source=True): if isinstance(entry, SCons.Node.FS.Dir) and not str(entry).startswith("."): try: - appmgr.load_manifest(entry.File("application.fam").abspath, entry.name) + appmgr.load_manifest( + os.path.join(entry.abspath, "application.fam"), entry.name + ) except FlipperManifestException as e: warn(WarningOnByDefault, str(e)) diff --git a/site_scons/site_tools/fbt_dist.py b/site_scons/site_tools/fbt_dist.py index 7c28c69c..399b7ecd 100644 --- a/site_scons/site_tools/fbt_dist.py +++ b/site_scons/site_tools/fbt_dist.py @@ -66,9 +66,38 @@ def AddOpenOCDFlashTarget(env, targetenv, **kw): **kw, ) env.Alias(targetenv.subst("${FIRMWARE_BUILD_CFG}_flash"), openocd_target) + if env["FORCE"]: + env.AlwaysBuild(openocd_target) return openocd_target +def AddJFlashTarget(env, targetenv, **kw): + jflash_target = env.JFlash( + "#build/jflash-${BUILD_CFG}-flash.flag", + targetenv["FW_BIN"], + JFLASHADDR=targetenv.subst("$IMAGE_BASE_ADDRESS"), + BUILD_CFG=targetenv.subst("${FIRMWARE_BUILD_CFG}"), + **kw, + ) + env.Alias(targetenv.subst("${FIRMWARE_BUILD_CFG}_jflash"), jflash_target) + if env["FORCE"]: + env.AlwaysBuild(jflash_target) + return jflash_target + + +def AddUsbFlashTarget(env, file_flag, extra_deps, **kw): + usb_update = env.UsbInstall( + file_flag, + ( + env["DIST_DEPENDS"], + *extra_deps, + ), + ) + if env["FORCE"]: + env.AlwaysBuild(usb_update) + return usb_update + + def DistCommand(env, name, source, **kw): target = f"dist_{name}" command = env.Command( @@ -86,6 +115,8 @@ def generate(env): env.AddMethod(AddFwProject) env.AddMethod(DistCommand) env.AddMethod(AddOpenOCDFlashTarget) + env.AddMethod(AddJFlashTarget) + env.AddMethod(AddUsbFlashTarget) env.SetDefault( COPRO_MCU_FAMILY="STM32WB5x", diff --git a/site_scons/site_tools/jflash.py b/site_scons/site_tools/jflash.py new file mode 100644 index 00000000..aea7279b --- /dev/null +++ b/site_scons/site_tools/jflash.py @@ -0,0 +1,27 @@ +from SCons.Builder import Builder +from SCons.Defaults import Touch + + +def generate(env): + env.SetDefault( + JFLASH="JFlash" if env.subst("$PLATFORM") == "win32" else "JFlashExe", + JFLASHFLAGS=[ + "-auto", + "-exit", + ], + JFLASHCOM="${JFLASH} -openprj${JFLASHPROJECT} -open${SOURCE},${JFLASHADDR} ${JFLASHFLAGS}", + ) + env.Append( + BUILDERS={ + "JFlash": Builder( + action=[ + "${JFLASHCOM}", + Touch("${TARGET}"), + ], + ), + } + ) + + +def exists(env): + return True