Quansheng UV-K5 · Volume 6
Quansheng UV-K5 Volume 6 — Flashing & Recovery
The bootloader, k5prog and the browser web-flashers, why the binary is generation-specific, verifying the hardware generation before flashing, a reproducible workflow, and how to unbrick
6.1 About this Volume
Flashing a UV-K5 is the single moment where a $30 radio becomes a hacker’s tool — and the single moment where it is easiest to turn one into a paperweight. The good news is that the radio’s stock bootloader is a permanent, un-overwritable recovery path: the practical consequence is that almost every “brick” is a soft-brick, recoverable in two minutes without opening the case. This volume treats flashing as an engineering procedure with a verification step in front of it, not a point-and-pray web click.
The through-line is one fact that Volume 2 established at the silicon level and this volume turns into an operational rule: the firmware image is specific to the radio’s MCU generation. Flashing a binary built for the wrong generation is the most common way people soft-brick these radios. So the order of operations here is deliberate — identify the generation (§3), choose the matching image (§4), only then flash (§5–§7) — and recovery (§8) is presented as a routine step you should expect to use at least once while learning, not as an emergency.
Cross-references: Volume 2 is the hardware/MCU-generation reference (what DP32G030 / PY32F030 / PY32F071 are and how they differ); Volume 3 carries the supported-radios-and-firmware table that §4 depends on; Volume 7 covers channel-plan programming once the custom firmware is running; Volume 8 covers building your own image from source, which produces exactly the two files §2 describes.
6.2 The bootloader and the two-image build
The UV-K5’s MCU holds two logically distinct regions: a small bootloader at the bottom of flash that Quansheng programs at the factory and that custom firmware never touches, and the application region above it that holds the radio’s actual firmware. Powering the radio on while holding the right key tells the bootloader to stay resident and wait for a new application image over the serial cable, instead of jumping to the application. Because the bootloader itself is never rewritten by a normal flash, the recovery path in §8 is always available even after a failed flash — this is the architectural reason a UV-K5 is so hard to truly kill.
A custom-firmware build produces two files, and knowing which is which prevents a whole class of confusion:
Table 1 — A custom-firmware build produces two files, and knowing which is which prevents a whole class of confusion
| File | What it is | Who consumes it |
|---|---|---|
firmware.bin | The raw, un-obfuscated application image | Emulators, disassembly, some web-flashers that pack it for you |
firmware.packed.bin | The same image wrapped in the obfuscation layer + version string the stock bootloader expects | k5prog, and web-flashers that send the image verbatim |
The “packing” is a lightweight obfuscation plus a version-string header the bootloader checks before it accepts the write — it is a format requirement, not security. The operational rule: send the image the tool asks for. Some web-flashers take the raw firmware.bin and pack it in the browser; k5prog and verbatim web-flashers want firmware.packed.bin. Fork release pages state which of the two the release .bin already is; when in doubt, the packed image is the one the radio’s bootloader natively accepts.
Note — the version string is a feature, not a nuisance. The bootloader echoes the packed image’s version string to the display during flashing. Reading that string back and confirming it matches the fork/version you intended is the cheapest possible sanity check that you fed the radio the file you meant to.
6.3 Verifying your hardware generation first
There are three firmware-incompatible hardware generations, distinguished by MCU. Volume 2 covers the silicon; here is the operational summary and how to read the generation off a radio in hand before you flash anything.
Table 2 — 3. Verifying your hardware generation first
| Gen | MCU | Rough era | Flash budget | Firmware reality |
|---|---|---|---|---|
| V1 | DP32G030 | 2022 – early 2024 | Smallest | The classic target; the huge installed base. egzumer, F4HWN ≤ v4.3, VUURWERK all target it. |
| V2 | PY32F030 | transitional | Small/medium | A Puya part that appeared as Quansheng second-sourced the MCU; narrower fork coverage. |
| V3 | PY32F071 | mid-2024 onward | Largest | The current target; F4HWN “Fusion” v5.x and the UV-K1 live here. |
Ways to determine the generation, cheapest first:
- Ask the seller / check the production date. New stock is overwhelmingly V3 (PY32F071). Old or clearance listings skew V1 (DP32G030). This is a probability, not proof — verify in software.
- Read it back over the cable. With the programming cable connected and the radio in normal (not bootloader) mode, a programmer tool can read the firmware-info/metadata block.
k5prog’s info read exposes the identifier the stock firmware reports. - Let the bootloader tell you. Some web-flashers, on connecting to a radio in bootloader mode, read and display the chip/version identity before offering to flash. Reading that and matching it to the image you are about to send is the belt-and-braces check.
# Read the radio's stock firmware info over the cable (radio in NORMAL mode).
# The reported version/metadata encodes the MCU family — note it before flashing.
./k5prog -p /dev/ttyUSB0 -F
Callout — do this once, write it down. The generation never changes for a given physical radio. Determine it once, label the radio (a strip of tape on the battery reading
V3 / PY32F071), and you never have to re-derive it. Mis-labelling is how the wrong-binary mistake in §10 happens.
6.4 Which .bin for your radio — the decision aid
With the generation known from §3, this maps it to a firmware choice. See Volume 3 for the full supported-radios-and-firmware table and Volume 4 for the ecosystem/fork comparison that justifies these picks; this is the fast operational version.
┌─────────────────────────────────────────┐
│ What MCU does your radio report? (§3) │
└───────────────┬─────────────────────────-┘
│
┌────────────────────────┼────────────────────────────┐
▼ ▼ ▼
DP32G030 (V1) PY32F030 (V2) PY32F071 (V3)
│ │ │
▼ ▼ ▼
Daily driver: Check the fork's Daily driver:
egzumer v0.22 release page for a F4HWN "Fusion"
(frozen, most- V2/PY32F030 asset. v5.9.0 (V3 + UV-K1)
installed) OR Coverage is the │
F4HWN v4.3 (last narrowest of the three; ▼
V1 build) OR a V3 image will NOT Feature-rich,
VUURWERK v1.5.0 run on a V2 and vice actively maintained,
│ versa. largest flash headroom
▼
Choose a *V1/DP32G030*
asset from the release
Table 3 — 4. Which .bin for your radio — the decision aid
| Your radio (from §3) | Recommended image | Why | Also runs |
|---|---|---|---|
| V1 — DP32G030 | egzumer v0.22 (frozen 2024-01-28) | The most-installed, most-documented build; merges OneOfEleven’s refactor + fagci’s spectrum | F4HWN v4.3 (last V1 build, 2025-12-02); VUURWERK v1.5.0 (2026-07-04) |
| V2 — PY32F030 | Whichever active fork publishes a V2 asset | Narrowest coverage; match the exact PY32F030 asset | — |
| V3 — PY32F071 | F4HWN “Fusion” v5.9.0 (2026-08-14) | Current flagship fork; also covers the UV-K1 | Other forks as they publish V3/PY32F071 assets |
Hard rule. The three generations are mutually incompatible. A V3 (PY32F071) image flashed to a V1 (DP32G030) radio — or any other mismatch — soft-bricks it. The radio is recoverable (§8), but the only way to avoid the detour is to match the generation to the asset on the release page, every time. Release pages name the generation in the filename or asset list; if a release offers only one
.binwith no generation marker, assume it is the fork’s primary target (V1 for egzumer/VUURWERK, V3 for F4HWN Fusion) and confirm before flashing.
6.5 Entering bootloader (flash) mode
The flash procedure begins by forcing the bootloader to stay resident:
1. Power the radio OFF.
2. Connect the programming cable (3.5 mm + 2.5 mm dual plug) to the radio and PC.
3. Hold the PTT button (some fork docs also say hold the side/flashlight key).
4. While holding, switch the radio ON.
5. The display stays dark or shows a solid/patterned backlight, and (on many units)
the flashlight LED lights — this is the bootloader waiting for an image.
6. Release the key. The radio will sit in this mode for a short window; start the
flash promptly.
The exact key combination has drifted slightly across firmware eras and fork docs, which is why fork READMEs are the authority for the model in front of you. The reliable tell is the display: a normal power-on shows the UI; bootloader mode shows a dark/plain screen (and usually the lit flashlight), and the radio does not respond to the keypad.
Note. If the radio boots normally into its UI, it did not enter bootloader mode — power off and retry, holding the key before the power switch moves. A radio in normal mode will not accept a firmware write; the programmer will time out.
6.6 Flashing with k5prog
k5prog (sq5bpf, Python/C over the serial bootloader) is the command-line path. It is the tool of choice when scripting, when the browser Web Serial path is unavailable, or when you want an auditable, repeatable command rather than a GUI.
# 1. Build or download the image for YOUR generation (§4). Example: a V1 build.
# egzumer's build emits firmware.bin (raw) and firmware.packed.bin (bootloader format).
# 2. Put the radio in bootloader mode (§5).
# 3. Confirm the serial device enumerated (clone cables use CH340/CP2102/PL2303):
dmesg | tail # look for ttyUSB0 / ttyACM0
ls -l /dev/ttyUSB*
# 4. Flash the packed image. -p selects the port; -F selects flash-firmware mode.
./k5prog -p /dev/ttyUSB0 -F firmware.packed.bin
# 5. Power-cycle the radio. It boots into the new firmware.
A few operational notes:
- Feed the packed image to
k5prog. The rawfirmware.binis for emulators/disassembly (Volume 8); the bootloader wantsfirmware.packed.bin. Fork releases state which of the two their published.binalready is. - Serial permissions. On Linux, add your user to the
dialoutgroup (or run with sufficient privilege) so the port is writable without root:sudo usermod -aG dialout $USERthen re-login. - Baud and timing are fixed by the bootloader. You do not tune them;
k5progalready speaks the bootloader’s protocol. A timeout almost always means the radio is not actually in bootloader mode (§5) or the cable is bad (§10), not a baud-rate problem.
Callout — k5prog is also your EEPROM tool. The same utility reads and writes the channel/calibration EEPROM, which Volume 7 uses for channel-plan work. Firmware flashing and EEPROM programming are separate operations on the same cable; do not confuse a firmware flash (
-F) with an EEPROM read/write.
6.7 The browser web-flashers
The mainstream, zero-install path is a Web Serial flasher that runs in a Chromium-based browser (Chrome/Edge). The community maintains several; egzumer ships one from the firmware project, and other forks link their own. The appeal is that there is nothing to install and the flasher can present the radio’s identity and the firmware version string in the UI before you commit.
Web-flasher workflow (Chromium-based browser, Web Serial):
1. Open the fork's flasher page over HTTPS.
2. Put the radio in bootloader mode (§5).
3. Click "Connect" → the browser's serial-port picker appears → choose the
radio's port (CH340/CP2102/PL2303).
4. Select the firmware: either upload the .bin for YOUR generation, or pick
from the flasher's built-in version list (confirm the generation!).
5. Click "Flash". Watch the progress + the reported version string.
6. Power-cycle.
Table 4 — 7. The browser web-flashers
| Path | Strengths | Watch-outs |
|---|---|---|
| Web-flasher | No install; shows radio identity + version; built-in version lists; cross-platform | Needs a Chromium-based browser with Web Serial; some pick-from-list menus make a wrong-generation choice one careless click away |
| k5prog (CLI) | Scriptable, auditable, works headless; also does EEPROM | Manual install; you supply the correct image yourself |
Note — Web Serial, not Bluetooth. These flashers drive the wired programming cable over the browser’s Web Serial API. Firefox and Safari do not implement Web Serial; use a Chromium-based browser or fall back to
k5prog.
Callout — the generation trap in list-based flashers. The convenience feature — “pick egzumer v0.22 from the dropdown” — is also the hazard: the dropdown may default to one generation’s asset. Before clicking Flash, confirm the selected build matches the generation you determined in §3. A mismatch here is the single most common cause of the soft-brick in §8.
6.8 Recovery and unbrick
Because the bootloader is never overwritten (§2), a UV-K5 that “won’t turn on” after a bad flash is almost always a soft-brick: the application region is corrupt or holds a wrong-generation image, but the bootloader is intact and still listening. The recovery is simply flash again, correctly.
UNBRICK PROCEDURE
1. Symptom: dark screen / no UI / won't boot after a flash.
2. Do NOT panic-flash more wrong-generation images.
3. Re-verify the generation (§3) — the brick is usually a generation mismatch.
4. Enter bootloader mode (§5). A soft-bricked radio STILL enters bootloader mode;
that is the whole point of the un-overwritable bootloader.
5. Flash the CORRECT image for the generation (§6 or §7) — this can be the
matching custom firmware, OR Quansheng's official stock firmware.
6. Power-cycle. The radio returns.
Table 5 — 8. Recovery and unbrick
| Recovery image | When to use |
|---|---|
| Correct-generation custom firmware | You simply flashed the wrong generation; re-flash the right one |
| Quansheng official stock firmware | You want a known-good baseline, or to return the radio to factory behaviour; download the stock image matching the generation from Quansheng’s channels |
Hard rule — the bootloader is your safety net, so don’t poke it. Standard custom-firmware flashing never touches the bootloader and therefore never removes the recovery path. Avoid any “bootloader replacement” procedure unless you fully accept that it is the one operation that can produce a hard-brick requiring hardware (SWD) recovery. For normal modding, you never need to.
Callout — a truly dead radio (rare). If the radio will not even enter bootloader mode — no dark-screen state, no response on the cable with a known-good cable — the causes are almost always outside the firmware: a dead battery, a bad cable (§10), or hardware damage. Rule those out before concluding the bootloader is gone; a genuinely corrupted bootloader is uncommon and would need SWD-level reflashing on the MCU, which is out of scope for a $30 radio.
6.9 A reproducible flashing workflow
Putting §3–§8 together as a checklist you can run every time, V1 example shown:
UV-K5 FLASH — REPRODUCIBLE WORKFLOW
────────────────────────────────────────────────────────────
[ ] 0. Charge the battery to >50% (brownout mid-flash is avoidable grief)
[ ] 1. IDENTIFY generation (§3): k5prog -p /dev/ttyUSB0 -F → read MCU metadata
→ write it on the radio's tape label (e.g. "V1 / DP32G030")
[ ] 2. CHOOSE image (§4): download the asset whose filename/notes name THIS gen
→ verify the fork + version is the one you intend
[ ] 3. BACK UP (optional but wise): k5prog read of the EEPROM (channels+cal) → Vol 7
[ ] 4. CABLE check: dmesg / ls /dev/ttyUSB* → note CH340/CP2102/PL2303
[ ] 5. BOOTLOADER mode (§5): power off → hold PTT → power on → dark screen + light
[ ] 6. FLASH (§6 or §7):
CLI: ./k5prog -p /dev/ttyUSB0 -F firmware.packed.bin
Web: Connect → select THIS-gen image → Flash → watch version string
[ ] 7. VERIFY: confirm reported version string == intended fork/version
[ ] 8. POWER-CYCLE → radio boots new firmware
[ ] 9. RESTORE channels/settings (Vol 7) if the flash reset the EEPROM layout
────────────────────────────────────────────────────────────
If step 8 fails → you are at §8 (unbrick): re-verify gen, re-enter bootloader,
re-flash the CORRECT image (custom or stock). The bootloader is still there.
Note — back up the EEPROM before your first flash. Custom firmwares can reorganise the EEPROM channel layout, and a factory-stock radio holds calibration data in the high EEPROM region (Volume 7 §memory-map) that you never want to lose. A one-command EEPROM read with
k5progcaptures channels and calibration as a file you can write back; it costs thirty seconds and is cheap insurance.
6.10 Pitfalls and gotchas
Table 6 — 10. Pitfalls and gotchas
| Pitfall | Symptom | Fix |
|---|---|---|
| Wrong-generation binary | Soft-brick: dark screen, no boot after flash | §8 — re-enter bootloader, flash the correct-generation image. Prevent by labelling the radio (§3). |
| Bad / miswired clone cable | k5prog timeout or junk; web-flasher can’t connect | Try another cable; confirm the USB-serial bridge driver (CH340/CP2102/PL2303) matches what enumerated |
| Radio not actually in bootloader | Programmer times out; radio shows normal UI | Re-do §5, holding the key before flipping the switch; confirm dark screen + flashlight |
| Non-Chromium browser for web-flasher | No “Connect” button / Web Serial unavailable | Use Chrome/Edge (Web Serial), or fall back to k5prog |
| Raw vs packed image mismatch | Bootloader rejects the image | Feed k5prog/verbatim flashers the .packed.bin; let packing-aware flashers take the raw .bin |
| Battery brownout mid-flash | Flash stalls / radio resets partway | Charge to >50% first; the flash itself is brief but a dying cell can reset the MCU |
| Lost channels/calibration after flash | Memories gone; TX power or squelch off | Restore the EEPROM backup (§9 step 3); never overwrite the calibration region (Vol 7) |
| Port permissions (Linux) | Permission denied on /dev/ttyUSB0 | Add user to dialout, re-login; avoid blanket root if you can |
Callout — the one habit that prevents most grief. Every soft-brick story traces back to a skipped identification step. Determine the generation once, label the radio, and confirm the image’s generation on the release page and in the flasher UI before clicking. Everything else in this table is a cable or a battery.
See Volume 7 for channel-plan programming now that custom firmware is running, Volume 8 to build the image yourself from source, and Volume 3 for the full supported-radios-and-firmware table referenced throughout.
Comments (0)