nrflash 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nrflash/__init__.py +6 -0
- nrflash/__main__.py +4 -0
- nrflash/cdc_reset.py +96 -0
- nrflash/cli.py +759 -0
- nrflash/rom_loader.py +469 -0
- nrflash/stub_flasher_data.py +1860 -0
- nrflash/uart_reset.py +76 -0
- nrflash/usb_device.py +762 -0
- nrflash-1.0.0.dist-info/METADATA +251 -0
- nrflash-1.0.0.dist-info/RECORD +16 -0
- nrflash-1.0.0.dist-info/WHEEL +5 -0
- nrflash-1.0.0.dist-info/entry_points.txt +2 -0
- nrflash-1.0.0.dist-info/licenses/LICENSE-APACHE +201 -0
- nrflash-1.0.0.dist-info/licenses/STUB_LICENSE-APACHE +201 -0
- nrflash-1.0.0.dist-info/licenses/STUB_LICENSE-MIT +21 -0
- nrflash-1.0.0.dist-info/top_level.txt +1 -0
nrflash/__init__.py
ADDED
nrflash/__main__.py
ADDED
nrflash/cdc_reset.py
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""
|
|
2
|
+
cdc_reset.py - Put a native-USB-CDC ESP32 (S2 / S3 / C3) into the ROM
|
|
3
|
+
download bootloader, and reset it back to running firmware afterward.
|
|
4
|
+
|
|
5
|
+
usb_device.py's init_uart_bridge() already solves this for *external*
|
|
6
|
+
UART bridge chips (CP2102/CH340/FTDI) by toggling DTR/RTS, which are real
|
|
7
|
+
GPIO-wired reset/boot lines on those boards. Native USB CDC boards
|
|
8
|
+
(303A:1001 / 303A:0002) have no such bridge chip and no real DTR/RTS
|
|
9
|
+
hardware — Espressif's USB-CDC-ACM stack on these chips instead exposes a
|
|
10
|
+
*software* convention over CDC "SET_LINE_CODING" / control transfers:
|
|
11
|
+
|
|
12
|
+
- Standard CDC has no boot-strap pins, so Espressif's `esptool.py`
|
|
13
|
+
triggers entry into the ROM bootloader two different ways depending
|
|
14
|
+
on board age/firmware:
|
|
15
|
+
|
|
16
|
+
1. "USB-JTAG/serial" reset hack: send a CDC `SET_CONTROL_LINE_STATE`
|
|
17
|
+
class request with specific DTR/RTS *bit patterns* — the chip's
|
|
18
|
+
internal USB-Serial-JTAG peripheral watches these bits in
|
|
19
|
+
hardware and maps them to EN/BOOT internally, the same logic
|
|
20
|
+
CP2102/CH340 boards do externally with real wires.
|
|
21
|
+
|
|
22
|
+
2. If that doesn't trigger it (older bootloader ROMs, or the
|
|
23
|
+
sketch never enabled the watch), we fall back to asking the
|
|
24
|
+
*currently running sketch* to reboot into bootloader via the
|
|
25
|
+
well-known "0xAD 0xDE" magic isn't relevant here -- that's
|
|
26
|
+
NRcap32's own app protocol, not a chip-level reset path, so we
|
|
27
|
+
do NOT depend on the firmware cooperating. Native USB CDC entry
|
|
28
|
+
must work even when the flash is blank/corrupt.
|
|
29
|
+
|
|
30
|
+
This module only implements path (1), which is what every ESP32-S3/C3/S2
|
|
31
|
+
dev board with native USB (including bare modules wired per Espressif's
|
|
32
|
+
reference) supports at the silicon level — it's part of the USB-Serial-JTAG
|
|
33
|
+
peripheral, not the user sketch.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
import time
|
|
37
|
+
|
|
38
|
+
# bmRequestType for CDC class-specific request, host->device
|
|
39
|
+
_CDC_REQTYPE = 0x21
|
|
40
|
+
_SET_CONTROL_LINE_STATE = 0x22
|
|
41
|
+
|
|
42
|
+
# DTR/RTS bit positions inside wValue of SET_CONTROL_LINE_STATE
|
|
43
|
+
_DTR = 0x01
|
|
44
|
+
_RTS = 0x02
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _set_line_state(device, dtr: bool, rts: bool):
|
|
48
|
+
value = (_DTR if dtr else 0) | (_RTS if rts else 0)
|
|
49
|
+
# wIndex is the CDC control interface number; native ESP32 USB CDC
|
|
50
|
+
# always exposes it as interface 0 (data class lives on interface 1,
|
|
51
|
+
# matched by get_cdc_endpoints()'s native-CDC branch).
|
|
52
|
+
device.ctrl_transfer(_CDC_REQTYPE, _SET_CONTROL_LINE_STATE, value, 0, None)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def enter_bootloader(device, settle: float = 0.3):
|
|
56
|
+
"""
|
|
57
|
+
Drive the native USB-CDC reset-into-bootloader sequence.
|
|
58
|
+
|
|
59
|
+
Sequence (matches the espressif esptool 'usb_jtag_serial' reset
|
|
60
|
+
strategy, re-derived from the public USB-Serial-JTAG peripheral
|
|
61
|
+
behavior, no esptool code reused):
|
|
62
|
+
|
|
63
|
+
1. DTR=1, RTS=0 -> internal EN released (chip held in reset briefly)
|
|
64
|
+
2. DTR=0, RTS=1 -> internal BOOT pulled low, EN toggled -> reset
|
|
65
|
+
into bootloader because BOOT is sampled low
|
|
66
|
+
3. DTR=0, RTS=0 -> release lines, let ROM bootloader start cleanly
|
|
67
|
+
|
|
68
|
+
Some boards need this whole sequence sent twice back-to-back because
|
|
69
|
+
the very first control transfer after USB enumeration can be eaten by
|
|
70
|
+
the host controller settling — harmless to repeat, the chip is already
|
|
71
|
+
held in reset for the duration.
|
|
72
|
+
"""
|
|
73
|
+
for _ in range(2):
|
|
74
|
+
_set_line_state(device, dtr=True, rts=False)
|
|
75
|
+
time.sleep(0.05)
|
|
76
|
+
_set_line_state(device, dtr=False, rts=True)
|
|
77
|
+
time.sleep(0.05)
|
|
78
|
+
_set_line_state(device, dtr=False, rts=False)
|
|
79
|
+
time.sleep(0.05)
|
|
80
|
+
time.sleep(settle)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def reset_to_app(device, settle: float = 0.5):
|
|
84
|
+
"""
|
|
85
|
+
Reset the chip back out of the bootloader into the normal app
|
|
86
|
+
(whatever was just flashed, or the existing firmware if the user
|
|
87
|
+
only wanted to probe/verify).
|
|
88
|
+
|
|
89
|
+
1. DTR=1, RTS=1 -> EN pulled low -> reset asserted
|
|
90
|
+
2. DTR=0, RTS=0 -> EN released, BOOT high (not sampled)
|
|
91
|
+
-> boots the flashed application, not the ROM loader
|
|
92
|
+
"""
|
|
93
|
+
_set_line_state(device, dtr=True, rts=True)
|
|
94
|
+
time.sleep(0.1)
|
|
95
|
+
_set_line_state(device, dtr=False, rts=False)
|
|
96
|
+
time.sleep(settle)
|