Nyas

An Android app on Google Play that programs STM32 chips through an ST-Link over USB. No PC, no network.

How it connects

STM32ST-Link (SWD)USB OTGC bridge (stlink, libusb)JNIKotlin app

CategoryEmbedded & On-device
Timeline2026
ContextSLIS Solutions · Under NDA
StatusLive on Google Play

■ Built under NDA — described at the level the client has published.

Phone → ST-Link → STM32 architecture
70+STM32 chip IDs · 13 flash families
4CPU architectures the native libraries build for
0manifest permissions · no internet
0PCs needed in the field

The product

Factory and field technicians normally need a laptop, an ST-Link and desktop tooling to flash firmware. Nyas turns an Android phone into that toolchain: plug an ST-Link probe into the phone over USB OTG and write, read, verify and erase STM32 microcontrollers on the spot.

I built the whole stack: the open-source stlink and libusb C libraries compiled from source with the NDK and CMake, the C bridge and JNI layer that Kotlin calls, and the Jetpack Compose app on top. When races showed up on a shared USB session, I rewrote the bridge to be stateless, added erase guards, and reworked the CMake build for LGPL relinking and Google Play's 16 KB pages.

Built for an industrial client. Implementation details are summarised at the level the client has published.

Under the hood

THE ENGINEERING

  • 01

    Stateless native bridge: every command opens, connects, runs and closes, so a stale USB file descriptor or a shared session can't leak between commands

  • 02

    Erase guards: a zero address or size is refused instead of falling through to a full-chip wipe, and empty flash and SRAM ranges are rejected

  • 03

    CMake build reworked so libusb ships as its own shared library (relinkable, as LGPL 2.1 requires) and the native code links with 16 KB page alignment for Google Play

  • 04

    Caught a release-only R8 issue in development: the C++ looks up the JNI log callback by name, so a keep rule stops R8 from renaming it

  • 05

    Write .bin and Intel HEX, read, HEX-aware verify, full or sector erase; plugging in a probe auto-detects flash, SRAM, chip ID and the sector map

  • 06

    Option-byte editor for 6 chip families, including WRP and RDP Level 1 (Level 2 is blocked); batch mode flashes boards one after another and counts pass and fail

  • 07

    Internal build: encrypted, vendor-signed firmware packages (AES-256 firmware whose key is RSA-wrapped to a device key pair in the Android Keystore), made by a Go command-line tool

  • 08

    AVR support prototyped in Kotlin (STK500, AVR109 and UPDI engines, 137 tests), not merged into the app yet

  • 09

    Human-readable log narration: raw probe traffic translated into plain-language steps for technicians