How to read and backup flash of BL602/BL702/etc device with BLDevCube? Burning tutorial, pinout

BL602 is a WiFi+Bluetooth 32-bit SoC found in some Sonoff and eWeLink devices. It comes in 2MB and 1MB flash versions, but here I will focus on 2MB one. BL702, on the other hand, is a Zigbee chip. They both can be read and flashed with BLDevCube, here are the connection details and step by step guide for flash read.
Hardware setup
Let's start by considering the GPIO pinout of BL602 and determine which signals we will need to read and write flash.

Remember that dot marks the first pin!
Required connections are:
- GPIO16 (TX) - connect to USB to UART converter in 3.3V mode (like CH340, etc)
- GPIO7 (RX) - connect to USB to UART converter in 3.3V mode (like CH340, etc)
- GPIO8 (Boot) - must be connected to 3.3V via 10k resistor
- VDD (3.3V)
- GND - ground of power supply and USB to UART converter must be common
The 3.3V power supply must be reliable, it may not be enough to power it from USB to UART converter. It may fail to flash or bootloop on AP creation/connect. Wires should be short. Do not connect boot directly to 3.3V. Make sure to do power off/on cycle between each flash operation, just like on ESP.
Disconnect device from mains before doing any operations on it!!!
Hardware setup - example BL602
Here's BW2L module, as desoldered from eWeLink E14 candle RGBCW bulb. It has no pin markings, so we have to determine which pin is which. Luckily, we have our GPIO diagram, the one I made in previous section.

Now we can use multimeter to test which pad connects where.
Here are my connections:




Please note few things:
- UART wires are relatively short
- on the proto board, there is a 3.3V LDO powered from 5V, so we can get good 3.3V for WiFi module. I am using TC1264, but you can use AMS1117 or any other, or get 3.3V from NodeMCU or Arduino
- the 10k resistor for BOOT is clearly visible
- when in doubt, swap RX and TX
Hardware setup - example BL702
Here's second hardware sample, this time with Zigbee chip. This time silkscreen with markings was present, so there was no guessing involved.





Not much extra commentary is required here, as the process is the same as for BL602.
Flash read - Bouffalo Lab DevCube v1.9.0
v1.9.0 is the newer version of Bouffalo Labs BLDevCube.exe, get it from here:
https://github.com/openshwprojects/FlashTools
Unpack, and first select chip type:

Enable advanced view:

Open Flash Tab:

Select your com port, enter start offset (0x0) and read length (0x1FFFFF). Use "read flash", do not press "erase"!

If you are getting:
[16:56:43.375] - Read operation
[16:56:43.376] - ========= flash read =========
[16:56:47.406] - Read data error,maybe not get excepted length
[16:56:47.406] - Retry
[16:56:49.408] - ack is b''
[16:56:49.409] - Not ack OK
Then lower baud. 200000 is ok, default 2000000 is too high.
For flash size, make sure that you are entering 0x1FFFFF. If you enter 0x200000, you will get:
[16:40:29.599] - ========= flash read jedec ID =========
[16:40:29.602] - Read flash jedec ID
[16:40:29.603] - flash jedec id: ef401580
[16:40:29.603] - Finished
[16:40:29.608] - get flash size: 0x00200000
[16:40:29.609] - Read operation
[16:40:29.609] - read flash end addr 0x00200000 was overflow with flash size 0x00200000
[16:40:29.609] - ErrorCode: 0045, ErrorMsg: BFLB FLASH SIZE OVER FLOW
[16:40:29.609] - Burn Retry
[16:40:29.610] - 0
[16:40:29.610] - Burn return with retry fail
So enter 0x1FFFFF as a work around, it's just one byte less than 0x00200000 .
Now flash read should work, wait patiently:

Flash read should be successful:

Here is successful flash read log:
[16:41:08.465] - Save as flash.bin
[16:41:08.467] - Version: eflash_loader_v2.5.1
[16:41:08.467] - Program Start
[16:41:08.467] - ========= eflash loader cmd arguments =========
[16:41:08.467] - Config file: W:\GIT\FlashTools\BouffaloLabs\BouffaloLabDevCube-v1.9.0\chips\bl602\eflash_loader\eflash_loader_cfg.ini
[16:41:08.469] - serial port is COM4
[16:41:08.470] - cpu_reset=False
[16:41:08.470] - chiptype: bl602
[16:41:08.470] - ========= Interface is uart =========
[16:41:08.470] - com speed: 200000
[16:41:08.470] - Eflash load helper file: W:\GIT\FlashTools\BouffaloLabs\BouffaloLabDevCube-v1.9.0\chips\bl602\eflash_loader/eflash_loader_40m.bin
[16:41:08.470] - ========= load eflash_loader.bin =========
[16:41:08.471] - Load eflash_loader.bin via uart
[16:41:08.471] - ========= image load =========
[16:41:08.701] - Not ack OK
[16:41:08.701] - FL
[16:41:08.701] - result: FL
[16:41:08.981] - tx rx and power off, press the machine!
[16:41:08.981] - cutoff time is 0.1
[16:41:09.089] - power on tx and rx
[16:41:09.904] - reset cnt: 0, reset hold: 0.005, shake hand delay: 0.1
[16:41:09.905] - clean buf
[16:41:09.906] - send sync
[16:41:10.133] - ack is 4f4b
[16:41:10.165] - shake hand success
[16:41:10.180] - get_boot_info
[16:41:10.183] - data read is b'0100000000000000030004002127eaedbb281700'
[16:41:10.183] - ========= chipid: 28bbedea2721 =========
[16:41:10.183] - last boot info: None
[16:41:10.183] - sign is 0 encrypt is 0
[16:41:10.184] - segcnt is 1
[16:41:10.192] - segdata_len is 38592
[16:41:10.277] - 4080/38592
[16:41:10.362] - 8160/38592
[16:41:10.447] - 12240/38592
[16:41:10.531] - 16320/38592
[16:41:10.616] - 20400/38592
[16:41:10.701] - 24480/38592
[16:41:10.786] - 28560/38592
[16:41:10.871] - 32640/38592
[16:41:10.955] - 36720/38592
[16:41:10.995] - 38592/38592
[16:41:10.997] - Run img
[16:41:11.108] - Load helper bin time cost(ms): 2636.855712890625
[16:41:11.216] - Flash load shake hand
[16:41:11.226] - default set DTR high
[16:41:11.338] - clean buf
[16:41:11.339] - send sync
[16:41:11.572] - ack is 4f4b
[16:41:11.619] - Read mac addr
[16:41:11.623] - macaddr: 2127eaedbb28
[16:41:11.623] - flash set para
[16:41:11.624] - ========= flash read jedec ID =========
[16:41:11.626] - Read flash jedec ID
[16:41:11.627] - flash jedec id: ef401580
[16:41:11.627] - Finished
[16:41:11.633] - get flash size: 0x00200000
[16:41:11.633] - Read operation
[16:41:11.633] - ========= flash read =========
[16:41:11.952] - Read 2048/2097152
Read 4096/2097152
Read 6144/2097152
[16:41:12.271] - Read 8192/2097152
Read 10240/2097152
Read 12288/2097152
[16:41:12.590] - Read 14336/2097152
(...)
[16:43:00.474] - Read 2091008/2097152
Read 2093056/2097152
Read 2095104/2097152
[16:43:00.581] - Read 2097152/2097152
[16:43:00.582] - Flash read time cost(ms): 108947.57373046875
[16:43:00.583] - Finished
[16:43:00.585] - All time cost(ms): 112118.49609375
[16:43:00.701] - close interface
[16:43:00.701] - [All Success]
File will appear where BLDevCube is:

You can also read eFuse:
[16:41:08.465] - Save as flash.bin
[16:41:08.467] - Version: eflash_loader_v2.5.1
[16:41:08.467] - Program Start
[16:41:08.467] - ========= eflash loader cmd arguments =========
[16:41:08.467] - Config file: W:\GIT\FlashTools\BouffaloLabs\BouffaloLabDevCube-v1.9.0\chips\bl602\eflash_loader\eflash_loader_cfg.ini
[16:41:08.469] - serial port is COM4
[16:41:08.470] - cpu_reset=False
[16:41:08.470] - chiptype: bl602
[16:41:08.470] - ========= Interface is uart =========
[16:41:08.470] - com speed: 200000
[16:41:08.470] - Eflash load helper file: W:\GIT\FlashTools\BouffaloLabs\BouffaloLabDevCube-v1.9.0\chips\bl602\eflash_loader/eflash_loader_40m.bin
[16:41:08.470] - ========= load eflash_loader.bin =========
[16:41:08.471] - Load eflash_loader.bin via uart
[16:41:08.471] - ========= image load =========
[16:41:08.701] - Not ack OK
[16:41:08.701] - FL
[16:41:08.701] - result: FL
[16:41:08.981] - tx rx and power off, press the machine!
[16:41:08.981] - cutoff time is 0.1
[16:41:09.089] - power on tx and rx
[16:41:09.904] - reset cnt: 0, reset hold: 0.005, shake hand delay: 0.1
[16:41:09.905] - clean buf
[16:41:09.906] - send sync
[16:41:10.133] - ack is 4f4b
[16:41:10.165] - shake hand success
[16:41:10.180] - get_boot_info
[16:41:10.183] - data read is b'0100000000000000030004002127eaedbb281700'
[16:41:10.183] - ========= chipid: 28bbedea2721 =========
[16:41:10.183] - last boot info: None
[16:41:10.183] - sign is 0 encrypt is 0
[16:41:10.184] - segcnt is 1
[16:41:10.192] - segdata_len is 38592
[16:41:10.277] - 4080/38592
[16:41:10.362] - 8160/38592
[16:41:10.447] - 12240/38592
[16:41:10.531] - 16320/38592
[16:41:10.616] - 20400/38592
[16:41:10.701] - 24480/38592
[16:41:10.786] - 28560/38592
[16:41:10.871] - 32640/38592
[16:41:10.955] - 36720/38592
[16:41:10.995] - 38592/38592
[16:41:10.997] - Run img
[16:41:11.108] - Load helper bin time cost(ms): 2636.855712890625
[16:41:11.216] - Flash load shake hand
[16:41:11.226] - default set DTR high
[16:41:11.338] - clean buf
[16:41:11.339] - send sync
[16:41:11.572] - ack is 4f4b
[16:41:11.619] - Read mac addr
[16:41:11.623] - macaddr: 2127eaedbb28
[16:41:11.623] - flash set para
[16:41:11.624] - ========= flash read jedec ID =========
[16:41:11.626] - Read flash jedec ID
[16:41:11.627] - flash jedec id: ef401580
[16:41:11.627] - Finished
[16:41:11.633] - get flash size: 0x00200000
[16:41:11.633] - Read operation
[16:41:11.633] - ========= flash read =========
[16:41:11.952] - Read 2048/2097152
Read 4096/2097152
Read 6144/2097152
[16:41:12.271] - Read 8192/2097152
Read 10240/2097152
Read 12288/2097152
[16:41:12.590] - Read 14336/2097152
[16:42:51.861] - Read 1925120/2097152
Read 1927168/2097152
Read 1929216/2097152
[16:42:52.180] - Read 1931264/2097152
Read 1933312/2097152
Read 1935360/2097152
[16:42:52.499] - Read 1937408/2097152
Read 1939456/2097152
Read 1941504/2097152
[16:42:52.819] - Read 1943552/2097152
Read 1945600/2097152
Read 1947648/2097152
[16:42:53.139] - Read 1949696/2097152
Read 1951744/2097152
Read 1953792/2097152
[16:42:53.457] - Read 1955840/2097152
Read 1957888/2097152
Read 1959936/2097152
[16:42:53.775] - Read 1961984/2097152
Read 1964032/2097152
Read 1966080/2097152
[16:42:54.094] - Read 1968128/2097152
Read 1970176/2097152
Read 1972224/2097152
[16:42:54.413] - Read 1974272/2097152
Read 1976320/2097152
Read 1978368/2097152
[16:42:54.732] - Read 1980416/2097152
Read 1982464/2097152
Read 1984512/2097152
[16:42:55.050] - Read 1986560/2097152
Read 1988608/2097152
Read 1990656/2097152
[16:42:55.369] - Read 1992704/2097152
Read 1994752/2097152
Read 1996800/2097152
[16:42:55.688] - Read 1998848/2097152
Read 2000896/2097152
Read 2002944/2097152
[16:42:56.007] - Read 2004992/2097152
Read 2007040/2097152
Read 2009088/2097152
[16:42:56.326] - Read 2011136/2097152
Read 2013184/2097152
Read 2015232/2097152
[16:42:56.645] - Read 2017280/2097152
Read 2019328/2097152
Read 2021376/2097152
[16:42:56.964] - Read 2023424/2097152
Read 2025472/2097152
Read 2027520/2097152
[16:42:57.282] - Read 2029568/2097152
Read 2031616/2097152
Read 2033664/2097152
[16:42:57.601] - Read 2035712/2097152
Read 2037760/2097152
Read 2039808/2097152
[16:42:57.921] - Read 2041856/2097152
Read 2043904/2097152
Read 2045952/2097152
[16:42:58.242] - Read 2048000/2097152
Read 2050048/2097152
Read 2052096/2097152
[16:42:58.561] - Read 2054144/2097152
Read 2056192/2097152
Read 2058240/2097152
[16:42:58.881] - Read 2060288/2097152
Read 2062336/2097152
Read 2064384/2097152
[16:42:59.200] - Read 2066432/2097152
Read 2068480/2097152
Read 2070528/2097152
[16:42:59.518] - Read 2072576/2097152
Read 2074624/2097152
Read 2076672/2097152
[16:42:59.837] - Read 2078720/2097152
Read 2080768/2097152
Read 2082816/2097152
[16:43:00.155] - Read 2084864/2097152
Read 2086912/2097152
Read 2088960/2097152
[16:43:00.474] - Read 2091008/2097152
Read 2093056/2097152
Read 2095104/2097152
[16:43:00.581] - Read 2097152/2097152
[16:43:00.582] - Flash read time cost(ms): 108947.57373046875
[16:43:00.583] - Finished
[16:43:00.585] - All time cost(ms): 112118.49609375
[16:43:00.701] - close interface
[16:43:00.701] - [All Success]
[16:44:45.474] - Save as efuse.bin
[16:44:45.475] - Version: eflash_loader_v2.5.1
[16:44:45.476] - Program Start
[16:44:45.476] - ========= eflash loader cmd arguments =========
[16:44:45.476] - Config file: W:\GIT\FlashTools\BouffaloLabs\BouffaloLabDevCube-v1.9.0\chips\bl602\eflash_loader\eflash_loader_cfg.ini
[16:44:45.477] - serial port is COM4
[16:44:45.477] - cpu_reset=False
[16:44:45.478] - chiptype: bl602
[16:44:45.478] - ========= Interface is uart =========
[16:44:45.478] - com speed: 2000000
[16:44:45.478] - Eflash load helper file: W:\GIT\FlashTools\BouffaloLabs\BouffaloLabDevCube-v1.9.0\chips\bl602\eflash_loader/eflash_loader_40m.bin
[16:44:45.478] - ========= load eflash_loader.bin =========
[16:44:45.478] - Load eflash_loader.bin via uart
[16:44:45.479] - ========= image load =========
[16:44:45.695] - Not ack OK
[16:44:45.696] - FL
[16:44:45.696] - result: FL
[16:44:45.973] - tx rx and power off, press the machine!
[16:44:45.974] - cutoff time is 0.1
[16:44:46.082] - power on tx and rx
[16:44:46.898] - reset cnt: 0, reset hold: 0.005, shake hand delay: 0.1
[16:44:46.899] - clean buf
[16:44:46.900] - send sync
[16:44:47.132] - ack is 4f4b
[16:44:47.177] - shake hand success
[16:44:47.193] - get_boot_info
[16:44:47.196] - data read is b'ffffffff00000000030004002127eaedbb281700'
[16:44:47.196] - ========= chipid: 28bbedea2721 =========
[16:44:47.197] - last boot info: None
[16:44:47.198] - eflash loader present
[16:44:47.198] - Error: Image load fail
[16:44:47.198] - shakehand with eflash loader found
[16:44:47.198] - Load helper bin time cost(ms): 1718.669189453125
[16:44:47.198] - ErrorCode: 0003, ErrorMsg: BFLB LOAD HELP BIN FAIL
[16:44:47.199] - Burn Retry
[16:44:47.199] - 0
[16:44:47.199] - Burn return with retry fail
[16:44:53.939] - Save as efuse.bin
[16:44:53.940] - Version: eflash_loader_v2.5.1
[16:44:53.940] - Program Start
[16:44:53.941] - ========= eflash loader cmd arguments =========
[16:44:53.942] - Config file: W:\GIT\FlashTools\BouffaloLabs\BouffaloLabDevCube-v1.9.0\chips\bl602\eflash_loader\eflash_loader_cfg.ini
[16:44:53.943] - serial port is COM4
[16:44:53.943] - cpu_reset=False
[16:44:53.943] - chiptype: bl602
[16:44:53.946] - ========= Interface is uart =========
[16:44:53.946] - com speed: 2000000
[16:44:53.947] - Eflash load helper file: W:\GIT\FlashTools\BouffaloLabs\BouffaloLabDevCube-v1.9.0\chips\bl602\eflash_loader/eflash_loader_40m.bin
[16:44:53.947] - ========= load eflash_loader.bin =========
[16:44:53.947] - Load eflash_loader.bin via uart
[16:44:53.947] - ========= image load =========
[16:44:54.177] - Not ack OK
[16:44:54.177] - FL
[16:44:54.178] - result: FL
[16:44:54.461] - tx rx and power off, press the machine!
[16:44:54.462] - cutoff time is 0.1
[16:44:54.572] - power on tx and rx
[16:44:55.391] - reset cnt: 0, reset hold: 0.005, shake hand delay: 0.1
[16:44:55.391] - clean buf
[16:44:55.394] - send sync
[16:44:55.622] - ack is 4f4b
[16:44:55.669] - shake hand success
[16:44:55.684] - get_boot_info
[16:44:55.687] - data read is b'0100000000000000030004002127eaedbb281700'
[16:44:55.688] - ========= chipid: 28bbedea2721 =========
[16:44:55.688] - last boot info: None
[16:44:55.688] - sign is 0 encrypt is 0
[16:44:55.689] - segcnt is 1
[16:44:55.697] - segdata_len is 38592
[16:44:55.782] - 4080/38592
[16:44:55.867] - 8160/38592
[16:44:55.952] - 12240/38592
[16:44:56.037] - 16320/38592
[16:44:56.122] - 20400/38592
[16:44:56.207] - 24480/38592
[16:44:56.292] - 28560/38592
[16:44:56.377] - 32640/38592
[16:44:56.461] - 36720/38592
[16:44:56.501] - 38592/38592
[16:44:56.504] - Run img
[16:44:56.613] - Load helper bin time cost(ms): 2666.262939453125
[16:44:56.722] - Flash load shake hand
[16:44:56.733] - default set DTR high
[16:44:56.846] - clean buf
[16:44:56.848] - send sync
[16:44:57.080] - ack is 4f4b
[16:44:57.127] - Read mac addr
[16:44:57.128] - macaddr: 2127eaedbb28
[16:44:57.129] - Read operation
[16:44:57.132] - Read efuse
[16:44:57.133] - Finished
[16:44:57.134] - All time cost(ms): 3194.5458984375
[16:44:57.248] - close interface
[16:44:57.249] - [All Success]

Flash read - Bouffalo Lab DevCube v1.4.8
This version also seem to work good - no extra commentary is required here.

Both BlDevCubes work good for me.
Flash write - Bouffalo Lab DevCube v1.4.8
We already have some guides for firmware write process, so you can check them out first:
Still, the process is very similar to flash read, just use different flash section and select the Partition Table and Boot2 bin and Firmware Bin as we've shown on our screenshot:

Remember to get our binary from Releases:
https://github.com/openshwprojects/OpenBK7231T_App
It should flash and create OBK access point as soon as you disconnect BOOT from resistor and do power off/on cycle:

But that's not the scope of this topic, so I'll finish here.
Summary
This way you can backup and restore flash of BL602/BL702 device or similar. Make sure to use 10k resistor while pulling BOOT pin high. Don't forget to do power off/on cycle (or reset via reset pin...) between each flash operation, just like you'd do with ESP8266.
If you manage to read some flash of device that has not been yet paired with Tuya, consider flashing it with us:
https://github.com/openshwprojects/FlashDumps
That's all for now, let us know if you have managed to flash any BL devices, we can also help you with flashing process and guide you step by step if you want. Let's run our devices without the cloud!
PS: Flashing OBK to 1MB version of BL602 requires some different configuration, we will cover it in another topic
Comments
that's cool. I hadn't considered dumping the efuse on BL. I hadn't seen a BW2L module before either. Seems like it's pin-compatible with at least: TYWE2L, CB2L, DT-BL200, TYWE2L, WB2L, WBR2L, WR2L,... [Read more]
I still didn't figure out the remaining pinout of the BW2L module, but maybe it's the same as in DT-BL200? [Read more]
Maybe. Did you trace each pin in the end? Look what came today https://obrazki.elektroda.pl/1437538300_1741352085_thumb.jpg [Read more]
Are you able to flash it? I may be posting flashing guide for this device soon, so if you manage to flash it on time, you could also add your experience there. And I still haven't figured out which... [Read more]
I have not done anything to it yet, I will note my experiences, with pics, when the time comes. Added after 6 [minutes]: I was about to say surely the assignments are mentioned in the updated, verbose... [Read more]
It seems that I got the same bulb as you. So now I have E14 with BW2L and E27 with BW2L. https://github.com/openshwprojects/FlashDumps/commit/e44fbdfe8a41e4c0fdee07cb1c6a98e4eb5e290d [Read more]
cool. they both seem to be v1.1.1 and then offer update to v1.5.0 eWeLink-C3009-EW-E14-BWL2-bulb_(FWLED-CK0205PWM-LIGHT-BL602L_v1.5.0).bin was added to dumps to sit alongside your original E14 [Read more]
Have you added all your BW2L dumps? Btw, did you know that C3009 marking is present on all three bulbs I have - two BW2L based from eWeLink and the Tuya one as well? https://obrazki.elektroda.pl/2887217500_1741636866_thumb.jpg... [Read more]
yes. these two anyway. 1.5.0 not done yet. I guess our EW-A60-15Ws will be the same. eWeLink-C3009-EW-E27-BW2L-RGBCW-EW-A60-15W_(FWLED-CK0205PWM-LIGHT-BL602L_v1.1.1)_divadiow.bin eWeLink-C3009-EW-E27-BW2L-RGBCW-EW-A60-15W_(FWLED-CK0205PWM-LIGHT-BL602L_v1.1.1)_efuse_divadiow.bin... [Read more]
I've copied my OBK template from E14 version to E27 and it works just fine, so PWM roles are 100% the same. Still, it would be nice to find out where GPIOs are stored for BL602 eWeLink devices. [Read more]
Ah. makes sense. of course there doesn't have to be anything device-specific if theyre wired the same way. Config extraction from eWeLink would be nice... [Read more]
It has some string references like cw_power... https://obrazki.elektroda.pl/3304701200_1741642310_thumb.jpg Have you tried to load this binary in Ghidra or any other tool like that? Added after... [Read more]
Interesting. I'm also wondering if we can use what looks like the pin assignments in some BL602 boot logs as a reference point. eg https://www.elektroda.com/rtvforum/viewtopic.php?p=20987133#20987133 ... [Read more]
I'm able to find those strings in Ghidra, but when I search for code referencing them, it finds nothing. There is something wrong with the way I import BL602 dump. [Read more]