Architecture
Fantasi is a FreeRTOS-based system. The kernel provides preemptive multitasking, heap management, and synchronization primitives. A thin HAL layer abstracts hardware differences between targets so that core logic - the CLI, storage, and application loader - is written once and compiled for all platforms.
┌──────────────────────────────────┐
│ Applications │ ← loaded into RAM from host
├──────────────────────────────────┤
│ core/ CLI, commands │
│ hal/ serial, storage │
├──────────────────────────────────┤
│ platform HAL implementations │
├──────────────────────────────────┤
│ FreeRTOS kernel │
├──────────────────────────────────┤
│ MCU hardware │
└──────────────────────────────────┘
Tasks
| Task | Priority | Role |
|---|---|---|
| USB | tskIDLE + 2 | Drives TinyUSB (tud_task), services CDC and MSC class drivers |
| CLI | tskIDLE + 1 | Line-editing, command dispatch, serial I/O |
| Idle | tskIDLE | FreeRTOS idle hook (unused) |
Code Structure
core/ Shared across all targets
main.c Task creation, scheduler start
cli.c Line editor, command dispatch loop
commands/ Built-in commands, one file per command (help, free, scan, msc, ...)
elf_loader.c Load + run apps; ramfs.c / vfs.c storage
hal/ Hardware abstraction
hal.h HAL contract - every platform implements these
storage/ LittleFS mount/unmount, MSC block-device callbacks
tinyusb/ Shared USB descriptors, CDC serial transport
platforms/ One directory per target
flipper/ STM32WB55 - hal.c, display, BLE, flash driver, linker
kiisu/ STM32WB55 - Flipper-compatible; reuses flipper/ sources, SH1106-via-companion display
chameleon/ nRF52840 - hal.c, BLE, flash driver, linker
proxmark3/ AT91SAM7S - hal.c, flash driver, USB mode-switch, linker
third_party/ tinyusb + littlefs are auto-cloned on first build; the rest are vendored in-tree
tinyusb/ USB device stack (pinned tag, fetched)
littlefs/ On-flash filesystem (pinned tag, fetched)
FreeRTOS-Kernel/
nanopb/ protobuf (WebUSB vendor pipe)
cmsis_core/
stm32wb_cmsis/
nrf52_mdk/
HAL Contract
Every platform implements the functions declared in hal/hal.h:
hal_init- clock, GPIO, peripheral setuphal_serial_read/write/connected- USB CDC transporthal_reboot,hal_reboot_dfu- warm reset, bootloader entryhal_battery_percent- fuel gauge or ADC reading (-1 if unavailable)hal_ble_scan- passive BLE scan with per-device callback (-1 if no radio)hal_flash_free_bytes- free flash between firmware end and reserved regionshal_enter_msc_mode- USB mode switch to MSC (PM3), or -1 if MSC is concurrent (FZ/CU)
Platforms that lack a feature return a sentinel value rather than requiring compile-time exclusion. The CLI adapts at runtime.
USB
All four targets use TinyUSB as the USB device stack. The Flipper Zero, Kiisu, and Chameleon Ultra run CDC and MSC as a composite device (both interfaces active simultaneously). The Proxmark3 has only 4 hardware endpoints, so it mode-switches between CDC and MSC on demand - the msc CLI command re-enumerates as MSC-only, and host-side eject returns to CDC.
Storage
Each device reserves 256 KB of internal flash for a LittleFS filesystem, placed at the top of available flash so firmware updates (which write from the bottom) never touch stored files.
| Target | Storage Region | Placement Logic |
|---|---|---|
| Flipper Zero | Just below BLE secure flash (SFSA) | Runtime-detected from FLASH->SFR |
| Kiisu | Just below BLE secure flash (SFSA) | Runtime-detected from FLASH->SFR |
| Chameleon Ultra | Just below DFU bootloader | Runtime-detected from UICR.NRFFW[0] |
| Proxmark3 | Flash plane 1 (0x140000) | Fixed; S512 only |
The storage is exposed to the host as a USB mass storage block device (512-byte sectors). Host tools that understand LittleFS can read/write files directly. The on-device firmware mounts LittleFS at boot and can read/write files via the lfs_* API.
Application Model
Fantasi's long-term role is a runtime and loader, not a monolithic firmware:
- Host deploys an application via the web flasher or CLI tool. The binary is transferred over USB into device RAM.
- The loader executes the application from RAM. The application has access to a defined API surface (serial I/O, storage, radio, display where available).
- Persistence is handled through LittleFS. Configuration, calibration data, captured samples - anything that should survive a power cycle lives here, including a limited number of apps.
- Applications are portable across targets. The HAL and loader API abstract hardware differences. An application compiled for the Fantasi API runs on any supported device, with runtime capability queries for target-specific features.