Flipper Zero 固件应用清单(FAM)详解
什么是FAM
Flipper Zero 固件采用模块化设计,所有组件(包括系统服务、用户应用和系统设置)都是独立开发的。每个组件都有一个名为 application.fam
的构建系统清单文件,这个文件定义了组件的基本属性以及与其他系统部分的关系。
FAM的核心作用
在构建固件时,构建工具会收集所有应用清单并处理它们的依赖关系。然后仅构建当前构建配置中引用的那些组件。这种设计带来了几个显著优势:
- 模块化开发:开发者可以专注于单个应用的开发,无需关心整个系统的复杂性
- 按需构建:减少不必要的编译,提高构建效率
- 依赖管理:自动处理应用间的依赖关系
- 冲突检测:防止不兼容的应用被同时构建
应用定义详解
每个固件组件的属性都是通过调用 App()
函数并传入各种参数来声明的。这些参数可以分为必需参数和可选参数两大类。
必需参数
-
appid:字符串类型,表示应用在构建系统中的唯一标识符。它用于:
- 指定要包含在构建配置中的应用
- 解析依赖关系
- 检测冲突
-
apptype:FlipperAppType 枚举成员,定义应用类型。有效值包括:
| 类型 | 说明 | |--------------|----------------------------------------------------------------------| | SERVICE | 系统服务,在系统启动早期创建 | | SYSTEM | 不在任何菜单中显示,可由其他应用或CLI启动 | | APP | 主菜单中的常规应用 | | PLUGIN | 作为固件一部分构建并放置在插件菜单中的应用 | | DEBUG | 仅在调试模式下可见的调试菜单应用 | | ARCHIVE | 唯一的归档应用 | | SETTINGS | 系统设置菜单中的应用 | | STARTUP | 系统启动时运行的回调函数,不定义单独的应用 | | EXTERNAL | 构建为.fap插件的应用 | | METAPACKAGE | 不定义任何可运行代码,仅用于声明依赖关系和应用包 |
常用可选参数
- name:在菜单中显示的名称
- entry_point:用作应用入口点的C函数
- stack_size:为应用分配的堆栈大小(字节)
- icon:内置资源中的动画图标名称
- order:应用在其组中的排序位置
- requires:构建当前应用时需要包含的其他应用ID列表
- conflicts:与当前应用冲突的应用ID列表
内存管理技巧
stack_size
参数需要特别注意:
- 分配过小会导致栈溢出和系统崩溃
- 分配过大会减少可用堆内存
- 可以使用
top
和free
CLI命令分析应用的内存使用情况
外部应用(FAP)专用参数
对于构建为外部插件(.fap文件)的应用,有一些特殊参数:
- fap_version:应用版本号,默认为"0.1"
- fap_icon:嵌入.fap文件的10x10像素1位色深PNG图标
- fap_category:应用子类别,也决定文件系统中的路径
- fap_description:简短的应用描述
- fap_author:应用作者
- fap_weburl:应用主页
高级构建功能
外部构建支持
通过 fap_extbuild
参数可以支持使用外部工具构建部分应用源代码。例如构建Rust应用:
sources=["target/thumbv7em-none-eabihf/release/libhello_rust.a"],
fap_extbuild=(
ExtFile(
path="${FAP_WORK_DIR}/target/thumbv7em-none-eabihf/release/libhello_rust.a",
command="cargo build --release --verbose --target thumbv7em-none-eabihf --target-dir ${FAP_WORK_DIR}/target --manifest-path ${FAP_SRC_DIR}/Cargo.toml",
),
),
私有库支持
通过 fap_private_libs
可以包含与应用一起分发的库源代码。这些库将作为应用构建过程的一部分进行构建。例如:
fap_private_libs=[
Lib(
name="mbedtls",
fap_include_paths=["include"],
sources=[
"library/des.c",
"library/sha1.c",
"library/platform_util.c",
],
cdefines=["MBEDTLS_ERROR_C"],
),
Lib(
name="loclass",
cflags=["-Wno-error"],
),
],
实际应用示例
以下是蓝牙服务的部分FAM定义:
App(
appid="bt_start",
apptype=FlipperAppType.STARTUP,
entry_point="bt_on_system_start",
order=70,
)
App(
appid="bt_settings",
name="Bluetooth",
apptype=FlipperAppType.SETTINGS,
entry_point="bt_settings_app",
stack_size=1 * 1024,
requires=[
"bt",
"gui",
],
order=10,
)
最佳实践建议
- 合理设置堆栈大小:根据应用实际需求设置,避免浪费内存
- 明确依赖关系:准确声明requires和conflicts参数
- 版本控制:为外部应用设置适当的版本号
- 资源优化:合理使用图标和资源,避免固件体积过大
- 模块化设计:将大型功能拆分为独立模块,便于维护和更新
通过理解和正确使用FAM文件,开发者可以高效地为Flipper Zero开发各种功能模块,同时确保系统的稳定性和可维护性。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考