Creating a simple BW16E (RTL8720DN) DIY flash tool command line utility

I've been recently experimenting with simple flashing code for BW16E (RTL8720DN AmebaD) board, in theory also working for any of RTL872xDx family. RTL8720DN is a WiFi (2.4GHz and 5GHz) and Bluetooth (LE 5.0) module that features dual core CPU using KM4 and KM0 cores. It can be bought for as low as 1$. Here I will show my experiences with programming this board and briefly describe the flashing process.


The goal of this topic will be to create a simple C# flash tool that can write OpenBeken firwmare port to RTL8720DN.
First experiments
I've started by looking for simple and easy to use flashers supporting RTL8720DN. After some time, I've decided to RTL872xDx python tool.rar that was shown previously on our forum. Reading seemed to work well, however we had to add longer delay to function waiting for MCU response. Read command:
python rtltool.py -p COM7 -b1500000 rf 0x0 0x400000 bw16_rtltool.bin
I couldn't get it to write, though. It worked for other boards, but failed on RTL8720DN every time:
python rtltool.py -p COM4 -b 100000 wf 0 ff1_4mb.bin
Error message was:
error: Set Flash Status
Same problem was reported by other users. I played around with the code and figured out that the culprit is the unsupported flash unprotect, which seems to work on other RTLs, but breaks on RTL8720. Commenting it out solved the issue and flashing proceeded correctly.
Simple flasher implementation
My simple flasher is available on Github, here:
https://github.com/openshwprojects/SharpRTL872xTool
Released repository also contains sample scripts and dumps:
https://github.com/openshwprojects/SharpRTL872xTool/tree/main/samples
If there is no imgtool_flashloader_amebad.bin next to downloaded exe, make sure to download it from there!
The flash read procedure seems fairly simple. It can be divided into the following steps:
- first, MCU is put in flashing mode and reset via RTS/DTS pins
- next, a simple xmodem loader code is read from file and put into the device RAM (this step is skipped if code section header bytes are already present in RAM)
- finally, flash is read in 1024/128 chunks via Xmodem protocol
Similar approach is used for flash write, altough then, first required sectors are erased and then written.
Let's consider procedure in details.
Initial reset sequence
BW16E board, like many other boards, features RESET and BOOT pins. They are controlled via CH340 DTR and RTS lines. Boot must be held low while RESET is released in order to enter flashing mode.
Code: C#
Command system
Command system is very simple. First N bytes are written and then flasher waits for a single expected byte. If no expected response is met, then communication is assumed to have failed. I am suprised by the simplicity of this approach, I was rather expecting at least some kind of CRC check somewhere in the way, but original rtltool is missing it as well.
Code: C#
Baud setting
Baud setting is tricky, because the MCU would just lose the communication if not notified about change. That's why there is a specific packet that first sends new value to the MCU, then waits for acknowledge, and then, finally, adjusts the baud.
Code: C#
Writing RAM code
To communicate with flash memory, a helper binary (imgtool_flashloader_amebad.bin) must be uploaded into MCU SRAM. This file contains the flashloader used by Realtek’s official tools. Before uploading, the flasher checks whether the RAM already contains a valid loader by examining the first 4 bytes. If not present, the file is sent using XMODEM protocol.
Code: C#
NOTE: 33 dec is 0x21 hex, and so on.

Writing memory
After RAM is loaded with the loader code, commands like erase, write, and read can be executed. Writing uses XMODEM and automatically breaks data into 1024 or 128 byte chunks, depending on how much remains.
Code: C#
Test scripts
To verify and experiment with the flasher tool, I prepared several simple batch scripts that perform common operations such as erasing, writing, and reading flash memory. These scripts automate the command line usage of the flasher executable and help to easily reproduce basic flash operations.
The first script, erase_4mb.cmd, erases the first 4 megabytes of flash starting at address 0. This is useful for clearing the entire main flash region before writing new firmware or data. OpenBeken was not booting correctly without it! The erase command (ef) takes the start address and length as parameters:
RTL872xDx_Flasher.exe -p COM3 -b 1500000 ef 0 0x400000
pause
Next, write_obk.cmd writes a full firmware image file to the flash memory starting at address 0. This script is essential for flashing a new program image to the device after erasing:
RTL872xDx_Flasher.exe -p COM3 -b 1500000 wf 0 OpenRTL8720D_1.18.135.bin
pause
OpenBeken then should be able to boot:


However, I've added some more test scripts. They operate on smaller flash section, so are quicker to run.
For a simple test, try erase_4096.cmd and then read_4096_dump_bin.cmd, you should get:

After doing write_lorem_ipsum.cmd the read_4096_dump_bin.cmd should give:

Similary, read back after write_obk.cmd should show:

This way you can reliably check whether read and write works.
Summary
The mentioned repository should provide a basic method for flashing RTL8720DN. I am not sure if it will work for other RTLs from the same family, as I omited the flash protection code. Soon I'm going to try them as well, but first I will most likely integrate ported code with our easy flasher
Do you have any similar RTL boards? Let us know if this flashing solution works for you!
Comments
RTL872xDx_Flasher.exe -p COM45 -b 1500000 rf 0 0x400000 dump.bin === ReadFlash === Connecting... Connected Set baudrate 1500000 Write SRAM at 0x00082000 to 0x00083250 from file: imgtool_flashloader_amebad.bin Set... [Read more]
What? Easy Flasher can't read RTL? Let me check... https://obrazki.elektroda.pl/9478692600_1752431426_bigthumb.jpg Ah wait, you don't have stub! https://obrazki.elektroda.pl/5248347200_1752... [Read more]
oh. ok sure. I assumed it was embedded in somehow already. cool https://obrazki.elektroda.pl/5468015100_1752431822_bigthumb.jpg [Read more]
Do you have other RTLs from the same family to try? Do they need flash unprotect? [Read more]
negative. I never did get a WBRG1 in the end. @insmod and @dedamraz have that module though. I only have CR3L/RTL8720CM and RTL8720CF options - Z2 [Read more]
I see.... I am considering next steps to take now, of course, first I will port write to Easy Flasher, and then, maybe this: https://github.com/openshwprojects/FlashTools/tree/main/Realtek/AmebaZ_FlashTool Or... [Read more]
I got Ai Thinker BW15 module with CF, also BW16 and BW20-12F - these naming schemes are driving me crazy. [Read more]
Which of those RTLs support variable flash size (i.e. external flash memory)? [Read more]
No clue, haven't look into that detail at all. [Read more]
BW16E/RTL8720DN does https://www.elektroda.com/rtvforum/viewtopic.php?p=21444276#21444276 [Read more]
Usually, if chip last letter is F - means embedded flash, M - external. All RTL8710B have external flash. Almost all RTL8720D/CS except RTL8720DF (4mb), Normal BW16 usually comes with 2MB flash chip,... [Read more]
So if I unshield the board from the topic, then I can give it like 8MB flash or something, like it's often done with ESP? Nice, gotta try someday. Easy Flasher progress report - read and write are... [Read more]
Can you somehow get flash id? If so, then do it like i've done on RTL8721DA (1 << (flash_ID[2] - 0x11)) / 8 Same method can be applied to beken (like those 4mb BK7252) [Read more]
definitely +1 on this. otherwise users will only get half or quarter backup depending on device. custom read or another tool becomes the favourable option in this case. also. BK7252N/BK7252U split..?... [Read more]
Is there anyone with 2MB version of this RTL? I had a weird idea, because I did this SPI driver from previous article, you know? https://www.elektroda.com/rtvforum/topic4129001.html And I tried to... [Read more]
I have 2MB BW16. I could also solder 16mb chip to another BW16. Is GH branch or binary available somewhere? [Read more]
I will push code in a moment. I just HAD to check. https://obrazki.elektroda.pl/7014185800_1752485489_bigthumb.jpg https://obrazki.elektroda.pl/5190176900_1752485488_bigthumb.jpg https://obrazki.elektroda.pl/1765547200_1752485488_bigthumb.jpg... [Read more]
2mb ok Serial port open! Sending RAM code... Setting baud rate 1500000 (given as 1500000)...... OK! Write SRAM at 0x00082000 to 0x00083250 from file: imgtool_flashloader_amebad.bin Write... [Read more]
I didn't do automatic size determination yet, it always reads 2MB. The only thing you can check so far is whether flash ID read works. Added after 1 [minutes]: I can see in your log that it recognized... [Read more]