Lightweight Python CLI tool for flashing Ingenic T-series SoCs (T20/T21/T23/T30/T31/T40/T41) via USB boot mode. Supports SPI NOR flash and eMMC.
pip install ingenic-flash-toolRequires libusb on your system:
- Linux:
sudo apt install libusb-1.0-0orsudo pacman -S libusb - macOS:
brew install libusb
To use without sudo, add a udev rule:
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="a108", MODE="0666"' | sudo tee /etc/udev/rules.d/99-ingenic.rules
sudo udevadm control --reload-rules && sudo udevadm trigger$ ingenic-flash-tool detect
Device found!
USB PID: 0xc309 (T-series)
CPU info: b'T 3 1 V ' (hex: 5420332031205620)
$ ingenic-flash-tool -v flash prj008 firmware.bin
INFO: Boot ROM CPU info: 5420332031205620
INFO: Loading ginfo (324 bytes) to 0x80001000
INFO: Loading SPL (32384 bytes) to 0x80001800
INFO: SPL running: 5420332031205620
INFO: Loading stage2 (417656 bytes) to 0x80100000
INFO: Stage2 running: b'PRJ\x00\x00\x00\x00\x00'
INFO: Flash JEDEC ID: 0xef7018
INFO: Initializing flash...
INFO: Writing 232652 bytes (227K) at offset 0x0
[########################################] 100% (232652/232652)
Flash complete!
$ ingenic-flash-tool -v flash prj008_mmc0 firmware.bin
INFO: Stage2 running: b'PRJ\x00\x00\x00\x00\x00'
INFO: Initializing flash...
INFO: Writing 232652 bytes (227K) at offset 0x0
[########################################] 100% (232652/232652)
Flash complete!
-v/-vv— increase verbosity--offset 0x40000— write at a specific flash offset--erase-all— full chip erase before writing (SPI NOR only, default: sector erase)--no-reboot— don't reboot the device after flashing--timeout SECONDS— override USB bulk-transfer and write-ACK timeouts (default: 120s)--gpio PORT STATE— drive a GPIO pin via the boot ROM before SPL load (repeatable, see below)
The --gpio flag drives GPIO pins while still in boot-ROM mode — the earliest reachable point in a USB-boot session. This is useful for asserting the PMIC power-hold line so the board stays alive without the operator holding the power button:
$ ingenic-flash-tool -v flash prj008 firmware.bin --gpio PB15 on
PORT is PA0–PD31 (the P prefix is optional). STATE is on/off (also accepts high/low, 1/0). Repeat the flag for multiple pins:
$ ingenic-flash-tool flash prj008 firmware.bin --gpio PB15 on --gpio PC20 off
Boot into stage2 burner without flashing (useful for debugging):
$ ingenic-flash-tool boot prj008
Device booted into stage2: b'PRJ\x00\x00\x00\x00\x00' (50524a0000000000)
$ ingenic-flash-tool info
Supported chips:
prj008 PID=0xc309 ginfo=0x80001000 [bundled]
prj008_mmc0 PID=0xc309 ginfo=0x80001000 [bundled]
t20 PID=0xc309 ginfo=0x80001000 [bundled]
...
| Board/Target | Flash Type | Status |
|---|---|---|
| prj008 | SPI NOR | Full support (T31/T33 camera board) |
| prj008_mmc0 | eMMC/SD | Full support (MSC0 slot) |
| T20–T41 | — | Boot only (need board-specific ginfo + config) |
| 40+ chips | — | Bundled SPL/U-Boot for all Ingenic SoCs |
Full flash support requires board-specific firmware files (ginfo.bin, spl.bin, uboot.bin, and config blobs). PRJ008 files are bundled for both SPI NOR and eMMC.
The tool implements the Ingenic USB boot protocol, reverse-engineered from USB packet captures:
-
Boot ROM — The SoC enters USB boot mode. The tool sends a DDR configuration block (ginfo) and first-stage bootloader (SPL) via vendor USB requests.
-
SPL — The SPL initializes DDR memory, then stays resident and re-implements USB. It does not return to the boot ROM. The tool sends the stage2 burner firmware (U-Boot) via the SPL's USB interface.
-
Stage2 Burner — A specialized U-Boot build that handles flash operations. The tool sends board configuration, then writes firmware in 64KB chunks with CRC verification. Supports SPI NOR (with JEDEC auto-detection), SPI NAND, and eMMC/SD.
Boot ROM requests: GET_CPU_INFO(0x00), SET_DATA_ADDR(0x01), SET_DATA_LEN(0x02),
PROGRAM_START1(0x04)
SPL requests: FLUSH_CACHES(0x03), PROGRAM_START2(0x05)
Stage2 requests: GET_ACK(0x10), INIT(0x11), WRITE(0x12), UPDATE_CFG(0x14),
REBOOT(0x16), GET_FLASH_INFO(0x26)
Key discovery: FLUSH_CACHES and PROGRAM_START2 are only supported by the resident SPL, not the boot ROM (contrary to the JZ4760 documentation). The boot ROM only supports requests 0x00–0x02 and 0x04.
git clone https://github.com/will-tm/ingenic-flash-tool.git
cd ingenic-flash-tool
python -m venv .venv
source .venv/bin/activate
pip install -e .MIT