fbt: support for LOADER_AUTOSTART; post-build size stats (#1594)

* fbt: restored LOADER_AUTOSTART support
* scripts: added fwsize.py wrapper for size command; fbt: changed size post-build stats to fwsize.py call
* fbt: removed size wrapper
* fbt: added stats for binary flash size in pages
* fbt: hint on build options details
* scripts: fixed fwsize.py for *nix
This commit is contained in:
hedger 2022-08-13 01:17:11 +03:00 committed by GitHub
parent 9e452d2b26
commit e1ffb4ac4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 87 additions and 35 deletions

View File

@ -18,6 +18,8 @@ typedef struct {
typedef void (*FlipperOnStartHook)(void); typedef void (*FlipperOnStartHook)(void);
extern const char* FLIPPER_AUTORUN_APP_NAME;
/* Services list /* Services list
* Spawned on startup * Spawned on startup
*/ */

View File

@ -466,9 +466,9 @@ int32_t loader_srv(void* p) {
furi_record_create(RECORD_LOADER, loader_instance); furi_record_create(RECORD_LOADER, loader_instance);
#ifdef LOADER_AUTOSTART if(FLIPPER_AUTORUN_APP_NAME && strlen(FLIPPER_AUTORUN_APP_NAME)) {
loader_start(loader_instance, LOADER_AUTOSTART, NULL); loader_start(loader_instance, FLIPPER_AUTORUN_APP_NAME, NULL);
#endif }
while(1) { while(1) {
uint32_t flags = uint32_t flags =

View File

@ -1,5 +1,7 @@
import posixpath import posixpath
# For more details on these options, run 'fbt -h'
# Default hardware target # Default hardware target
TARGET_HW = 7 TARGET_HW = 7
@ -59,6 +61,9 @@ SVD_FILE = "debug/STM32WB55_CM4.svd"
# Look for blackmagic probe on serial ports and local network # Look for blackmagic probe on serial ports and local network
BLACKMAGIC = "auto" BLACKMAGIC = "auto"
# Application to start on boot
LOADER_AUTOSTART = ""
FIRMWARE_APPS = { FIRMWARE_APPS = {
"default": [ "default": [
"crypto_start", "crypto_start",

View File

@ -139,7 +139,7 @@ fwenv.AppendUnique(
# Depends on virtual value-only node, so it only gets rebuilt when set of apps changes # Depends on virtual value-only node, so it only gets rebuilt when set of apps changes
apps_c = fwenv.ApplicationsC( apps_c = fwenv.ApplicationsC(
"applications/applications.c", "applications/applications.c",
Value(fwenv["APPS"]), [Value(fwenv["APPS"]), Value(fwenv["LOADER_AUTOSTART"])],
) )
# 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"))
@ -210,11 +210,19 @@ fwelf = fwenv["FW_ELF"] = fwenv.Program(
Depends(fwelf, lib_targets) Depends(fwelf, lib_targets)
# Output extra details after building firmware # Output extra details after building firmware
AddPostAction(fwelf, fwenv["APPBUILD_DUMP"]) AddPostAction(fwelf, fwenv["APPBUILD_DUMP"])
AddPostAction(fwelf, Action("@$SIZECOM")) AddPostAction(
fwelf,
Action('${PYTHON3} "${ROOT_DIR}/scripts/fwsize.py" elf ${TARGET}', "Firmware size"),
)
# Produce extra firmware files # Produce extra firmware files
fwhex = fwenv["FW_HEX"] = fwenv.HEXBuilder("${FIRMWARE_BUILD_CFG}") fwhex = fwenv["FW_HEX"] = fwenv.HEXBuilder("${FIRMWARE_BUILD_CFG}")
fwbin = fwenv["FW_BIN"] = fwenv.BINBuilder("${FIRMWARE_BUILD_CFG}") fwbin = fwenv["FW_BIN"] = fwenv.BINBuilder("${FIRMWARE_BUILD_CFG}")
AddPostAction(
fwbin,
Action('@${PYTHON3} "${ROOT_DIR}/scripts/fwsize.py" bin ${TARGET}'),
)
fwdfu = fwenv["FW_DFU"] = fwenv.DFUBuilder("${FIRMWARE_BUILD_CFG}") fwdfu = fwenv["FW_DFU"] = fwenv.DFUBuilder("${FIRMWARE_BUILD_CFG}")
Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_dfu", fwdfu) Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_dfu", fwdfu)

52
scripts/fwsize.py Normal file
View File

@ -0,0 +1,52 @@
#!/usr/bin/env python3
from flipper.app import App
import subprocess
import os
import math
class Main(App):
def init(self):
self.subparsers = self.parser.add_subparsers(help="sub-command help")
self.parser_elfsize = self.subparsers.add_parser("elf", help="Dump elf stats")
self.parser_elfsize.add_argument("elfname", action="store")
self.parser_elfsize.set_defaults(func=self.process_elf)
self.parser_binsize = self.subparsers.add_parser("bin", help="Dump bin stats")
self.parser_binsize.add_argument("binname", action="store")
self.parser_binsize.set_defaults(func=self.process_bin)
def process_elf(self):
all_sizes = subprocess.check_output(
["arm-none-eabi-size", "-A", self.args.elfname], shell=False
)
all_sizes = all_sizes.splitlines()
sections_to_keep = (".text", ".rodata", ".data", ".bss", ".free_flash")
for line in all_sizes:
line = line.decode("utf-8")
parts = line.split()
if len(parts) != 3:
continue
section, size, _ = parts
if section not in sections_to_keep:
continue
print(f"{section:<11} {size:>8} ({(int(size)/1024):6.2f} K)")
return 0
def process_bin(self):
PAGE_SIZE = 4096
binsize = os.path.getsize(self.args.binname)
pages = math.ceil(binsize / PAGE_SIZE)
last_page_state = (binsize % PAGE_SIZE) * 100 / PAGE_SIZE
print(
f"{os.path.basename(self.args.binname):<11}: {pages:>4} flash pages (last page {last_page_state:.02f}% full)"
)
return 0
if __name__ == "__main__":
Main()()

View File

@ -174,6 +174,12 @@ vars.Add(
default="update_default", default="update_default",
) )
vars.Add(
"LOADER_AUTOSTART",
help="Application name to automatically run on Flipper boot",
default="",
)
vars.Add( vars.Add(
"FIRMWARE_APPS", "FIRMWARE_APPS",

View File

@ -200,8 +200,9 @@ class ApplicationsCGenerator:
FlipperAppType.STARTUP: ("FlipperOnStartHook", "FLIPPER_ON_SYSTEM_START"), FlipperAppType.STARTUP: ("FlipperOnStartHook", "FLIPPER_ON_SYSTEM_START"),
} }
def __init__(self, buildset: AppBuildset): def __init__(self, buildset: AppBuildset, autorun_app: str = ""):
self.buildset = buildset self.buildset = buildset
self.autorun = autorun_app
def get_app_ep_forward(self, app: FlipperApplication): def get_app_ep_forward(self, app: FlipperApplication):
if app.apptype == FlipperAppType.STARTUP: if app.apptype == FlipperAppType.STARTUP:
@ -219,7 +220,11 @@ class ApplicationsCGenerator:
.flags = {'|'.join(f"FlipperApplicationFlag{flag}" for flag in app.flags)} }}""" .flags = {'|'.join(f"FlipperApplicationFlag{flag}" for flag in app.flags)} }}"""
def generate(self): def generate(self):
contents = ['#include "applications.h"', "#include <assets_icons.h>"] contents = [
'#include "applications.h"',
"#include <assets_icons.h>",
f'const char* FLIPPER_AUTORUN_APP_NAME = "{self.autorun}";',
]
for apptype in self.APP_TYPE_MAP: for apptype in self.APP_TYPE_MAP:
contents.extend( contents.extend(
map(self.get_app_ep_forward, self.buildset.get_apps_of_type(apptype)) map(self.get_app_ep_forward, self.buildset.get_apps_of_type(apptype))

View File

@ -7,7 +7,6 @@ from SCons.Tool import gnulink
import strip import strip
import gdb import gdb
import objdump import objdump
import size
from SCons.Action import _subproc from SCons.Action import _subproc
import subprocess import subprocess
@ -38,7 +37,7 @@ def _get_tool_version(env, tool):
def generate(env, **kw): def generate(env, **kw):
for orig_tool in (asm, gcc, gxx, ar, gnulink, strip, gdb, objdump, size): for orig_tool in (asm, gcc, gxx, ar, gnulink, strip, gdb, objdump):
orig_tool.generate(env) orig_tool.generate(env)
env.SetDefault( env.SetDefault(
TOOLCHAIN_PREFIX=kw.get("toolchain_prefix"), TOOLCHAIN_PREFIX=kw.get("toolchain_prefix"),
@ -57,7 +56,6 @@ def generate(env, **kw):
"GDB", "GDB",
"GDBPY", "GDBPY",
"OBJDUMP", "OBJDUMP",
"SIZE",
], ],
) )
# Call CC to check version # Call CC to check version

View File

@ -51,7 +51,7 @@ def DumpApplicationConfig(target, source, env):
def build_apps_c(target, source, env): def build_apps_c(target, source, env):
target_file_name = target[0].path target_file_name = target[0].path
gen = ApplicationsCGenerator(env["APPBUILD"]) gen = ApplicationsCGenerator(env["APPBUILD"], env.subst("$LOADER_AUTOSTART"))
with open(target_file_name, "w") as file: with open(target_file_name, "w") as file:
file.write(gen.generate()) file.write(gen.generate())

View File

@ -1,24 +0,0 @@
from SCons.Builder import Builder
from SCons.Action import Action
def generate(env):
env.SetDefault(
SIZE="size",
SIZEFLAGS=[],
SIZECOM="$SIZE $SIZEFLAGS $TARGETS",
)
env.Append(
BUILDERS={
"ELFSize": Builder(
action=Action(
"${SIZECOM}",
"${SIZECOMSTR}",
),
),
}
)
def exists(env):
return True