Moving from Stock DM-32UV Firmware
This chapter is for a Baofeng DM-32UV running Baofeng's stock firmware. One program, dm32_migrate.py, does the
whole move over the programming cable:
- It reads your codeplug from the radio: channels, zones, contacts, RX group lists, your DMR ID.
- It flashes RadioFoundry through the radio's own bootloader (update mode).
- It writes the codeplug back, plus the DMR ID (callsign) database.
The web installer and the Codeplug Editor do the same in two steps (Installing). Use this program
to do all of it in one run. What has been checked on the radio is in the Radio reference,
and the bring-up checklist lists what is open. Keep Baofeng's firmware file
(DM32.01.01.049.bin), so you can go back to stock.
RadioFoundry never touches the bootloader, so update mode always works. It never touches the data flash below 7 MB either. The stock codeplug, the factory calibration and the stock contact database live there. Going back to stock gives you your old codeplug as it was.
What you need
| Item | Notes |
|---|---|
| Python 3.8 or newer | macOS, Linux and Windows. Tested on files only |
| qdmr 0.15 or newer | Brings the dmrconf command that reads the stock radio and converts the codeplug. macOS: brew install qdmr. Linux: your distribution's qdmr package. Windows: the installer from dm3mat.darc.de/qdmr |
pip install pyserial |
For the cable |
| The RadioFoundry image | rfoundry_dm32_codec.bin with the codec merged in, from the tester kit or your own build (bring-up checklist, step 0). An image without the codec works with --codec-from DM32.01.01.049.bin |
| The programming cable | The DM-32's USB-serial cable (CH340, FTDI or CP210x). The radio has no USB of its own: the stock CPS, the bootloader and RadioFoundry all use this cable |
A tester kit (dm32_migrate.py package) is one folder with the scripts, their helpers, the image, a README.txt
and a requirements.txt.
Run it
Look at every step first. This reads only files and touches nothing:
python3 dm32_migrate.py all --image rfoundry_dm32_codec.bin --dry-run
Then run it for real. With one USB-serial cable plugged in, the program finds it. Otherwise add
--port /dev/ttyUSB0 (Linux), --port /dev/cu.usbserial-XXXX (macOS) or --port COM5 (Windows):
python3 dm32_migrate.py all --image rfoundry_dm32_codec.bin
The program asks before each step that needs you at the radio:
| Step | You do | The program does |
|---|---|---|
| 0. Check | nothing | Checks dmrconf, pyserial, the cable and the image. If something is missing, it stops before it touches the radio |
| 1. Backup | Switch the radio on normally, cable in | Reads the codeplug (backup-stock.dfu, backup-stock.yaml). Converts it for RadioFoundry and shows what fits and what doesn't (conversion-report.txt) |
| 2. Flash | Radio off. Hold PTT and SK1 (the side key just below PTT), switch on. The green LED lights | Asks once more, then writes RadioFoundry. The radio erases its old firmware first, which takes up to 15 s |
| 3. Settings area | Wait for the RadioFoundry Home screen | Checks the radio runs RadioFoundry. If stock data sits where RadioFoundry keeps its settings, it asks, saves that area to a file, and gives it to RadioFoundry |
| 3b. Data flash backup | nothing | Reads the stock codeplug and calibration area (800 KB, about 2 minutes) into the work directory. --flash-backup full saves all 16 MB (about 30 minutes), none skips it |
| 4. Codeplug | nothing | Saves what was in RadioFoundry's codeplug area, writes the codeplug, waits for the restart, reads it back and compares |
| 5. ID database | nothing | Writes the DMR ID database. A large one takes many minutes over the cable |
It keeps everything in ~/RadioFoundry-DM32-migration/<date-time>/ and never deletes those files. If a step fails, it
stops and says why. When the failure comes after the flash, it prints the command that continues:
python3 dm32_migrate.py restore --workdir ~/RadioFoundry-DM32-migration/20261011-101500
Your codeplug from a file
--from takes a codeplug saved with qdmr from the stock radio. It can be a .dfu (dmrconf read --radio dm32uv)
or a .yaml. dm32_migrate.py import --from FILE only converts and checks, with no radio needed. Files from Baofeng's
own CPS aren't supported here. Read the radio with qdmr and save the codeplug from there.
What fits
RadioFoundry holds 1024 channels, 68 zones of 80 channels, 1024 contacts and 76 RX group lists, with names of up to 16
characters. The stock radio holds more. If yours has more, the program lists what would be left out (the last ones).
It asks before it flashes. To choose yourself, open backup-stock.yaml in qdmr and delete what you don't need. Save
it, and run again with --from on the saved file.
The program also tidies the RX group lists: lists that hold only the channel's own talkgroup go (RadioFoundry always hears the
talkgroup a channel talks to), as do empty, duplicate and unused ones. Every channel keeps its talkgroup.
--no-cleanup keeps the lists as they are.
conversion-report.txt lists everything that changes: counts before and after, names that get shortened, channels
outside 136-174 and 400-480 MHz, and the parts of the codeplug RadioFoundry doesn't use. These parts aren't carried over: the
stock menu, key and display settings, scan lists, roaming, GPS and APRS settings, encryption keys and the stock
contact database. RadioFoundry
uses the parts of the codeplug listed in Programming the radio.
The DMR ID database
By default, dmrconf downloads the public DMR user database and picks the IDs nearest yours (internet needed). The
radio holds about 300,000 records. When the list is longer, the tool keeps the ones nearest your ID.
--users FILE takes radioid.net's user.csv instead. Options: --db-limit N, --id-prefix, --no-db.
Flashing only
serial_loader.py flashes any image without touching the codeplug:
python3 serial_loader.py --model dm32 rfoundry_dm32_codec.bin # a raw image (a _BFUV32.bin file needs no --model)
python3 serial_loader.py --list-ports # the cables it sees
Going back to stock
Baofeng's firmware file goes through the same bootloader:
python3 serial_loader.py --stock DM32.01.01.049.bin
The stock codeplug was never overwritten, so the radio comes back with it. If it doesn't, write backup-stock.dfu with
qdmr (dmrconf write --radio dm32uv). RadioFoundry's own data stays at 7 MB and up. The stock firmware may later reuse that
space.
Limits and notes
- If the radio doesn't start after a flash, remove and refit the battery. Update mode still works.
- The program never changes the radio's calibration.
- Linux: add yourself to the
dialoutgroup for the cable. - Windows: install the cable's driver (CH340 or FTDI) first. Untested.