Прошивка Flipper Zero своими руками: четыре уровня — от своего .fap до форка

«Собрать прошивку для Flipper Zero» — фраза, за которой прячутся четыре очень разные задачи. Кому-то нужно своё приложение, кому-то — патч в системном коде, кому-то форк со снятыми ограничениями Sub-GHz, а кому-то на самом деле не нужно собирать ничего. Прежде чем выбирать между ними, стоит понять, что вообще лежит внутри и какие инструменты вы получаете вместе с исходниками.

Всё, что ниже, снято с живого стенда: официальный репозиторий на теге 1.4.3, контейнер с 2 vCPU и 7 ГБ RAM, Debian. Цифры посчитаны по дереву исходников и по api_symbols.csv из SDK, размеры файлов — с реальной сборки, приложение на C действительно скомпилировано.

Инвентаризация: что уже умеет стоковая прошивка

Начинать имеет смысл отсюда, потому что примерно половина запросов «а можно ли собрать прошивку, чтобы…» относится к тому, что уже есть.


Подсчитано по дереву исходников тега 1.4.3 и реестрам протоколов

Десять пользовательских приложений в applications/main — это не десять кнопок в меню, а десять аппаратных подсистем со своими стеками протоколов:

Приложение Железо Что внутри
subghz трансивер CC1101, 300–928 МГц 52 протокола в реестре: keeloq, came, nice_flo, somfy, hormann, secplus_v1/v2, princeton, holtek
nfc ST25R3916, 13,56 МГц 12 протокольных стеков (iso14443-3a/3b/4a/4b, iso15693-3, felica, mf_classic/ultralight/desfire/plus) и 26 парсеров конкретных карт
lfrfid собственный аналоговый тракт, 125 кГц 24 протокола: EM4100, HID H10301, Indala, Awid, FDX-B, Paradox, Viking, Jablotron, Noralsy
infrared приёмник и передатчик ИК 14 вариантов протоколов: NEC и расширения, Samsung32, RC5/RC5X, RC6, SIRC/15/20, Kaseikyo, Pioneer, RCA
ibutton, onewire 1-Wire Dallas DS1990, DS1971, DS1992, DS1996, generic-режим, работа с болванками
gpio 8 линий наружу ручное управление пинами, USB-UART мост
bad_usb, u2f USB-стек STM32 эмуляция HID-клавиатуры и аппаратного ключа U2F
archive файловая система SD браузер сохранённых карт, ключей и сигналов

Рядом — 16 фоновых сервисов (gui, storage, notification, power, bt, cli, loader, rpc, dolphin, region, crypto, input и другие), 10 экранов настроек, 27 отладочных стендов и 13 готовых примеров приложений, которые можно взять как каркас для своего.

Important:

Практический вывод из этой таблицы: 26 парсеров карт включают troika, plantain, social_moscow, umarsh, two_cities — то есть распространённые транспортные карты уже разбираются стоковой прошивкой. Сборка ради «поддержки моей карты» нужна только тогда, когда конкретной карты в этом списке нет.

Куда всё это помещается


Границы — из линкер-скриптов targets/f7, размер образа — с собственной сборки

Прошивка живёт в STM32WB55 — двухъядерном чипе, где Cortex-M4 занят прикладной частью, а Cortex-M0+ крутит радиостек Bluetooth. Границы жёстко заданы в линкер-скриптах targets/f7: флеш-память 1024 КБ, из них прикладному процессору доступно всё до адреса радиостека 0x080D7000, то есть 860 КБ.

Мой образ, собранный с COMPACT=1 DEBUG=0, занял 750 КБ. Свободного места осталось около 110 КБ — и это ровно та причина, по которой флаги сборки не косметика: отладочная сборка ощутимо толще, и на форке с десятком дополнительных приложений запас исчезает быстро.

С оперативной памятью похожая история: 192 КБ в RAM1 на всё сразу — прошивку, ваши приложения и графику, плюс два блока по 10 КБ, через которые идёт обмен с радиопроцессором. Именно поэтому stack_size в манифесте приложения указывается явно и в байтах, а не «сколько надо».

Что из этого доступно вашему коду

Приложение .fap не линкуется статически с прошивкой — оно обращается к ней через таблицу экспортируемых символов. Таблица лежит в SDK файлом targets/f7/api_symbols.csv, и её можно посмотреть глазами:

head -3 ~/.ufbt/current/sdk_headers/f7_sdk/targets/f7/api_symbols.csv
# entry,status,name,type,params
# Version,+,87.1,,
# Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,

# сколько всего чего
cut -d, -f1 ~/.ufbt/current/sdk_headers/f7_sdk/targets/f7/api_symbols.csv | sort | uniq -c


Цифры из targets/f7/api_symbols.csv — файла, по которому линкуется каждый .fap

В версии 1.4.3 это 3531 функция, 311 переменных и 319 заголовков при версии API 87.1. Разложение по подсистемам показывает, где сосредоточена мощность.

Ядро furi — 29 заголовков. Под капотом FreeRTOS, но наружу торчит собственный слой: потоки (furi_thread), мьютексы, семафоры, очереди сообщений, потоковые буферы, флаги событий, таймеры, цикл событий (furi_event_loop), шина pubsub и реестр сервисов record. Плюс furi_string — строки с подсчётом ссылок, потому что обычный char* на 192 КБ RAM быстро надоедает.

Слой железа — 47 заголовков furi_hal_* и 488 функций. Это прямой доступ к периферии: gpio, spi, i2c, adc, pwm, serial, usb (включая cdc, hid, ccid), nfc, subghz, infrared, rfid, ibutton, bt, power, speaker, vibro, light, rtc, random, crypto, flash, sd, region. Если задача формулируется как «подёргать ногой и послушать ответ» — это сюда, и прошивку пересобирать не нужно.

Интерфейс — 17 готовых элементов. submenu, menu, button_menu, button_panel, dialog_ex, popup, widget, text_input, byte_input, number_input, text_box, variable_item_list, file_browser, loading, empty_screen и валидаторы. Своё меню с нуля писать не нужно — экран 128×64 монохромный, и всё типовое уже нарисовано.

Info:

Отдельно стоит lib/flipper_application — пять заголовков, которые отвечают за загрузку и выполнение .fap во время работы, включая плагины. Именно этот механизм позволяет 26 парсерам NFC-карт быть отдельными файлами, а не частью монолита: приложение nfc подгружает нужный парсер по требованию.

Четыре уровня: где вы окажетесь


Уровни отличаются не сложностью команд, а объёмом ответственности

Info:

Что понадобится в любом случае: 64-битная Linux, macOS 12+ или Windows 10+, установленный git и Python 3.8 или новее. Компилятор ставить не нужно — обе сборочные системы Flipper тянут собственный arm-none-eabi-gcc и не трогают системный PATH.

Уровень 0. Проверить, что собирать не надо

Официальные прошивки раздаются через канал обновлений, и он же — самый честный источник правды о версиях:

curl -s https://update.flipperzero.one/firmware/directory.json \
  | python3 -c 'import json,sys;[print(c["id"], c["versions"][0]["version"]) for c in json.load(sys.stdin)["channels"]]'
development       a55e3939
release-candidate 1.4.2-rc
release           1.4.3

Стабильный канал отдаёт 1.4.3 — релиз от 5 декабря 2025 года. Если задача звучит как «поставить свежую прошивку» или «поставить чужой готовый форк», качать исходники не надо: qFlipper и веб-апдейтер сделают это за минуту, а образ будет подписан и проверен.

Уровень 1. Своё приложение .fap: пять команд

Приложения Flipper Zero — отдельные файлы .fap на SD-карте, они не входят в прошивку. Собирает их ufbt — обрезанная сборочная система, которая качает готовый SDK вместо исходников всей прошивки.

python3 -m pip install --upgrade ufbt
mkdir gig_hello && cd gig_hello
ufbt create APPID=gig_hello

Первый запуск подтягивает SDK: в моём случае — Using version: 1.4.3, распаковка в ~/.ufbt/current. После ufbt create в каталоге появляется ровно пять файлов:

gig_hello.c                  исходник приложения
application.fam              манифест сборки
gig_hello.png                иконка 10×10, 1 бит
images/.gitkeep              каталог под ассеты
.github/workflows/build.yml  готовый CI на GitHub Actions

Манифест — обычный Python-вызов. Вот что генерируется, дословно:

App(
    appid="gig_hello",  # Must be unique
    name="App gig_hello",  # Displayed in menus
    apptype=FlipperAppType.EXTERNAL,
    entry_point="gig_hello_app",
    stack_size=2 * 1024,
    fap_category="Examples",
    fap_icon="gig_hello.png",  # 10x10 1-bit PNG
    fap_icon_assets="images",
)

Важных полей три. entry_point — имя функции на C, с которой начинается приложение; оно должно совпадать с тем, что написано в исходнике. stack_size — сколько байт стека выделяется потоку приложения: 2 КБ хватает на простую отрисовку, но работа с NFC или файлами потребует больше. fap_category определяет подкаталог на SD-карте: доступны Sub-GHz, RFID, NFC, Infrared, GPIO, iButton, Bluetooth, USB, Games, Tools, Media, Debug, Examples.

Шаблонный gig_hello.c умеет только писать в лог. Заменим его на минимальное приложение с экраном и выходом по кнопке — этот код собран и проверен на SDK 1.4.3:

#include <furi.h>
#include <gui/gui.h>
#include <input/input.h>

static void gig_hello_draw_callback(Canvas* canvas, void* ctx) {
    UNUSED(ctx);
    canvas_clear(canvas);
    canvas_set_font(canvas, FontPrimary);
    canvas_draw_str(canvas, 2, 12, "GIG Community");
    canvas_set_font(canvas, FontSecondary);
    canvas_draw_str(canvas, 2, 28, "Built from source");
    canvas_draw_str(canvas, 2, 40, "Press Back to exit");
}

static void gig_hello_input_callback(InputEvent* event, void* ctx) {
    FuriMessageQueue* queue = ctx;
    furi_message_queue_put(queue, event, FuriWaitForever);
}

int32_t gig_hello_app(void* p) {
    UNUSED(p);

    FuriMessageQueue* queue = furi_message_queue_alloc(8, sizeof(InputEvent));

    ViewPort* view_port = view_port_alloc();
    view_port_draw_callback_set(view_port, gig_hello_draw_callback, NULL);
    view_port_input_callback_set(view_port, gig_hello_input_callback, queue);

    Gui* gui = furi_record_open(RECORD_GUI);
    gui_add_view_port(gui, view_port, GuiLayerFullscreen);

    InputEvent event;
    bool running = true;
    while(running) {
        if(furi_message_queue_get(queue, &event, FuriWaitForever) == FuriStatusOk) {
            if(event.type == InputTypeShort && event.key == InputKeyBack) {
                running = false;
            }
        }
    }

    gui_remove_view_port(gui, view_port);
    furi_record_close(RECORD_GUI);
    view_port_free(view_port);
    furi_message_queue_free(queue);

    return 0;
}

Обратите внимание на порядок освобождения в конце: сначала вьюпорт снимается с GUI, только потом освобождается. Если поменять эти строки местами, система продолжит рисовать уже освобождённую структуру — и это будет не ошибка компиляции, а перезагрузка устройства в руках.

Сборка — просто ufbt без аргументов:

$ ufbt
    CC      /tmp/fz/gig_hello.c
    LINK    /root/.ufbt/build/gig_hello_d.elf
    FAP     /root/.ufbt/build/gig_hello.fap
    INSTALL /tmp/fz/dist/gig_hello.fap
    APPCHK  /root/.ufbt/build/gig_hello.fap
            Target: 7, API: 87.1

Готовый файл — dist/gig_hello.fap, 2200 байт. Строка APPCHK — самая полезная во всём выводе.

Warning:

Target: 7, API: 87.1 — это отпечаток, по которому устройство решает, запускать приложение или нет. Target — ревизия железа (7 — Flipper Zero), API — версия того самого экспорта из api_symbols.csv. Прошивка с другой мажорной версией API откажется запускать приложение, хотя файл скопируется без ошибок. Отсюда правило: .fap, собранный под стабильный канал, не обязан работать на форке или на dev-сборке. Переключить SDK можно, не пересоздавая проект:

ufbt update --channel=dev      # или rc, или release
ufbt update --branch=1.4.3     # конкретная ветка SDK
ufbt update --local=/path/to/flipper-z-f7-sdk-local.zip   # SDK из своей сборки

Залить и сразу запустить на подключённом устройстве:

ufbt launch

Команда копирует .fap на SD-карту в подкаталог из fap_category и стартует приложение. qFlipper при этом должен быть закрыт — он держит последовательный порт монопольно.

Откуда люди берут приложения


Проверку мажорной версии API проходит любой .fap, кем бы он ни был собран

Собственный код — далеко не самый частый способ получить новую функцию. Источников четыре, и различаются они не удобством установки, а тем, под какую версию API собран бинарник.

Официальный каталог: 437 приложений


Числа отданы публичным API каталога на момент подготовки материала

Каталог живёт на lab.flipper.net, ставится оттуда прямо из браузера или из мобильного приложения, а числа по разделам отдаёт публичный API — их можно перепроверить самому:

curl -s 'https://catalog.flipperzero.one/api/v0/category?limit=50' \
  | python3 -c 'import json,sys;[print(f"{c[\"name\"]:12} {c[\"applications\"]}") for c in json.load(sys.stdin)]'

Перекос показательный: GPIO — 112 приложений, Games — 102, Tools — 93, а на весь iButton приходится два. То есть каталог живёт вокруг внешних модулей и утилит, а не вокруг радиочасти — радиочасть и так закрыта стоковыми приложениями.

Попасть в каталог можно и со своим приложением, причём исходники туда не заливаются. В репозиторий flipper-application-catalog кладётся один файл applications/<Категория>/<app_id>/manifest.yml, который лишь ссылается на ваш репозиторий и конкретный коммит:

sourcecode:
  type: git
  location:
    origin: https://github.com/example/test.git
    commit_sha: bf7019d16d7b50f6a98cc3abdac38c53952a4f30
short_description: Test app
description: "@README.md"
changelog: "@./docs/changelog.md"
screenshots:
  - screenshots/ss0.png

Собирает .fap уже инфраструктура каталога. Правила жёсткие: id должен быть в нижнем регистре и совпадать с appid из application.fam, category — соответствовать каталогу, куда положен манифест, version имеет формат «мажор.минор», а обновление с номером не выше предыдущего отклоняется. Скриншоты требуется снимать штатной функцией qFlipper.

Готовое приложение из чужого репозитория

Половина интересного в каталог не попадает и лежит просто на GitHub. Схема одна и та же: клонировать, зайти в каталог приложения, запустить ufbt.

Проверил на официальном наборе flipperzero-good-faps — 15 приложений, которые ведёт сама команда Flipper:

git clone --depth 1 https://github.com/flipperdevices/flipperzero-good-faps.git
cd flipperzero-good-faps/weather_station
ufbt          # собрать
ufbt launch   # залить на устройство и запустить

Собрались все, без единой правки. Реальные размеры:

Приложение Что делает Размер .fap
clock часы на экране 3,8 КБ
signal_generator генератор сигналов на GPIO 11,8 КБ
mfkey восстановление ключей Mifare Classic из перехвата 37,6 КБ
nfc_magic запись на «магические» карты с перезаписываемым UID 92,4 КБ
weather_station приём беспроводных метеодатчиков на 433 МГц 101,9 КБ

Там же — dap_link (превращает Flipper в отладочный зонд CMSIS-DAP), avr_isp_programmer (программатор AVR), spi_mem_manager (чтение и запись SPI-флешек), air_mouse (мышь по гироскопу), mass_storage, music_player, nfc_rfid_detector, video_game_module_tool, flip_tdi, air_arkanoid.

Success:

Собирать чужое приложение самому обычно правильнее, чем качать готовый .fap из чата: сборка идёт под тот SDK, который стоит у вас, и вопрос совместимости снимается на месте. Разница в трудозатратах — две команды.

Почему приложение из каталога не запускается на форке

Официальная документация формулирует правило коротко: загрузчик приложений сверяет мажорную версию API у .fap с мажорной версией API прошивки, и при расхождении приложение не запускается. Мажорная версия растёт, когда из экспорта убирают функцию или меняют сигнатуру, минорная — когда добавляют новую.

Отсюда следствие, которое обычно обнаруживают опытным путём: каталог собирает бинарники под API официальной прошивки, поэтому на форке со своим набором изменений часть приложений оттуда просто не стартует. Именно поэтому форки везут собственные паки приложений внутри самой прошивки — это единственный способ гарантировать совпадение версий.

Уровень 2. Полная сборка прошивки: fbt

Здесь клонируется весь репозиторий вместе с сабмодулями. Ключ --recursive не опция, а обязательное условие: без него сборка упадёт на отсутствующих библиотеках.

git clone --recursive https://github.com/flipperdevices/flipperzero-firmware.git
cd flipperzero-firmware
./fbt COMPACT=1 DEBUG=0 updater_package


Замеры с живой сборки тега 1.4.3 на контейнере с 2 vCPU и 7 ГБ RAM

Первый запуск ./fbt выглядит так, будто ничего не происходит: скрипт проверяет tar и curl, качает архив тулчейна и распаковывает его в ./toolchain внутри репозитория. Системные пакеты не ставятся — компилятор живёт рядом с исходниками, и снести всю сборочную среду можно удалением одного каталога. Версия, которая приехала у меня, — arm-none-eabi-gcc (GCC) 12.3.1.

Чистая сборка после ./fbt -c заняла 144 секунды на двух ядрах. Это ощутимо меньше, чем принято ожидать от прошивки на 700 МБ исходников, — большую часть объёма занимают сабмодули, которые в целевой образ не попадают.

Что означают COMPACT и DEBUG

Значения по умолчанию лежат в fbt_options.py:

TARGET_HW = 7
COMPACT = 0
DEBUG = 1
DIST_SUFFIX = "local"
FIRMWARE_APP_SET = "default"
FBT_TOOLCHAIN_VERSIONS = (" 12.3.", " 13.2.")

То есть «из коробки» вы собираете отладочную некомпактную сборку — она больше и медленнее, зато с ней работает пошаговая отладка. Для прошивки, которой собираетесь пользоваться каждый день, нужны как раз COMPACT=1 DEBUG=0.

Success:

Не правьте fbt_options.py — он под контролем версий и будет конфликтовать при каждом git pull. Создайте рядом fbt_options_local.py, его сборка подхватывает автоматически:

COMPACT = 1
DEBUG = 0
DIST_SUFFIX = "gig"
FIRMWARE_APP_SET = "default"

DIST_SUFFIX попадает в имена артефактов и в поле Info внутри пакета обновления, так что свои сборки потом легко отличить от официальных. FIRMWARE_APP_SET переключает набор встраиваемых приложений — например, значение unit_tests собирает прошивку-стенд вместо обычной.

Куда лечь артефактам и чем их залить

Каталог dist/f7-C из моей сборки содержит 11 файлов, разбор — на схеме выше. Найти его можно, не запоминая суффиксы:

ls -1 dist/*/ | head -20

Способов доставить сборку на устройство три, и они не равнозначны.

./fbt flash_usb_full     # по USB, с ресурсами и радиостеком
./fbt flash              # через SWD-программатор: ST-Link, J-Link, CMSIS-DAP, Wi-Fi devboard

Третий — руками через qFlipper: взять dist/f7-C/flipper-z-f7-update-local.tgz, открыть qFlipper и выбрать «Install from file». Этот путь предпочтительнее, если вы не уверены в сборке: qFlipper проверит целостность пакета до того, как начнёт писать во флеш.

Error:

Не отключайте кабель и не давайте ноутбуку уснуть во время flash_usb_full. Обновление радиостека Core2 — отдельная фаза, и прерывание именно на ней превращает устройство в кирпич надёжнее, чем что-либо ещё в этом руководстве.

Полный набор целей fbt

./fbt — не одна команда сборки, а зонтик над несколькими десятками целей. Ниже те, что реально пригождаются.

Группа Цель Что делает
Сборка fw_dist собрать прошивку и разложить в dist (цель по умолчанию)
updater_package / updater_minpackage пакет самообновления; минимальный — только DFU, полный — плюс радиостек и ресурсы SD
copro_dist собрать бандл Core2 FUS и стека для qFlipper
faps собрать все внешние приложения как .fap
fap_<appid> собрать одно приложение по его идентификатору
fap_dist разложить внешние приложения в dist
Прошивка flash_usb, flash_usb_full залить по USB
flash, firmware_flash залить через SWD; выбор адаптера — SWD_TRANSPORT=…, серийник — SWD_TRANSPORT_SERIAL=…
jflash залить через J-Link с помощью JFlash
Отладка debug собрать, залить и сразу присоединить gdb с загруженным .elf
updater_debug то же самое, но с .elf апдейтера
debug_other gdb без загрузки символов — символы добавляются вручную через add-symbol-file
blackmagic, openocd, get_blackmagic, get_stlink обвязка вокруг отладочных зондов
devboard_flash обновить Wi-Fi devboard, ARGS="-c dev" для канала
cli открыть консоль устройства по USB
Качество lint, format clang-format по исходникам на C
lint_py, format_py black по скриптам сборки и манифестам
lint_img, format_img проверка и нормализация PNG-ассетов
lint_all, format_all всё сразу
doxygen, doxy сгенерировать документацию по API и открыть её в браузере
Ассеты resources, icons, proto, proto_ver пересобрать ресурсы SD, иконки из PNG и protobuf
Служебное firmware_list, updater_list листинг исходник + ассемблер
firmware_cdb, updater_cdb сгенерировать compile_commands.json без полной сборки
vscode_dist развернуть конфигурацию VS Code с задачами сборки и отладки

Отдельно — работа с одним приложением, когда прошивку пересобирать не хочется:

./fbt launch APPSRC=applications_user/my_app   # собрать, залить и запустить
./fbt build APPSRC=applications_user/my_app    # только собрать
./fbt -c fap_my_app                            # почистить артефакты этого приложения

Инструменты, которые идут в комплекте

Помимо целей, сборочная система приносит несколько вещей, о которых обычно узнают случайно.

Оболочка с тулчейном. Тот самый arm-none-eabi-gcc, gdb и objdump можно получить в свой шелл, не прописывая пути:

source scripts/toolchain/fbtenv.sh     # Linux и macOS
. `./fbt -s env`                       # то же самое короче
scripts\toolchain\fbtenv.cmd           # Windows

Переменные окружения, которые меняют поведение сборки:

Переменная Эффект
FBT_NOENV=1 не настраивать тулчейн, брать всё из системного PATH (только *nix)
FBT_TOOLCHAIN_PATH держать тулчейн в общем каталоге, а не по копии на клон
FBT_NO_SYNC=1 не обновлять сабмодули автоматически
FBT_VERBOSE=1 показать полные командные строки компилятора

Ключи командной строки. --extra-define=NAME=VALUE пробрасывает define в компилятор глобально, --extra-ext-apps=app1,app2 заставляет собрать перечисленные приложения как внешние, --options другой_файл.py подменяет файл конфигурации целиком, --proxy-env=VAR1,VAR2 прокидывает переменные окружения в дочерние процессы — по умолчанию fbt окружение санирует.

Отладка на железе. Поддерживаются Wi-Fi devboard от самих Flipper Devices, ST-Link v2/v3, J-Link и любые CMSIS-DAP-совместимые зонды, включая Raspberry Pi Debug Probe. Цель debug собирает, прошивает и открывает gdb с уже подгруженными символами, SVD-файл для регистров периферии тоже идёт в комплекте.

CLI: второй интерфейс к устройству

Про эту часть забывают чаще всего, а она даёт доступ ко всем подсистемам без единой строки кода. Консоль поднимается по USB:

./fbt cli          # из репозитория
ufbt cli           # из проекта приложения

Базовый набор команд, зарегистрированных в прошивке: help, ?, !, device_info, info, uptime, date, free, free_blocks, top, log, sysctl, power, sleep, vibro, led, input, gpio, i2c, storage, crypto, bt, js, factory_reset, update, unit_tests, start_rpc_session, reload_ext_cmds.

Работа с радиочастью подключается внешними плагинами из /ext/apps_data/cli/plugins — если после установки приложения команда не появилась, её подхватит reload_ext_cmds. Наиболее полезные подкоманды:

Подсистема Команды
Sub-GHz rx, tx, tx_from_file, rx_raw, decode_raw, rx_carrier, tx_carrier, chat, encrypt_keeloq, encrypt_raw
NFC scanner, field, raw, apdu, iso14a, iso14b, mfc (rdbl, wrbl, dump), mfu, mfp, felica, slix, st25, emulate
LF-RFID read, write, emulate, raw_read, raw_emulate, raw_analyze
Инфракрасный rx, tx, decode, raw, universal, list
iButton / 1-Wire read, write, emulate, search
Success:

Прежде чем писать приложение, попробуйте решить задачу через CLI. Команда subghz rx пишет принятое в файл, nfc scanner показывает всё, что попадает в поле, а gpio дёргает пины. Скрипт на хосте, разговаривающий с устройством через последовательный порт, часто закрывает вопрос без единой строки на C — и без разбирательств с версиями API.

JavaScript, если C избыточен

В прошивке живёт js_app — интерпретатор на базе mJS, и это отдельный уровень между «нажать в меню» и «писать на C». Скрипт кладётся на SD-карту и запускается из меню или командой js в консоли.

Доступные модули: badusb, gpio, serial, storage, notification, math, event_loop, flipper, gui и tests. Модуль gui при этом не игрушечный — из скрипта доступны те же элементы, что и из C: submenu, menu, button_menu, button_panel, dialog, popup, widget, text_input, byte_input, number_input, text_box, file_picker, loading, empty_screen.

В репозитории лежат 18 примеров — applications/system/js_app/examples: от badusb_demo.js и uart_echo_8e1.js до event_loop.js, gpio.js, storage.js и gui.js. Для одноразовой автоматизации этого хватает с запасом, а порог входа несопоставим со сборкой прошивки.

Уровень 3. Форк — и что вы вместе с ним берёте

Momentum и Unleashed собираются теми же целями fbt, что и официальная прошивка: ./fbt updater_package для TGZ и ./fbt flash_usb_full для прямой заливки. Технически разницы почти нет — вы клонируете другой репозиторий и запускаете те же команды.

Разница в содержимом. Ниже — то, что заявлено в собственных описаниях проектов.

Momentum Unleashed RogueMaster
База официальная прошивка плюс наработки Unleashed официальная прошивка форк Unleashed
Sub-GHz расширенные диапазоны 281–361, 378–481, 749–962 МГц; «сабдрайвинг» — сохранение координат GPS вместе с сигналом сняты региональные TX-ограничения, добавлены протоколы, сохранение и отправка прыгающих кодов (FAAC SLH, BFT Mitto с ручным созданием), поддержка внешнего CC1101 наследует изменения Unleashed
NFC и RFID поддержка Type 4 и NTAG4xx, дополнительные парсеры карт разбор EMV, расширенный словарь Mifare Classic, произвольный UID, фаззеры для LF-RFID и iButton наследует плюс собственные наборы
Ввод и USB Bad-Keyboard с настраиваемыми параметрами USB и Bluetooth BadKB — тот же BadUSB, но по Bluetooth, с раскладками наследует
Встроенные приложения Momentum App для настройки прошивки, BLE Spam, FindMy Flipper, NFC Maker, Wardriver, поиск файлов по SD плагины сообщества и игры в сборке заявлено более 150 игр плюс десятки плагинов
Оформление система Asset Packs: анимации, иконки и шрифты меняются без пересборки свои анимации и часы на рабочем столе тематические наборы анимаций и ассетов
Прочее блокировка при загрузке, сброс при неверном пин-коде, подмена имени, MAC и серийного номера, настройка RGB-подсветки, операции с файлами и монтирование образов дисков текстовый курсор, редактор байтов, блокировка по пин-коду, dev-сборки на dev.unleashedflip.com в описании прямо сказано: сначала поставить сток, и удалять приложения перед обновлением

Asset Packs у Momentum — отдельный механизм, который стоит знать даже тем, кто форк не ставит: паки лежат на карте в /ext/asset_packs/<Имя>/ с подкаталогами Anims и Icons, переключаются из настроек прямо на устройстве, а собираются скриптом scripts/asset_packer.py из репозитория. То есть менять анимации, иконки и шрифты можно без пересборки прошивки вообще.

Есть и техническая цена. Каждое дополнительное встроенное приложение съедает часть тех самых 110 КБ запаса во флеш-памяти, а собственная версия API означает, что .fap из официального каталога может не запуститься.

Security:

Региональные ограничения в официальной прошивке — не каприз вендора, а отражение того, что радиодиапазоны в разных странах распределены по-разному. Передача на частоте, не разрешённой в вашей юрисдикции, — административное нарушение независимо от того, что вы передаёте. Сборка форка переносит эту ответственность целиком на вас: ни производитель, ни автор форка в этой схеме не участвуют. Отдельно стоит помнить, что снятая гарантия — наименьшая из возможных неприятностей.

Внешние модули: чем расширяют железо

Восемь линий GPIO наружу — это не мелочь, а полноценная шина расширения: через неё Flipper получает то, чего нет на плате. Отсюда и перекос каталога в сторону раздела GPIO со 112 приложениями.

Модуль Чип Что даёт Чем прошивается
Wi-Fi Developer Board ESP32-S2-WROVER официально — отладка по SWD: точки останова, просмотр памяти, пошаговое выполнение; штатная прошивка построена на Black Magic Debug и CMSIS-DAP и собрана на ESP-IDF по USB или по Wi-Fi; цель ./fbt devboard_flash
Та же плата с ESP32 Marauder ESP32-S2 сторонняя прошивка со сканированием Wi-Fi и Bluetooth и набором наступательных функций заливается вместо штатной прошивки платы
Video Game Module RP2040 видеовыход DVI-D на монитор или проектор, шестиосевой датчик движения TDK ICM-42688-P, собственный 14-контактный разъём GPIO режим UF2 через порт USB-C
Внешний CC1101 CC1101 вынесенный трансивер Sub-GHz с нормальной антенной; поддерживается официальным приложением через драйвер cc1101_ext не требует прошивки
Внешний ИК-передатчик дальность вместо встроенного светодиода не требует прошивки
Warning:

ESP32 Marauder — это набор инструментов для тестирования Wi-Fi и Bluetooth, и часть его возможностей (деаутентификация клиентов, флуд служебными кадрами) в большинстве юрисдикций законна только в отношении собственной сети и только с согласия её владельца. Плата при этом остаётся той же самой: официальная прошивка от Flipper Devices делает из неё отладчик, а не радиоинструмент.

Прошивка знает про внешнюю радиочасть штатно: в дереве исходников есть applications/drivers/subghz/cc1101_ext, а в SDK — семейство функций subghz_devices. Так что внешний CC1101 не требует ни форка, ни патчей.

Базы сигналов и графика

Отдельный пласт экосистемы вообще не про код — это данные, которые кладутся на карту памяти.

Инфракрасные базы. Репозиторий Flipper-IRDB — самая крупная общая свалка ИК-дампов. Я склонировал его и посчитал: 8901 файл .ir в 47 разделах — телевизоры, кондиционеры, проекторы, ресиверы, вентиляторы, пылесосы, автомагнитолы, камеры, вплоть до каминов и подъёмников. Файлы кладутся в /ext/infrared и открываются штатным приложением.

Сборные коллекции. UberGuidoZ/Flipper — большой архив файлов, документации и дампов всех видов сразу: Sub-GHz, NFC, ИК, BadUSB-скрипты, графика. Индекс по всему остальному — список awesome-flipperzero, где собраны прошивки, приложения, базы и модули с короткими описаниями.

Графика. Помимо Asset Packs у Momentum есть отдельные инструменты сообщества: менеджеры анимаций и конвертеры GIF в формат анимаций Flipper. Экран монохромный 128×64, так что «тяжёлой» графики там не бывает по определению.

Info:

Полезная привычка: держать всё, что скачано из чатов и репозиториев, в отдельном каталоге на карте и не смешивать с тем, что записали сами. Форматы файлов Flipper текстовые и человекочитаемые — .ir, .sub, .nfc открываются обычным редактором, и перед установкой чужого файла в него полезно заглянуть.

Если устройство перестало включаться

Хорошая новость: прошивка Flipper Zero лежит в основном контроллере STM32WB55, а загрузчик в нём отдельный, и убить его пользовательской сборкой практически невозможно. Восстановление описано в официальной документации и сводится к двум комбинациям.

Important:

Устройство включается, но обновление не проходит: зажать влево + назад на 5 секунд, отпустить «назад», продолжая держать «влево», пока не загорится синий светодиод.

Устройство не подаёт признаков жизни: зажать OK + назад на 30 секунд. Экран при этом остаётся пустым — это нормально. После этого компьютер должен увидеть DFU-устройство, а qFlipper — предложить кнопку Repair, которая ставит прошивку с нуля.

Если DFU-устройство в системе не появляется — дело уже не в прошивке, а в питании или кабеле; проверьте кабель заведомо рабочим, желательно не «зарядным».

Тем, кому близка сама идея собирать прошивку под своё железо, будет знаком и соседний сюжет с 3D-принтерами: порядок калибровки Klipper — там ровно та же логика, где перестановка шагов ломает результат.

Источники

Question:

На каком уровне остановились вы — CLI и скрипт на хосте, свой .fap, патч в официальной прошивке или форк? И отдельный вопрос к тем, кто собирает регулярно: держите тулчейн внутри репозитория или вынесли через FBT_TOOLCHAIN_PATH в общий каталог, чтобы не качать по 1,2 ГБ на каждый клон?