mirror of
https://github.com/OpenEPaperLink/OpenEPaperLink.git
synced 2026-03-21 12:05:51 +01:00
Merge pull request #265 from kquinsland/feat/add-nrf-mac-patcher-scrip
Feat/add nrf mac patcher scrip
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
# Tag Flasher
|
||||
|
||||
You can use the following flasher-scripts to program various types of tags with the Tag-Flasher or AP-Flasher. The Tag-Flasher is the easiest to build; it uses only a Wemos S2-Mini or clone to program quite a few different tags. The tags below are the tags that can be programmed with this flasher.
|
||||
|
||||
* ZBS243-based tags
|
||||
* nRF52-based tags
|
||||
* 88MZ100-based tags
|
||||
|
||||
This is the schematic for the flasher, including a pinout for the debug-header that is used by quite a few Solum tags. This flasher is also compatible with the OEPL-AP-Flasher jig/programming boards.
|
||||
This is the schematic for the flasher, including a pinout for the debug-header that is used by quite a few Solum tags. This flasher is also compatible with the OEPL-AP-Flasher jig/programming boards.
|
||||

|
||||
|
||||
This is what it looks like with the wires connected. I've chosen to use 0.635mm pitch wires, to be able to use the jigs with the 1.27mm FDC connectors. After soldering, you can add a little bit of hot-glue to make sure they stay attached.
|
||||
@@ -17,29 +18,31 @@ This is what it looks like with the wires connected. I've chosen to use 0.635mm
|
||||
* R - required
|
||||
* O - optional
|
||||
|
||||
Flasher Pin | Cable Pin | ESP32-S2 Pin | ZBS | nRF | 88mz100
|
||||
:-------------------------:|:------:|:-----------------------:|:----:|:------:|:---:
|
||||
VCC | 1 | 16, 17, 18, 21 | R | R | R
|
||||
CS | 2 | 34 | R | |
|
||||
GND | 3 | GND | R | R | R
|
||||
CLK | 4 | 33 | R | R |
|
||||
TXD | 5 | 36 | O | O | R
|
||||
MISO | 6 | 35 | R | R |
|
||||
TEST | 7 | 38 |
|
||||
MOSI | 8 | 37 | R |
|
||||
RXD | 9 | 40 | O | O | R
|
||||
RSET | 10 | 39 | R | | O
|
||||
| Flasher Pin | Cable Pin | ESP32-S2 Pin | ZBS | nRF | 88mz100 |
|
||||
| :---------: | :-------: | :------------: | :---: | :---: | :-----: |
|
||||
| VCC | 1 | 16, 17, 18, 21 | R | R | R |
|
||||
| CS | 2 | 34 | R | | |
|
||||
| GND | 3 | GND | R | R | R |
|
||||
| CLK | 4 | 33 | R | R | |
|
||||
| TXD | 5 | 36 | O | O | R |
|
||||
| MISO | 6 | 35 | R | R | |
|
||||
| TEST | 7 | 38 | | | |
|
||||
| MOSI | 8 | 37 | R | | |
|
||||
| RXD | 9 | 40 | O | O | R |
|
||||
| RSET | 10 | 39 | R | | O |
|
||||
|
||||
Not all connections are required by all tags! If you want to solder fewer wires, skip the optional and unused ones.
|
||||
|
||||
## Flashing the flasher
|
||||
|
||||
Clone the [Tag_Flasher repo](https://github.com/jjwbruijn/OpenEPaperLink/tree/master/Tag_Flasher/ESP32_Flasher) and open into PlatformIO. Choose the correct COM-port and hit 'Upload'.
|
||||
Also, the precompiled binaries are part of any [release](https://github.com/jjwbruijn/OpenEPaperLink/releases), and to make it even easier, you can use the web flasher on https://install.openepaperlink.de to even flash it without installing any extra software.
|
||||
Also, the precompiled binaries are part of any [release](https://github.com/jjwbruijn/OpenEPaperLink/releases), and to make it even easier, you can use the web flasher on [https://install.openepaperlink.de](https://install.openepaperlink.de) to even flash it without installing any extra software.
|
||||
|
||||
## OEPL-Flasher.py
|
||||
|
||||
This script connects to the S2-mini's serial port and enables flashing to ZBS243 and nRF52811-based tags.
|
||||
```
|
||||
|
||||
```shell
|
||||
usage: OEPL-Flasher.py [-h] [-p PORT] [-f] [-i] [-n] [-z] [--internalap] [-e] [--altradio] [--pt] {read,write,autoflash,debug} [filename]
|
||||
|
||||
OpenEPaperLink Flasher for AP/Flasher board
|
||||
@@ -63,34 +66,44 @@ options:
|
||||
```
|
||||
|
||||
## 88MZ100-OEPL/Serial-Flasher.py
|
||||
|
||||
This script connects through a serial-TTL interface or OEPL - Tag_Flasher or AP-Flasher.
|
||||
|
||||
```
|
||||
```shell
|
||||
Example: COM1 read file.bin, or COM1 write file.bin, or COM1 write_flash file.bin
|
||||
To create an OTA file use: img file.bin
|
||||
```
|
||||
|
||||
## Solum ZBS243-based
|
||||
|
||||
Use with the -z option for ZBS243. Autoflash is currently not implemented on the Tag_Flasher/S2 version.
|
||||
```
|
||||
|
||||
```shell
|
||||
python3 OEPL-Flasher.py -e -z -p COM31 read blaat.bin --flash --pt
|
||||
```
|
||||
|
||||
## Nordic nRF-based
|
||||
|
||||
Use with the -n option for nRF52811
|
||||
```
|
||||
|
||||
```shell
|
||||
python3 OEPL-Flasher.py -e -n -p COM31 read blaat.bin --flash --pt
|
||||
```
|
||||
|
||||
**Note:** If something's gone wrong with the UICR partition on your nRF tag, you can use the [`nrf_uicr_mac_patcher.py`](nrf_uicr_mac_patcher.py) tool to patch a known good UICR partition dump with the MAC address of your broken tag.
|
||||
|
||||
## Marvell 88MZ100-based
|
||||
|
||||
Main article [here](https://github.com/jjwbruijn/OpenEPaperLink/wiki/88MZ100-Programming-and-interfacing).
|
||||
|
||||
The Tag-Flasher is used in serial passthrough-mode in order to flash the 88MZ100 with a modified flasher-script. A serial DTR/Reset line is used to reset the tag during the connection stage; this is however not strictly necessary! If you connect or reset the tag when prompted by the script, the flasher will work fine.
|
||||
```
|
||||
|
||||
```shell
|
||||
python3 .\88MZ100-OEPL-Flasher.py COM31 write_flash '0130c8144117.bin'
|
||||
```
|
||||
|
||||
## Credits
|
||||
|
||||
Much code was reused from ATC1441's various flashers
|
||||
* [ATC1441's ESP32-NRF52-SWD](https://github.com/atc1441/ESP32_nRF52_SWD)
|
||||
* [ATC1441's ZBS-Flasher](https://github.com/atc1441/ZBS_Flasher)
|
||||
|
||||
108
Tag_Flasher/nrf_uicr_mac_patcher.py
Normal file
108
Tag_Flasher/nrf_uicr_mac_patcher.py
Normal file
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
##
|
||||
# It's not 2002 anymore and we have wide screens.
|
||||
# pylint: disable=C0301
|
||||
"""
|
||||
This is a very simple script to read / patch the MAC address in uicr partition dump from a nrf based tag.
|
||||
The script was built for / tested against solum newton M3/2.9 inch tags but should be easy to adapt to other tags.
|
||||
|
||||
What the uicr partition contains has been reverse engineered and details are here:
|
||||
https://github.com/jjwbruijn/OpenEPaperLink/blob/master/ARM_Tag_FW/Newton_M3_nRF52811/hal/Newton_M3_nRF52811/tagtype_db.cpp
|
||||
|
||||
|
||||
If you have a tag with mac: 00:00:7E:7E:79:1F:B1:93, then only the bytes (1F 79 7E 7E) will be present in the uicr partition dump.
|
||||
This is because the first two bytes (00:00) are padding / not currently used and the last two octets are a checksum.
|
||||
The checksum is calculated by the tag firmware and is not relevant to us.
|
||||
|
||||
If you're curious, the checksum calc is here:
|
||||
https://github.com/jjwbruijn/OpenEPaperLink/blob/d2c2963b3b5b24346bff0d7966eeac28cf888377/ARM_Tag_FW/Newton_M3_nRF52811/hal/Newton_M3_nRF52811/HAL_Newton_M3.cpp#L140
|
||||
|
||||
Starting at offset 0x80, you should see this in your dump file:
|
||||
|
||||
0000:0080 | 1F 79 7E 7E
|
||||
|
||||
So, we're really only interested in patching 4 bytes from 0x80 through 0x84.
|
||||
Note that the order of the bytes is reversed in the uicr partition dump.
|
||||
|
||||
This script is meant to be used with the `OEPL-Flasher.py` tool to pull a known good uicr partition
|
||||
and to flash back a modified uicr partition dump to the tag.
|
||||
|
||||
## Usage
|
||||
|
||||
# Read a known good tag
|
||||
❯ python3 OEPL-Flasher.py -e -n --passthrough -p /dev/ttyACM0 -i read working_infopage.bin
|
||||
|
||||
# Confirm that the dump has the MAC you expect
|
||||
❯ python3 nrf_uicr_mac_patcher.py working_infopage.bin
|
||||
MAC Address: 00:00:7E:7E:79:1F:00:00
|
||||
|
||||
# Create a copy of the known good dump and patch it with the new MAC
|
||||
❯ python3 nrf_uicr_mac_patcher.py working_infopage.bin 7e:7e:4c:9b recovery1.bin
|
||||
Patching working_infopage.bin with new MAC address 7e:7e:4c:9b
|
||||
File patched and saved to recovery1.bin
|
||||
|
||||
# Check your work ;)
|
||||
❯ python3 nrf_uicr_mac_patcher.py recovery1.bin
|
||||
MAC Address: 00:00:7E:7E:4C:9B:00:00
|
||||
|
||||
# Write the modified uicr partition dump to the tag and then flash the tag with the new firmware
|
||||
❯ py OEPL-Flasher.py -e -n --passthrough -p /dev/ttyACM0 -i write recovery6.bin
|
||||
❯ py OEPL-Flasher.py -e -n --passthrough -p /dev/ttyACM0 --flash write ../binaries/Tag/SOL_M3_Uni_full_0027.bin
|
||||
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
def read_mac_from_file(filepath: str) -> None:
|
||||
"""Reads the MAC address from a file
|
||||
|
||||
Args:
|
||||
filepath (str): Path to bin file
|
||||
"""
|
||||
with open(filepath, "rb") as file:
|
||||
|
||||
# Seek to offset 0x80, read 4 bytes
|
||||
file.seek(0x80)
|
||||
mac_bytes = file.read(4)
|
||||
# Reverse the bytes
|
||||
mac_bytes = mac_bytes[::-1]
|
||||
# two left most bytes are 0x00, and the two right most bytes are a checksum that's
|
||||
# calculated by the tag firmware.
|
||||
mac = [0, 0] + list(mac_bytes) + [0, 0]
|
||||
mac_str = ":".join(f"{byte:02X}" for byte in mac)
|
||||
print("MAC Address:", mac_str)
|
||||
|
||||
|
||||
def patch_file(input_path: str, new_mac_str: str, output_path: str) -> None:
|
||||
"""Patch file
|
||||
|
||||
Args:
|
||||
input_path (str): Path to input file; this should be a known good uicr partition dump
|
||||
new_mac_str (str): colon delineated string containing the 4 bytes of new MAC address
|
||||
output_path (str): Path to the output file
|
||||
"""
|
||||
print(f"Patching {input_path} with new MAC address {new_mac_str}")
|
||||
new_mac = [int(x, 16) for x in new_mac_str.split(":")[0:4]]
|
||||
|
||||
with open(input_path, "rb") as file:
|
||||
data = bytearray(file.read())
|
||||
|
||||
# Update MAC address bytes, write them in reverse order
|
||||
new_mac = new_mac[::-1]
|
||||
data[0x80:0x84] = new_mac[0:4]
|
||||
|
||||
with open(output_path, "wb") as file:
|
||||
file.write(data)
|
||||
print(f"File patched and saved to {output_path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) == 2:
|
||||
read_mac_from_file(sys.argv[1])
|
||||
elif len(sys.argv) == 4:
|
||||
patch_file(sys.argv[1], sys.argv[2], sys.argv[3])
|
||||
else:
|
||||
print(f"Usage: {sys.argv[0]} <file_path> [new_mac] [output_file_path]")
|
||||
@@ -50,4 +50,3 @@ def main():
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user