Flipper Zero Unleashed 固件 GPIO 测试用例全解析:手动控制与 5V OTG 供电验证指南
【免费下载链接】unleashed-firmwareFlipper Zero Unleashed Firmware项目地址: https://gitcode.com/GitHub_Trending/un/unleashed-firmware
本文以 Unleashed 固件仓库中的 GPIO 测试用例文档 为骨架,结合 GPIO 应用源码(applications/main/gpio)与底层硬件抽象实现,系统讲解 GPIO Manual Control(手动控制)场景的完整测试流程:如何通过菜单进入测试界面、如何切换并驱动外接引脚电平、如何开启 5V OTG 供电并验证 LED 指示灯,以及每一步背后的源码实现原理。读者完成阅读后,将能够独立搭建 ST-Link 测试环境,按测试用例逐项验证 GPIO 输出功能,并能对照源码理解引脚枚举、模式切换与 OTG 供电的底层机制。
一、测试用例背景与适用场景
该测试用例属于仓库 documentation/testing 目录下的硬件功能验证体系,用于验证 Flipper Zero 对外排针(GPIO Header)的输出控制能力。它覆盖两个核心验证点:
- 引脚电平手动控制:验证 GPIO 应用能否将排针上的用户可用引脚切换为推挽输出模式,并通过按键将其拉高/拉低;
- 5V 供电输出(OTG):验证设备能否通过板载充电管理芯片(BQ25896)启用 OTG 模式,在 GPIO 的 5V 排针上输出 5V 电源,并驱动外接 LED 指示灯。
该用例的典型执行场景包括:固件改动后的硬件回归测试、新硬件目标(如 F7/F18 开发板)的 GPIO 输出验证,以及使用 ST-Link 等外接调试板时的供电链路检查。
二、测试前置条件与硬件准备
2.1 进入 GPIO 应用
在 Flipper Zero 主菜单中导航至GPIO → Manual Control,即可进入 GPIO 手动控制场景。从源码看,这一路径由 gpio_scene_start.c 中的场景初始化逻辑定义:
- 启动场景是一个可变项列表(
VariableItemList),依次提供三个入口:- USB-UART Bridge(对应
GpioItemUsbUart); - GPIO Manual Control(对应
GpioItemTest,即本文的测试对象); - 5V on GPIO(对应
GpioItemOtg,OTG 开关,见第四节)。
- USB-UART Bridge(对应
当用户选中 "GPIO Manual Control" 并按下确认键时,回调gpio_scene_start_var_list_enter_callback会发送自定义事件GpioStartEventManualControl,随后gpio_scene_start_on_event将其转入GpioSceneTest场景,最终由 gpio_scene_test.c 完成界面切换。
注:整个 GPIO 应用在 application.fam 中声明为
apptype=FlipperAppType.MENUEXTERNAL、fap_category="GPIO",入口函数为gpio_app,可作为独立 FAP 应用(扩展应用)从应用商店/外部加载,也可内置于固件。
2.2 连接 ST-Link 开发板与 LED
测试用例要求将 ST-Link 开发板插入 Flipper 的 GPIO 排针,并在对应引脚上接入不同颜色的 LED:
- 硬件连接:ST-Link 开发板的引脚与 Flipper GPIO 排针物理对接(注意排针间距与引脚编号对齐);
- LED 接入:在不同 GPIO 输出引脚上分别串联限流电阻接入不同颜色的 LED(如红、绿、蓝),用于直观区分多个引脚的电平状态;
- 5V 供电链路:确认测试用例中"开启 5V"步骤所需的外部 LED 供电指示灯(下文第四节)连接正确。
预期结果 1:进入测试界面后,可以通过应用界面切换引脚并驱动其输出电平,即"pins are managed from the app"——外接 LED 会随按键操作点亮/熄灭。
三、GPIO Manual Control 测试步骤与源码级操作原理
3.1 引脚列表的构建:哪些引脚可被测试
进入手动控制场景前,应用会枚举设备上所有可用的 GPIO 引脚。这一步在 gpio_items_alloc 中完成:
GPIOItems* gpio_items_alloc(void) { GPIOItems* items = malloc(sizeof(GPIOItems)); items->count = 0; for(size_t i = 0; i < gpio_pins_count; i++) { if(!gpio_pins[i].debug) { items->count++; } } // ... 将非 debug 引脚复制到 items->pins }其核心逻辑是遍历全局引脚表gpio_pins[](定义于 targets/f7/furi_hal/furi_hal_resources.c),只保留debug == false的引脚,即排除 SWD 调试口(PA13/PA14)、USART 串口(PB6/PB7)、iButton(PB14)以及标注为 Dangerous 的引脚(PB8 扬声器、PB9 红外发射管)。最终暴露给用户的可用引脚(F7 目标)为:
| 排针编号 | 引脚名 | 备注 |
|---|---|---|
| 2 | PA7 | 支持 ADC(CH12)与 PWM(TIM1) |
| 3 | PA6 | 支持 ADC(CH11) |
| 4 | PA4 | 支持 ADC(CH9)与 PWM(LPTIM2) |
| 5 | PB3 | 纯数字引脚 |
| 6 | PB2 | 纯数字引脚 |
| 7 | PC3 | 支持 ADC(CH4) |
| 15 | PC1 | 支持 ADC(CH2) |
| 16 | PC0 | 支持 ADC(CH1) |
引脚编号与排针丝印对应(1 号为 5V、8/11/18 号为 GND、9 号为 3V3,不参与输出控制)。引脚表的末尾还列出了 PB8(扬声器)与 PB9(红外发射)两个
number = 0的危险引脚,它们被标记为debug = true,因此在手动控制界面中不可选,防止误操作损坏硬件。
3.2 进入测试场景时的引脚初始化
在 gpio_scene_test_on_enter 中,进入场景的第一件事是把所有用户引脚统一配置为推挽输出:
void gpio_scene_test_on_enter(void* context) { GpioApp* app = context; gpio_items_configure_all_pins(app->gpio_items, GpioModeOutputPushPull); gpio_test_set_ok_callback(app->gpio_test, gpio_scene_test_ok_callback, app); view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewGpioTest); }gpio_items_configure_all_pins(gpio_items.c)内部逐个调用gpio_items_configure_pin,其实现为:
void gpio_items_configure_pin(GPIOItems* items, uint8_t index, GpioMode mode) { furi_assert(index < items->count); furi_hal_gpio_write(items->pins[index].pin, false); // 先拉低,避免上电瞬间抖动 furi_hal_gpio_init(items->pins[index].pin, mode, GpioPullNo, GpioSpeedVeryHigh); }关键点:
- 每次配置前先把引脚写为低电平(
false),确保进入测试界面时所有 LED 熄灭、无意外高电平输出; - 配置使用
GpioModeOutputPushPull(推挽输出)、GpioPullNo(无上下拉)、GpioSpeedVeryHigh(非常高速),保证输出驱动能力与翻转速度满足 LED 直驱测试需求。
相应地,退出测试场景时 gpio_scene_test_on_exit 会把所有引脚恢复为GpioModeAnalog(模拟模式),释放对引脚的控制权,避免与后续 USB-UART 桥接等其他功能冲突。
3.3 界面操作:切换引脚与驱动电平
测试界面由 gpio_test.c 实现,屏幕顶部显示 "GPIO Output Mode Test",并提示 "Press < or > to change pin"。操作逻辑如下:
| 按键 | 动作 | 源码位置 |
|---|---|---|
左键< | 切换到上一个引脚(pin_idx--,到 0 后不再递减) | gpio_test_process_left |
右键> | 切换到下一个引脚;当pin_idx等于引脚总数时进入特殊项"ALL" | gpio_test_process_right |
| OK 按下(Press) | 将当前选中引脚拉高(gpio_items_set_pin(..., true)),若选中 "ALL" 则全部引脚同时拉高 | gpio_test_process_ok |
| OK 松开(Release) | 将当前选中引脚拉低(gpio_items_set_pin(..., false)),"ALL" 同理全部拉低 | 同上 |
其中引脚名称由 gpio_items_get_pin_name 返回,当索引等于引脚总数时返回字符串"ALL",实现"一键全测"能力。
测试操作示例:
- 进入 Manual Control 界面后,按右键在 PA7 → PA6 → PA4 → PB3 → PB2 → PC3 → PC1 → PC0 → ALL 之间循环切换;
- 选中某个引脚后按住 OK 键,该引脚输出高电平,对应 LED 点亮;松开 OK 键,引脚恢复低电平,LED 熄灭;
- 切换到 "ALL" 后按住 OK,全部 8 个可用引脚的 LED 应同时点亮,可用于快速确认整排引脚输出通道完好;
- 观察每个引脚对应的 LED 是否与界面当前显示的引脚名一致,逐一比对排针编号,完成全量验证。
扩展提示:按住 OK 期间,gpio_scene_test_ok_callback 会同步向通知服务发送
sequence_set_green_255,使设备背光 LED 变为绿色,松开后发送sequence_reset_green恢复——即按压 OK 时 LED 变绿可作为"输出已使能"的额外视觉反馈。
预期结果(对应测试用例第 3 步):pins are managed from the app——所有 LED 的状态完全由应用内的按键操作驱动,且与界面显示的当前引脚一致。
四、5V on GPIO:OTG 供电开启与验证
4.1 操作步骤
- 在 GPIO 应用启动场景中,选中"5V on GPIO"项;
- 在OFF / ON两个取值间切换(gpio_scene_start.c 中
gpio_otg_text[] = {"OFF", "ON"}); - 选择 ON,GPIO 排针的 5V 引脚(排针 1 号)开始输出 5V 电源。
预期结果(对应测试用例第 4 步):外接的供电指示灯(LED)亮起,表明 5V 输出链路正常。
4.2 源码级原理:BQ25896 的 OTG 升压控制
"5V on GPIO" 并非简单的 GPIO 输出,而是通过电源管理芯片 BQ25896 的 OTG(On-The-Go)升压模式实现。相关调用链如下:
- 界面回调 gpio_scene_start_var_list_change_callback 在 ON/OFF 切换时发送
GpioStartEventOtgOn/GpioStartEventOtgOff自定义事件; - 场景事件处理 gpio_scene_start_on_event 分别调用
power_enable_otg(app->power, true/false); power_enable_otg是电源服务对硬件抽象层furi_hal_power_enable_otg的封装,后者实现在 targets/f7/furi_hal/furi_hal_power.c:
bool furi_hal_power_enable_otg(void) { furi_hal_i2c_acquire(&furi_hal_i2c_handle_power); bq25896_set_boost_lim(&furi_hal_i2c_handle_power, BoostLim_2150); // 升压电流限流临时提升 bq25896_enable_otg(&furi_hal_i2c_handle_power); // 使能 OTG 升压 furi_delay_ms(30); bool ret = bq25896_is_otg_enabled(&furi_hal_i2c_handle_power); // 回读确认 bq25896_set_boost_lim(&furi_hal_i2c_handle_power, BoostLim_1400); // 恢复 1.4A 限流 furi_hal_i2c_release(&furi_hal_i2c_handle_power); return ret; }实现要点(对应 lib/drivers/bq25896.c 中的寄存器操作):
- OTG 模式下 BQ25896 将电池电压升压到 5V 输出到 VBUS/5V 排针,因此无需外接电源即可为 ST-Link 等外部设备供电;
- 使能前将 Boost 限流临时提高到
BoostLim_2150(2.15A)以应对启动浪涌,回读确认 OTG 已启用后再恢复为BoostLim_1400(1.4A)正常运行限流; - 关闭时调用
furi_hal_power_disable_otg(furi_hal_power.c),内部执行bq25896_disable_otg; - 界面初始显示值由 power_is_otg_enabled 读取 BQ25896 的 OTG 状态位决定,保证 UI 与硬件状态一致。
安全提示:5V 排针在 OTG 开启时持续供电,测试完毕后应回到 "5V on GPIO" 切回 OFF,避免在连接敏感外设时长时间误供电;同时 1.4A 的 Boost 限流决定了外接负载不能超过安全范围,使用时应参考 BQ25896 数据手册与 DangerousSettings.md 中的相关警告。
五、测试判定标准与常见问题排查
5.1 通过标准汇总
| 测试项 | 操作 | 通过标准 |
|---|---|---|
| 引脚枚举 | 进入 Manual Control | 界面仅显示 8 个用户可用引脚(PA7/PA6/PA4/PB3/PB2/PC3/PC1/PC0),不含 SWD/USART/iButton 引脚 |
| 单引脚输出 | 选中引脚后按住 OK | 对应 LED 点亮;松开 OK 后熄灭;按压期间设备 LED 变绿 |
| ALL 全引脚输出 | 切换到 "ALL" 后按住 OK | 全部 8 路 LED 同时点亮/熄灭 |
| 引脚标识正确性 | 逐一切换并核对排针编号 | 界面引脚名与物理排针位置一一对应 |
| 5V OTG 供电 | "5V on GPIO" 切到 ON | 外接供电指示灯亮起;切回 OFF 后熄灭 |
| 引脚恢复 | 退出 Manual Control | 所有引脚恢复模拟模式,不影响其他外设功能 |
5.2 常见问题排查
- 进入 Manual Control 后 LED 全部不亮:确认推挽输出初始化成功(检查 gpio_scene_test_on_enter 中
GpioModeOutputPushPull是否被后续流程覆盖),并核对 LED 极性——推挽输出在 OK 按下时输出高电平,LED 正极应接引脚、负极经限流电阻接地; - "ALL" 选项缺失或引脚数量不符:检查目标平台的 furi_hal_resources.c 引脚表定义。不同硬件目标(如 f18)的引脚表不同,应用会根据
gpio_pins_count自动适配; - 5V 输出指示灯不亮:确认电池有足够电量(OTG 升压依赖电池),并查看 furi_hal_power.c 中
bq25896_is_otg_enabled的回读结果;若返回 false 说明升压未建立,需检查电池电压与 BQ25896 寄存器状态; - 退出后引脚仍保持输出状态:正常退出场景会执行
GpioModeAnalog恢复,若异常复位导致引脚状态残留,重启设备即可恢复默认配置(系统启动时会重新初始化 GPIO)。
六、扩展阅读
- GPIO 应用源码:包含场景管理(scenes)、测试视图(views/gpio_test.c)、USB-UART 桥接(usb_uart_bridge.c)等完整实现;
- gpio_items.c:引脚枚举、模式配置与电平控制的统一封装;
- furi_hal_resources.c:F7 目标全局引脚表,含 ADC 通道、PWM 输出、引脚编号与危险标记;
- furi_hal_power.c:OTG 使能/查询/关闭的硬件抽象实现;
- bq25896.c:充电管理芯片寄存器级驱动;
- 同类测试用例可参考 documentation/testing 目录下的 general_test_cases.md、integration_tests.md 等文档,形成完整的硬件回归测试矩阵。
【免费下载链接】unleashed-firmwareFlipper Zero Unleashed Firmware项目地址: https://gitcode.com/GitHub_Trending/un/unleashed-firmware
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考