mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-22 20:43:07 +00:00
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:
parent
9e452d2b26
commit
e1ffb4ac4d
10 changed files with 87 additions and 35 deletions
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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
52
scripts/fwsize.py
Normal 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()()
|
|
@ -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",
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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())
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
Loading…
Reference in a new issue