fbt fixes & improvements (#1490)
* 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: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									1e732830ec
								
							
						
					
					
						commit
						a1637e9216
					
				
							
								
								
									
										4
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @ -78,7 +78,7 @@ jobs: | |||||||
|             set -e |             set -e | ||||||
|             for TARGET in ${TARGETS} |             for TARGET in ${TARGETS} | ||||||
|             do |             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 |             done | ||||||
| 
 | 
 | ||||||
|       - name: 'Move upload files' |       - name: 'Move upload files' | ||||||
| @ -214,5 +214,5 @@ jobs: | |||||||
|             set -e |             set -e | ||||||
|             for TARGET in ${TARGETS} |             for TARGET in ${TARGETS} | ||||||
|             do |             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 |             done | ||||||
|  | |||||||
| @ -29,11 +29,11 @@ They both must be flashed in the order described. | |||||||
| 
 | 
 | ||||||
| With Flipper attached over USB: | With Flipper attached over USB: | ||||||
| 
 | 
 | ||||||
| `./fbt --with-updater flash_usb` | `./fbt flash_usb` | ||||||
| 
 | 
 | ||||||
| Just building the package: | 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.  | To update, copy the resulting directory to Flipper's SD card and navigate to `update.fuf` file in Archive app.  | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										66
									
								
								SConstruct
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								SConstruct
									
									
									
									
									
								
							| @ -33,8 +33,10 @@ coreenv["ROOT_DIR"] = Dir(".") | |||||||
| 
 | 
 | ||||||
| # Create a separate "dist" environment and add construction envs to it | # Create a separate "dist" environment and add construction envs to it | ||||||
| distenv = coreenv.Clone( | distenv = coreenv.Clone( | ||||||
|     tools=["fbt_dist", "openocd", "blackmagic"], |     tools=["fbt_dist", "openocd", "blackmagic", "jflash"], | ||||||
|     OPENOCD_GDB_PIPE=["|openocd -c 'gdb_port pipe; log_output debug/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}"], |     OPENOCD_GDB_PIPE=[ | ||||||
|  |         "|openocd -c 'gdb_port pipe; log_output debug/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}" | ||||||
|  |     ], | ||||||
|     GDBOPTS_BASE=[ |     GDBOPTS_BASE=[ | ||||||
|         "-ex", |         "-ex", | ||||||
|         "target extended-remote ${GDBREMOTE}", |         "target extended-remote ${GDBREMOTE}", | ||||||
| @ -61,6 +63,7 @@ distenv = coreenv.Clone( | |||||||
|         "-ex", |         "-ex", | ||||||
|         "compare-sections", |         "compare-sections", | ||||||
|     ], |     ], | ||||||
|  |     JFLASHPROJECT="${ROOT_DIR.abspath}/debug/fw.jflash", | ||||||
|     ENV=os.environ, |     ENV=os.environ, | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -71,7 +74,9 @@ firmware_env = distenv.AddFwProject( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| # If enabled, initialize updater-related targets | # 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( |     updater_env = distenv.AddFwProject( | ||||||
|         base_env=coreenv, |         base_env=coreenv, | ||||||
|         fw_type="updater", |         fw_type="updater", | ||||||
| @ -79,11 +84,11 @@ if GetOption("fullenv"): | |||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     # Target for self-update package |     # Target for self-update package | ||||||
|     dist_arguments = [ |     dist_basic_arguments = [ | ||||||
|         "-r", |  | ||||||
|         '"${ROOT_DIR.abspath}/assets/resources"', |  | ||||||
|         "--bundlever", |         "--bundlever", | ||||||
|         '"${UPDATE_VERSION_STRING}"', |         '"${UPDATE_VERSION_STRING}"', | ||||||
|  |     ] | ||||||
|  |     dist_radio_arguments = [ | ||||||
|         "--radio", |         "--radio", | ||||||
|         '"${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}"', |         '"${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}"', | ||||||
|         "--radiotype", |         "--radiotype", | ||||||
| @ -92,16 +97,34 @@ if GetOption("fullenv"): | |||||||
|         "--obdata", |         "--obdata", | ||||||
|         '"${ROOT_DIR.abspath}/${COPRO_OB_DATA}"', |         '"${ROOT_DIR.abspath}/${COPRO_OB_DATA}"', | ||||||
|     ] |     ] | ||||||
|     if distenv["UPDATE_SPLASH"]: |     dist_resource_arguments = [ | ||||||
|         dist_arguments += [ |         "-r", | ||||||
|  |         '"${ROOT_DIR.abspath}/assets/resources"', | ||||||
|  |     ] | ||||||
|  |     dist_splash_arguments = ( | ||||||
|  |         [ | ||||||
|             "--splash", |             "--splash", | ||||||
|             distenv.subst("assets/slideshow/$UPDATE_SPLASH"), |             distenv.subst("assets/slideshow/$UPDATE_SPLASH"), | ||||||
|         ] |         ] | ||||||
|  |         if distenv["UPDATE_SPLASH"] | ||||||
|  |         else [] | ||||||
|  |     ) | ||||||
| 
 | 
 | ||||||
|     selfupdate_dist = distenv.DistCommand( |     selfupdate_dist = distenv.DistCommand( | ||||||
|         "updater_package", |         "updater_package", | ||||||
|         (distenv["DIST_DEPENDS"], firmware_env["FW_RESOURCES"]), |         (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 |     # Updater debug | ||||||
| @ -121,18 +144,16 @@ if GetOption("fullenv"): | |||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     # Installation over USB & CLI |     # Installation over USB & CLI | ||||||
|     usb_update_package = distenv.UsbInstall( |     usb_update_package = distenv.AddUsbFlashTarget( | ||||||
|         "#build/usbinstall.flag", |         "#build/usbinstall.flag", (firmware_env["FW_RESOURCES"], selfupdate_dist) | ||||||
|         ( |  | ||||||
|             distenv["DIST_DEPENDS"], |  | ||||||
|             firmware_env["FW_RESOURCES"], |  | ||||||
|             selfupdate_dist, |  | ||||||
|         ), |  | ||||||
|     ) |     ) | ||||||
|     if distenv["FORCE"]: |     distenv.Alias("flash_usb_full", usb_update_package) | ||||||
|         distenv.AlwaysBuild(usb_update_package) | 
 | ||||||
|     distenv.Depends(usb_update_package, selfupdate_dist) |     usb_minupdate_package = distenv.AddUsbFlashTarget( | ||||||
|     distenv.Alias("flash_usb", usb_update_package) |         "#build/minusbinstall.flag", (selfupdate_min_dist,) | ||||||
|  |     ) | ||||||
|  |     distenv.Alias("flash_usb", usb_minupdate_package) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| # Target for copying & renaming binaries to dist folder | # Target for copying & renaming binaries to dist folder | ||||||
| basic_dist = distenv.DistCommand("fw_dist", distenv["DIST_DEPENDS"]) | 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) | firmware_flash = distenv.AddOpenOCDFlashTarget(firmware_env) | ||||||
| distenv.Alias("flash", firmware_flash) | 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( | firmware_bm_flash = distenv.PhonyTarget( | ||||||
|     "flash_blackmagic", |     "flash_blackmagic", | ||||||
|  | |||||||
| @ -38,6 +38,8 @@ appenv.AppendUnique( | |||||||
|         "-Wl,--no-export-dynamic", |         "-Wl,--no-export-dynamic", | ||||||
|         "-fvisibility=hidden", |         "-fvisibility=hidden", | ||||||
|         "-Wl,-e${APP_ENTRY}", |         "-Wl,-e${APP_ENTRY}", | ||||||
|  |         "-Xlinker", | ||||||
|  |         "-Map=${TARGET}.map", | ||||||
|     ], |     ], | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										90
									
								
								debug/fw.jflash
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								debug/fw.jflash
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||||
| @ -110,7 +110,12 @@ Even if something goes wrong, Updater gives you an option to retry failed operat | |||||||
| 
 | 
 | ||||||
| ## Full package | ## 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 | ## 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.  | 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`:  | 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. | 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. | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -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, | 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. | 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) | ### 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 | - `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 | - `copro_dist` - bundle Core2 FUS+stack binaries for qFlipper | ||||||
| - `flash` - flash attached device with OpenOCD over ST-Link | - `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` - 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) | - `blackmagic` - debug firmware with Blackmagic probe (WiFi dev board) | ||||||
| - `openocd` - just start OpenOCD | - `openocd` - just start OpenOCD | ||||||
| - `get_blackmagic` - output blackmagic address in gdb remote format. Useful for IDE integration | - `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  |     - 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 |     - `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 | - `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 | - `flash_blackmagic` - flash current version to attached device with Blackmagic probe | ||||||
| - `firmware_all`, `updater_all` - build basic set of binaries | - `firmware_all`, `updater_all` - build basic set of binaries | ||||||
| - `firmware_list`, `updater_list` - generate source + assembler listing | - `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 | ### Assets | ||||||
| 
 | 
 | ||||||
| @ -66,7 +68,7 @@ FBT keeps track of internal dependencies, so you only need to build the highest- | |||||||
| ## Command-line parameters | ## Command-line parameters | ||||||
| 
 | 
 | ||||||
| - `--options optionfile.py` (default value `fbt_options.py`) - load file with multiple configuration values | - `--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-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 | - `--extra-ext-apps=app1,app2,appN` - forces listed apps to be built as external with `firmware_extapps` target | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -80,6 +80,7 @@ FIRMWARE_APPS = { | |||||||
|     ], |     ], | ||||||
|     "unit_tests": [ |     "unit_tests": [ | ||||||
|         "basic_services", |         "basic_services", | ||||||
|  |         "updater_app", | ||||||
|         "unit_tests", |         "unit_tests", | ||||||
|     ], |     ], | ||||||
| } | } | ||||||
|  | |||||||
| @ -9,7 +9,11 @@ from fbt.util import ( | |||||||
| 
 | 
 | ||||||
| # Building initial C environment for libs | # Building initial C environment for libs | ||||||
| env = ENV.Clone( | env = ENV.Clone( | ||||||
|     tools=["compilation_db", "fwbin", "fbt_apps"], |     tools=[ | ||||||
|  |         ("compilation_db", {"COMPILATIONDB_COMSTR": "\tCDB\t${TARGET}"}), | ||||||
|  |         "fwbin", | ||||||
|  |         "fbt_apps", | ||||||
|  |     ], | ||||||
|     COMPILATIONDB_USE_ABSPATH=False, |     COMPILATIONDB_USE_ABSPATH=False, | ||||||
|     BUILD_DIR=fw_build_meta["build_dir"], |     BUILD_DIR=fw_build_meta["build_dir"], | ||||||
|     IS_BASE_FIRMWARE=fw_build_meta["type"] == "firmware", |     IS_BASE_FIRMWARE=fw_build_meta["type"] == "firmware", | ||||||
| @ -76,7 +80,6 @@ if not env["VERBOSE"]: | |||||||
|         HEXCOMSTR="\tHEX\t${TARGET}", |         HEXCOMSTR="\tHEX\t${TARGET}", | ||||||
|         BINCOMSTR="\tBIN\t${TARGET}", |         BINCOMSTR="\tBIN\t${TARGET}", | ||||||
|         DFUCOMSTR="\tDFU\t${TARGET}", |         DFUCOMSTR="\tDFU\t${TARGET}", | ||||||
|         OPENOCDCOMSTR="\tFLASH\t${SOURCE}", |  | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -139,7 +142,7 @@ apps_c = fwenv.ApplicationsC( | |||||||
|     Value(fwenv["APPS"]), |     Value(fwenv["APPS"]), | ||||||
| ) | ) | ||||||
| # Adding dependency on manifest files so apps.c is rebuilt when any manifest is changed | # 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] | sources = [apps_c] | ||||||
| # Gather sources only from app folders in current configuration | # Gather sources only from app folders in current configuration | ||||||
| @ -164,6 +167,8 @@ fwenv.AppendUnique( | |||||||
|         "-u", |         "-u", | ||||||
|         "_printf_float", |         "_printf_float", | ||||||
|         "-n", |         "-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 | # Firmware depends on everything child builders returned | ||||||
| Depends(fwelf, lib_targets) | Depends(fwelf, lib_targets) | ||||||
| # Output extra details after building firmware | # Output extra details after building firmware | ||||||
| @ -232,7 +236,8 @@ if should_gen_cdb_and_link_dir(fwenv, BUILD_TARGETS): | |||||||
|     fwcdb = fwenv.CompilationDatabase() |     fwcdb = fwenv.CompilationDatabase() | ||||||
|     # without filtering, both updater & firmware commands would be generated |     # without filtering, both updater & firmware commands would be generated | ||||||
|     fwenv.Replace(COMPILATIONDB_PATH_FILTER=fwenv.subst("*${FW_FLAVOR}*")) |     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) |     fw_artifacts.append(fwcdb) | ||||||
| 
 | 
 | ||||||
|     # Adding as a phony target, so folder link is updated even if elf didn't change |     # Adding as a phony target, so folder link is updated even if elf didn't change | ||||||
|  | |||||||
| @ -75,6 +75,7 @@ SECTIONS | |||||||
|   .text : |   .text : | ||||||
|   { |   { | ||||||
|     . = ALIGN(4); |     . = ALIGN(4); | ||||||
|  |     *lib*.a:*(.text .text.*) /* code from libraries before apps */ | ||||||
|     *(.text)           /* .text sections (code) */ |     *(.text)           /* .text sections (code) */ | ||||||
|     *(.text*)          /* .text* sections (code) */ |     *(.text*)          /* .text* sections (code) */ | ||||||
|     *(.glue_7)         /* glue arm to thumb code */ |     *(.glue_7)         /* glue arm to thumb code */ | ||||||
|  | |||||||
| @ -53,13 +53,14 @@ class FlipperStorage: | |||||||
|     CLI_PROMPT = ">: " |     CLI_PROMPT = ">: " | ||||||
|     CLI_EOL = "\r\n" |     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 = serial.Serial() | ||||||
|         self.port.port = portname |         self.port.port = portname | ||||||
|         self.port.timeout = 2 |         self.port.timeout = 2 | ||||||
|         self.port.baudrate = portbaud |         self.port.baudrate = 115200  # Doesn't matter for VCP | ||||||
|         self.read = BufferedRead(self.port) |         self.read = BufferedRead(self.port) | ||||||
|         self.last_error = "" |         self.last_error = "" | ||||||
|  |         self.chunk_size = chunk_size | ||||||
| 
 | 
 | ||||||
|     def start(self): |     def start(self): | ||||||
|         self.port.open() |         self.port.open() | ||||||
| @ -192,7 +193,7 @@ class FlipperStorage: | |||||||
|         with open(filename_from, "rb") as file: |         with open(filename_from, "rb") as file: | ||||||
|             filesize = os.fstat(file.fileno()).st_size |             filesize = os.fstat(file.fileno()).st_size | ||||||
| 
 | 
 | ||||||
|             buffer_size = 512 |             buffer_size = self.chunk_size | ||||||
|             while True: |             while True: | ||||||
|                 filedata = file.read(buffer_size) |                 filedata = file.read(buffer_size) | ||||||
|                 size = len(filedata) |                 size = len(filedata) | ||||||
| @ -221,7 +222,7 @@ class FlipperStorage: | |||||||
| 
 | 
 | ||||||
|     def read_file(self, filename): |     def read_file(self, filename): | ||||||
|         """Receive file from Flipper, and get filedata (bytes)""" |         """Receive file from Flipper, and get filedata (bytes)""" | ||||||
|         buffer_size = 512 |         buffer_size = self.chunk_size | ||||||
|         self.send_and_wait_eol( |         self.send_and_wait_eol( | ||||||
|             'storage read_chunks "' + filename + '" ' + str(buffer_size) + "\r" |             'storage read_chunks "' + filename + '" ' + str(buffer_size) + "\r" | ||||||
|         ) |         ) | ||||||
| @ -355,7 +356,7 @@ class FlipperStorage: | |||||||
|         """Hash of local file""" |         """Hash of local file""" | ||||||
|         hash_md5 = hashlib.md5() |         hash_md5 = hashlib.md5() | ||||||
|         with open(filename, "rb") as f: |         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) |                 hash_md5.update(chunk) | ||||||
|         return hash_md5.hexdigest() |         return hash_md5.hexdigest() | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -14,14 +14,6 @@ import serial.tools.list_ports as list_ports | |||||||
| class Main(App): | class Main(App): | ||||||
|     def init(self): |     def init(self): | ||||||
|         self.parser.add_argument("-p", "--port", help="CDC Port", default="auto") |         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("manifest_path", help="Manifest path") | ||||||
|         self.parser.add_argument( |         self.parser.add_argument( | ||||||
| @ -64,7 +56,7 @@ class Main(App): | |||||||
|         if not (port := resolve_port(self.logger, self.args.port)): |         if not (port := resolve_port(self.logger, self.args.port)): | ||||||
|             return 1 |             return 1 | ||||||
| 
 | 
 | ||||||
|         storage = FlipperStorage(port, self.args.baud) |         storage = FlipperStorage(port) | ||||||
|         storage.start() |         storage.start() | ||||||
| 
 | 
 | ||||||
|         try: |         try: | ||||||
| @ -99,6 +91,7 @@ class Main(App): | |||||||
|                         self.logger.error(f"Error: {storage.last_error}") |                         self.logger.error(f"Error: {storage.last_error}") | ||||||
|                         return -3 |                         return -3 | ||||||
| 
 | 
 | ||||||
|  |                 # return -11 | ||||||
|                 storage.send_and_wait_eol( |                 storage.send_and_wait_eol( | ||||||
|                     f"update install {flipper_update_path}/{manifest_name}\r" |                     f"update install {flipper_update_path}/{manifest_name}\r" | ||||||
|                 ) |                 ) | ||||||
|  | |||||||
| @ -14,14 +14,7 @@ import tempfile | |||||||
| class Main(App): | class Main(App): | ||||||
|     def init(self): |     def init(self): | ||||||
|         self.parser.add_argument("-p", "--port", help="CDC Port", default="auto") |         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.subparsers = self.parser.add_subparsers(help="sub-command help") | ||||||
| 
 | 
 | ||||||
|         self.parser_mkdir = self.subparsers.add_parser("mkdir", help="Create directory") |         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)): |         if not (port := resolve_port(self.logger, self.args.port)): | ||||||
|             return None |             return None | ||||||
| 
 | 
 | ||||||
|         storage = FlipperStorage(port, self.args.baud) |         storage = FlipperStorage(port) | ||||||
|         storage.start() |         storage.start() | ||||||
|         return storage |         return storage | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ from SCons.Builder import Builder | |||||||
| from SCons.Action import Action | from SCons.Action import Action | ||||||
| from SCons.Warnings import warn, WarningOnByDefault | from SCons.Warnings import warn, WarningOnByDefault | ||||||
| import SCons | import SCons | ||||||
|  | import os.path | ||||||
| 
 | 
 | ||||||
| from fbt.appmanifest import ( | from fbt.appmanifest import ( | ||||||
|     FlipperAppType, |     FlipperAppType, | ||||||
| @ -17,10 +18,12 @@ from fbt.appmanifest import ( | |||||||
| 
 | 
 | ||||||
| def LoadApplicationManifests(env): | def LoadApplicationManifests(env): | ||||||
|     appmgr = env["APPMGR"] = AppManager() |     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("."): |         if isinstance(entry, SCons.Node.FS.Dir) and not str(entry).startswith("."): | ||||||
|             try: |             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: |             except FlipperManifestException as e: | ||||||
|                 warn(WarningOnByDefault, str(e)) |                 warn(WarningOnByDefault, str(e)) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -66,9 +66,38 @@ def AddOpenOCDFlashTarget(env, targetenv, **kw): | |||||||
|         **kw, |         **kw, | ||||||
|     ) |     ) | ||||||
|     env.Alias(targetenv.subst("${FIRMWARE_BUILD_CFG}_flash"), openocd_target) |     env.Alias(targetenv.subst("${FIRMWARE_BUILD_CFG}_flash"), openocd_target) | ||||||
|  |     if env["FORCE"]: | ||||||
|  |         env.AlwaysBuild(openocd_target) | ||||||
|     return 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): | def DistCommand(env, name, source, **kw): | ||||||
|     target = f"dist_{name}" |     target = f"dist_{name}" | ||||||
|     command = env.Command( |     command = env.Command( | ||||||
| @ -86,6 +115,8 @@ def generate(env): | |||||||
|     env.AddMethod(AddFwProject) |     env.AddMethod(AddFwProject) | ||||||
|     env.AddMethod(DistCommand) |     env.AddMethod(DistCommand) | ||||||
|     env.AddMethod(AddOpenOCDFlashTarget) |     env.AddMethod(AddOpenOCDFlashTarget) | ||||||
|  |     env.AddMethod(AddJFlashTarget) | ||||||
|  |     env.AddMethod(AddUsbFlashTarget) | ||||||
| 
 | 
 | ||||||
|     env.SetDefault( |     env.SetDefault( | ||||||
|         COPRO_MCU_FAMILY="STM32WB5x", |         COPRO_MCU_FAMILY="STM32WB5x", | ||||||
|  | |||||||
							
								
								
									
										27
									
								
								site_scons/site_tools/jflash.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								site_scons/site_tools/jflash.py
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 hedger
						hedger