diff --git a/README.md b/README.md
index 8ef4c0f..63e33f8 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,56 @@
-efm8load.py
-===
+# efm8load.py
-A python-only implementation of the efm8 bootloader protocol
+A python-only implementation of the efm8 bootloader protocol.
+Check out http://fishpepper.de/2016/10/15/efm8-bootloader-flash-tool-efm8load-py/ for more info.
-see http://fishpepper.de/2016/10/15/efm8-bootloader-flash-tool-efm8load-py/ for more info
-Status:
-- tested on EFM8BB10F8G: identify, write, verify and read are working
+## Status
+| Microcontroller Unit (MCU) | Identify | Read | Write |
+| - | - | - | - |
+| EFM8BB10F8G | 🟢 | 🟢 | 🟢 |
+| EFM8BB52F32G | 🟢 | 🟢 | 🟡 |
-Usage:
-- connect rs232 (3.3V level!) to the RX and TX pins of your MCU
-- empty targets boot right into the bootloader (flash[0] = 0xFF -> bootloader)
-- flashed targets need the C2D pin pulled low during powerup to enter bootloader mode
+🟢 = Working,
+🟡 = Not tested,
+🔴 = Not working
-TODO:
-add a protection to stop users from overwriting the bootloader area
+
+## Info
+- Connect the MCU to the rs232:
+ * MCU RXD to TXD
+ * MCU TXD to RXD
+ * MCU 3v3 to 3v3 **or** MCU 5v to 5v **(⚠️Do not mix 5v with 3v3! Check the datasheet for VVDD and `Voltage on VDD supply pin`⚠️)**
+ * MCU GND to GND
+ * MCU C2D to GND
+- Empty targets boot right into the bootloader (flash[0] = 0xFF -> bootloader)
+
+
+## Requirements
+- python3 + pip
+- USB to UART Bridge Controller (e.g. CP2102)
+- CP210x USB to UART Bridge VCP Drivers
+- C2D Pin **must** be pulled low (connected to GND) during powerup to enter the bootload mode (Review section `5.3.1 Entering Bootload Mode` [documents/an945-efm8-factory-bootloader-user-guide.pdf](documents/an945-efm8-factory-bootloader-user-guide.pdf) for the right Pin numbers)
+
+
+## Setup
+```bash
+# Install the necessary packages
+pip install -r requirements.txt
+```
+
+## Usage
+```bash
+# Identify the chip
+python efm8load.py -p -i
+
+# Dump the flash memory to file
+python efm8load.py -p -r dumped_flash.hex
+
+# ⚠️Upload/Write file to flash memory⚠️
+python efm8load.py -p -w dumped_flash.hex
+```
+
+
+## TODO
+- Add a protection to stop users from overwriting the bootloader area
+- Information about decompiling the dumped flash memory
diff --git a/documents/an945-efm8-factory-bootloader-user-guide.pdf b/documents/an945-efm8-factory-bootloader-user-guide.pdf
new file mode 100644
index 0000000..f5ee639
Binary files /dev/null and b/documents/an945-efm8-factory-bootloader-user-guide.pdf differ
diff --git a/dumps/.gitignore b/dumps/.gitignore
new file mode 100644
index 0000000..c96a04f
--- /dev/null
+++ b/dumps/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
\ No newline at end of file
diff --git a/efm8load.py b/efm8load.py
index 3efbd9d..3bda760 100755
--- a/efm8load.py
+++ b/efm8load.py
@@ -21,13 +21,12 @@
import crcmod
import serial
+from tqdm import tqdm
+from collections import Counter
from intelhex import IntelHex
-
-# make sure to install the python3 modules for serial, crcmod, and pip3:
+# make sure to install the python modules for pyserial, tqdm, crcmod, intelhex:
# sudo apt intstall python3-crcmod python3-serial python3-pip
-# if you are missing the intelhex package, you can install it afterwars by
-# pip3 install intelhex --user
class COMMAND:
IDENTIFY = 0x30
@@ -81,6 +80,9 @@ class EFM8Loader:
}],
0x34 : ["EFM8BB3", {
0x01: ["EFM8BB31F64G-QFN32" , 64*1024, 512, 512],
+ }],
+ 0x39 : ["EFM8BB5", {
+ 0x08: ["EFM8BB52F32G-QFN32" , 15*2048, 2048, 2048],
}]
}
@@ -271,30 +273,41 @@ def download(self, filename):
#the bootloader protocol does not allow reading flash
#however it allows to verify written bytes
#we will exploit this feature to dump the flash contents
- #for now assume 8kb flash
- flash_size = 8 * 1024
+
ih = IntelHex()
- for address in range(flash_size):
- #test one byte by byte
- #first check 0x00
- byte = 0
- if (self.verify(address, [byte]) == RESPONSE.ACK):
- ih[address] = byte
- else:
- #now start with 0xFF (empty flash)
- for byte in range(0xFF, -1, -1):
- if (self.verify(address, [byte]) == RESPONSE.ACK):
- #success, the flash content on this address euals
- ih[address] = byte
- break
- print("\r> flash[0x%04X] = 0x%02X" % (address, byte), end="")
- sys.stdout.flush()
- print("\n> finished")
+ # generate list with all possible hex adress values
+ byte_list = Counter()
+ for byte in range(0xFF, -1, -1):
+ byte_list[byte] += 1
+
+
+ for address in tqdm(
+ range(self.flash_size),
+ desc="Dumping Flash",
+ unit=" Bytes",
+ ascii=" #",
+ smoothing=0.01,
+ dynamic_ncols=True,
+ unit_scale=True,
+ ):
+ sorted_byte_list = byte_list.most_common()
+ for curr_byte in sorted_byte_list:
+ byte=curr_byte[0]
+ if (self.verify(address, [byte]) == RESPONSE.ACK):
+ #success, the flash content on this address equals
+ ih[address] = byte
+ byte_list[byte] += 1
+ break
+ #print(" flash[0x%04X] = 0x%02X" % (address, byte))
+ print("\n> finished dumping")
- #done, all flash contents have been read, now store this to the file
- ih.write_hex_file(filename)
+ #done, all flash contents have been read, now store this to the files
+ ih.tofile("dumps/" + filename, format='hex')
+ ih.tofile("dumps/" + filename + ".bin", format='bin')
+ print("\n> dump written to disk successfully")
+ print("\n> done")
def upload(self, filename):
print("> uploading file '%s'" % (filename))
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..dc2fdea
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,4 @@
+crcmod==1.7
+intelhex==2.3.0
+pyserial==3.5
+tqdm==4.66.4