mpflash 1.0.1__py3-none-any.whl → 1.0.2__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.
- mpflash/add_firmware.py +98 -98
- mpflash/ask_input.py +236 -236
- mpflash/basicgit.py +284 -284
- mpflash/bootloader/__init__.py +2 -2
- mpflash/bootloader/activate.py +60 -60
- mpflash/bootloader/detect.py +82 -82
- mpflash/bootloader/manual.py +101 -101
- mpflash/bootloader/micropython.py +12 -12
- mpflash/bootloader/touch1200.py +36 -36
- mpflash/cli_download.py +129 -129
- mpflash/cli_flash.py +224 -216
- mpflash/cli_group.py +111 -111
- mpflash/cli_list.py +87 -87
- mpflash/cli_main.py +39 -39
- mpflash/common.py +210 -177
- mpflash/config.py +44 -44
- mpflash/connected.py +104 -77
- mpflash/download.py +364 -364
- mpflash/downloaded.py +130 -130
- mpflash/errors.py +9 -9
- mpflash/flash/__init__.py +55 -55
- mpflash/flash/esp.py +59 -59
- mpflash/flash/stm32.py +19 -19
- mpflash/flash/stm32_dfu.py +104 -104
- mpflash/flash/uf2/__init__.py +88 -88
- mpflash/flash/uf2/boardid.py +15 -15
- mpflash/flash/uf2/linux.py +136 -130
- mpflash/flash/uf2/macos.py +42 -42
- mpflash/flash/uf2/uf2disk.py +12 -12
- mpflash/flash/uf2/windows.py +43 -43
- mpflash/flash/worklist.py +170 -170
- mpflash/list.py +106 -106
- mpflash/logger.py +41 -41
- mpflash/mpboard_id/__init__.py +93 -93
- mpflash/mpboard_id/add_boards.py +251 -251
- mpflash/mpboard_id/board.py +37 -37
- mpflash/mpboard_id/board_id.py +86 -86
- mpflash/mpboard_id/store.py +43 -43
- mpflash/mpremoteboard/__init__.py +266 -266
- mpflash/mpremoteboard/mpy_fw_info.py +141 -141
- mpflash/mpremoteboard/runner.py +140 -140
- mpflash/vendor/click_aliases.py +91 -91
- mpflash/vendor/dfu.py +165 -165
- mpflash/vendor/pydfu.py +605 -605
- mpflash/vendor/readme.md +2 -2
- mpflash/versions.py +135 -135
- {mpflash-1.0.1.dist-info → mpflash-1.0.2.dist-info}/LICENSE +20 -20
- {mpflash-1.0.1.dist-info → mpflash-1.0.2.dist-info}/METADATA +1 -1
- mpflash-1.0.2.dist-info/RECORD +53 -0
- mpflash-1.0.1.dist-info/RECORD +0 -53
- {mpflash-1.0.1.dist-info → mpflash-1.0.2.dist-info}/WHEEL +0 -0
- {mpflash-1.0.1.dist-info → mpflash-1.0.2.dist-info}/entry_points.txt +0 -0
mpflash/downloaded.py
CHANGED
@@ -1,130 +1,130 @@
|
|
1
|
-
from pathlib import Path
|
2
|
-
from typing import Dict, List, Optional
|
3
|
-
|
4
|
-
import jsonlines
|
5
|
-
from loguru import logger as log
|
6
|
-
|
7
|
-
from mpflash.common import PORT_FWTYPES, FWInfo
|
8
|
-
from mpflash.versions import clean_version
|
9
|
-
|
10
|
-
from .config import config
|
11
|
-
|
12
|
-
|
13
|
-
# #########################################################################################################
|
14
|
-
def downloaded_firmwares(fw_folder: Path) -> List[FWInfo]:
|
15
|
-
"""Load a list of locally downloaded firmwares from the jsonl file"""
|
16
|
-
firmwares: List[FWInfo] = []
|
17
|
-
try:
|
18
|
-
with jsonlines.open(fw_folder / "firmware.jsonl") as reader:
|
19
|
-
firmwares = [FWInfo.from_dict(item) for item in reader]
|
20
|
-
except FileNotFoundError:
|
21
|
-
log.error(f"No firmware.jsonl found in {fw_folder}")
|
22
|
-
# sort by filename
|
23
|
-
firmwares.sort(key=lambda x: x.filename)
|
24
|
-
return firmwares
|
25
|
-
|
26
|
-
|
27
|
-
def clean_downloaded_firmwares(fw_folder: Path) -> None:
|
28
|
-
"""
|
29
|
-
Remove duplicate entries from the firmware.jsonl file, keeping the latest one
|
30
|
-
uniqueness is based on the filename
|
31
|
-
"""
|
32
|
-
firmwares = downloaded_firmwares(fw_folder)
|
33
|
-
if not firmwares:
|
34
|
-
return
|
35
|
-
# keep the latest entry
|
36
|
-
unique_fw = {fw.filename: fw for fw in firmwares}
|
37
|
-
with jsonlines.open(fw_folder / "firmware.jsonl", "w") as writer:
|
38
|
-
for fw in unique_fw.values():
|
39
|
-
writer.write(fw.to_dict())
|
40
|
-
log.info(f"Removed duplicate entries from firmware.jsonl in {fw_folder}")
|
41
|
-
|
42
|
-
|
43
|
-
def find_downloaded_firmware(
|
44
|
-
*,
|
45
|
-
board_id: str,
|
46
|
-
version: str = "", # v1.2.3
|
47
|
-
port: str = "",
|
48
|
-
variants: bool = False,
|
49
|
-
fw_folder: Optional[Path] = None,
|
50
|
-
trie: int = 1,
|
51
|
-
selector: Optional[Dict[str, str]] = None,
|
52
|
-
) -> List[FWInfo]:
|
53
|
-
if selector is None:
|
54
|
-
selector = {}
|
55
|
-
fw_folder = fw_folder or config.firmware_folder
|
56
|
-
# Use the information in firmwares.jsonl to find the firmware file
|
57
|
-
log.debug(f"{trie}] Looking for firmware for {board_id} {version} ")
|
58
|
-
fw_list = downloaded_firmwares(fw_folder)
|
59
|
-
if not fw_list:
|
60
|
-
log.error("No firmware files found. Please download the firmware first.")
|
61
|
-
return []
|
62
|
-
# filter by version
|
63
|
-
version = clean_version(version)
|
64
|
-
fw_list = filter_downloaded_fwlist(fw_list, board_id, version, port, variants, selector)
|
65
|
-
|
66
|
-
if not fw_list and trie < 3:
|
67
|
-
log.info(f"Try ({trie+1}) to find a firmware for the board {board_id}")
|
68
|
-
if trie == 1:
|
69
|
-
# ESP board naming conventions have changed by adding a PORT prefix
|
70
|
-
if port.startswith("esp") and not board_id.startswith(port.upper()):
|
71
|
-
board_id = f"{port.upper()}_{board_id}"
|
72
|
-
# RP2 board naming conventions have changed by adding a _RPI prefix
|
73
|
-
if port == "rp2" and not board_id.startswith("RPI_"):
|
74
|
-
board_id = f"RPI_{board_id}"
|
75
|
-
elif trie == 2:
|
76
|
-
board_id = board_id.replace("_", "-")
|
77
|
-
|
78
|
-
fw_list = find_downloaded_firmware(
|
79
|
-
fw_folder=fw_folder,
|
80
|
-
board_id=board_id,
|
81
|
-
version=version,
|
82
|
-
port=port,
|
83
|
-
trie=trie + 1,
|
84
|
-
selector=selector,
|
85
|
-
)
|
86
|
-
# hope we have a match now for the board
|
87
|
-
# sort by filename
|
88
|
-
fw_list.sort(key=lambda x: x.filename)
|
89
|
-
return fw_list
|
90
|
-
|
91
|
-
|
92
|
-
def filter_downloaded_fwlist(
|
93
|
-
fw_list: List[FWInfo],
|
94
|
-
board_id: str,
|
95
|
-
version: str, # v1.2.3
|
96
|
-
port: str,
|
97
|
-
# preview: bool,
|
98
|
-
variants: bool,
|
99
|
-
selector: dict,
|
100
|
-
) -> List[FWInfo]:
|
101
|
-
"""Filter the downloaded firmware list based on the provided parameters"""
|
102
|
-
if "preview" in version:
|
103
|
-
# never get a preview for an older version
|
104
|
-
fw_list = [fw for fw in fw_list if fw.preview]
|
105
|
-
else:
|
106
|
-
# older FWInfo version has no v1.2.3 prefix
|
107
|
-
either = [clean_version(version, drop_v=False), clean_version(version, drop_v=True)]
|
108
|
-
fw_list = [fw for fw in fw_list if fw.version in either]
|
109
|
-
log.trace(f"Filtering firmware for {version} : {len(fw_list)} found.")
|
110
|
-
# filter by port
|
111
|
-
if port:
|
112
|
-
fw_list = [fw for fw in fw_list if fw.port == port and Path(fw.firmware).suffix in PORT_FWTYPES[port]]
|
113
|
-
log.trace(f"Filtering firmware for {port} : {len(fw_list)} found.")
|
114
|
-
|
115
|
-
if board_id:
|
116
|
-
if variants:
|
117
|
-
# any variant of this board_id
|
118
|
-
fw_list = [fw for fw in fw_list if fw.board == board_id]
|
119
|
-
else:
|
120
|
-
# the firmware variant should match exactly the board_id
|
121
|
-
fw_list = [fw for fw in fw_list if fw.variant == board_id]
|
122
|
-
log.trace(f"Filtering firmware for {board_id} : {len(fw_list)} found.")
|
123
|
-
|
124
|
-
if selector and port in selector:
|
125
|
-
fw_list = [fw for fw in fw_list if fw.filename.endswith(selector[port])]
|
126
|
-
return fw_list
|
127
|
-
|
128
|
-
|
129
|
-
# #########################################################################################################
|
130
|
-
#
|
1
|
+
from pathlib import Path
|
2
|
+
from typing import Dict, List, Optional
|
3
|
+
|
4
|
+
import jsonlines
|
5
|
+
from loguru import logger as log
|
6
|
+
|
7
|
+
from mpflash.common import PORT_FWTYPES, FWInfo
|
8
|
+
from mpflash.versions import clean_version
|
9
|
+
|
10
|
+
from .config import config
|
11
|
+
|
12
|
+
|
13
|
+
# #########################################################################################################
|
14
|
+
def downloaded_firmwares(fw_folder: Path) -> List[FWInfo]:
|
15
|
+
"""Load a list of locally downloaded firmwares from the jsonl file"""
|
16
|
+
firmwares: List[FWInfo] = []
|
17
|
+
try:
|
18
|
+
with jsonlines.open(fw_folder / "firmware.jsonl") as reader:
|
19
|
+
firmwares = [FWInfo.from_dict(item) for item in reader]
|
20
|
+
except FileNotFoundError:
|
21
|
+
log.error(f"No firmware.jsonl found in {fw_folder}")
|
22
|
+
# sort by filename
|
23
|
+
firmwares.sort(key=lambda x: x.filename)
|
24
|
+
return firmwares
|
25
|
+
|
26
|
+
|
27
|
+
def clean_downloaded_firmwares(fw_folder: Path) -> None:
|
28
|
+
"""
|
29
|
+
Remove duplicate entries from the firmware.jsonl file, keeping the latest one
|
30
|
+
uniqueness is based on the filename
|
31
|
+
"""
|
32
|
+
firmwares = downloaded_firmwares(fw_folder)
|
33
|
+
if not firmwares:
|
34
|
+
return
|
35
|
+
# keep the latest entry
|
36
|
+
unique_fw = {fw.filename: fw for fw in firmwares}
|
37
|
+
with jsonlines.open(fw_folder / "firmware.jsonl", "w") as writer:
|
38
|
+
for fw in unique_fw.values():
|
39
|
+
writer.write(fw.to_dict())
|
40
|
+
log.info(f"Removed duplicate entries from firmware.jsonl in {fw_folder}")
|
41
|
+
|
42
|
+
|
43
|
+
def find_downloaded_firmware(
|
44
|
+
*,
|
45
|
+
board_id: str,
|
46
|
+
version: str = "", # v1.2.3
|
47
|
+
port: str = "",
|
48
|
+
variants: bool = False,
|
49
|
+
fw_folder: Optional[Path] = None,
|
50
|
+
trie: int = 1,
|
51
|
+
selector: Optional[Dict[str, str]] = None,
|
52
|
+
) -> List[FWInfo]:
|
53
|
+
if selector is None:
|
54
|
+
selector = {}
|
55
|
+
fw_folder = fw_folder or config.firmware_folder
|
56
|
+
# Use the information in firmwares.jsonl to find the firmware file
|
57
|
+
log.debug(f"{trie}] Looking for firmware for {board_id} {version} ")
|
58
|
+
fw_list = downloaded_firmwares(fw_folder)
|
59
|
+
if not fw_list:
|
60
|
+
log.error("No firmware files found. Please download the firmware first.")
|
61
|
+
return []
|
62
|
+
# filter by version
|
63
|
+
version = clean_version(version)
|
64
|
+
fw_list = filter_downloaded_fwlist(fw_list, board_id, version, port, variants, selector)
|
65
|
+
|
66
|
+
if not fw_list and trie < 3:
|
67
|
+
log.info(f"Try ({trie+1}) to find a firmware for the board {board_id}")
|
68
|
+
if trie == 1:
|
69
|
+
# ESP board naming conventions have changed by adding a PORT prefix
|
70
|
+
if port.startswith("esp") and not board_id.startswith(port.upper()):
|
71
|
+
board_id = f"{port.upper()}_{board_id}"
|
72
|
+
# RP2 board naming conventions have changed by adding a _RPI prefix
|
73
|
+
if port == "rp2" and not board_id.startswith("RPI_"):
|
74
|
+
board_id = f"RPI_{board_id}"
|
75
|
+
elif trie == 2:
|
76
|
+
board_id = board_id.replace("_", "-")
|
77
|
+
|
78
|
+
fw_list = find_downloaded_firmware(
|
79
|
+
fw_folder=fw_folder,
|
80
|
+
board_id=board_id,
|
81
|
+
version=version,
|
82
|
+
port=port,
|
83
|
+
trie=trie + 1,
|
84
|
+
selector=selector,
|
85
|
+
)
|
86
|
+
# hope we have a match now for the board
|
87
|
+
# sort by filename
|
88
|
+
fw_list.sort(key=lambda x: x.filename)
|
89
|
+
return fw_list
|
90
|
+
|
91
|
+
|
92
|
+
def filter_downloaded_fwlist(
|
93
|
+
fw_list: List[FWInfo],
|
94
|
+
board_id: str,
|
95
|
+
version: str, # v1.2.3
|
96
|
+
port: str,
|
97
|
+
# preview: bool,
|
98
|
+
variants: bool,
|
99
|
+
selector: dict,
|
100
|
+
) -> List[FWInfo]:
|
101
|
+
"""Filter the downloaded firmware list based on the provided parameters"""
|
102
|
+
if "preview" in version:
|
103
|
+
# never get a preview for an older version
|
104
|
+
fw_list = [fw for fw in fw_list if fw.preview]
|
105
|
+
else:
|
106
|
+
# older FWInfo version has no v1.2.3 prefix
|
107
|
+
either = [clean_version(version, drop_v=False), clean_version(version, drop_v=True)]
|
108
|
+
fw_list = [fw for fw in fw_list if fw.version in either]
|
109
|
+
log.trace(f"Filtering firmware for {version} : {len(fw_list)} found.")
|
110
|
+
# filter by port
|
111
|
+
if port:
|
112
|
+
fw_list = [fw for fw in fw_list if fw.port == port and Path(fw.firmware).suffix in PORT_FWTYPES[port]]
|
113
|
+
log.trace(f"Filtering firmware for {port} : {len(fw_list)} found.")
|
114
|
+
|
115
|
+
if board_id:
|
116
|
+
if variants:
|
117
|
+
# any variant of this board_id
|
118
|
+
fw_list = [fw for fw in fw_list if fw.board == board_id]
|
119
|
+
else:
|
120
|
+
# the firmware variant should match exactly the board_id
|
121
|
+
fw_list = [fw for fw in fw_list if fw.variant == board_id]
|
122
|
+
log.trace(f"Filtering firmware for {board_id} : {len(fw_list)} found.")
|
123
|
+
|
124
|
+
if selector and port in selector:
|
125
|
+
fw_list = [fw for fw in fw_list if fw.filename.endswith(selector[port])]
|
126
|
+
return fw_list
|
127
|
+
|
128
|
+
|
129
|
+
# #########################################################################################################
|
130
|
+
#
|
mpflash/errors.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
"""Custom exceptions for the MPFlash package."""
|
2
|
-
|
3
|
-
|
4
|
-
class MPFlashError(Exception):
|
5
|
-
"""Base class for exceptions in this module."""
|
6
|
-
|
7
|
-
def __init__(self, message: str):
|
8
|
-
self.message = message
|
9
|
-
super().__init__(message)
|
1
|
+
"""Custom exceptions for the MPFlash package."""
|
2
|
+
|
3
|
+
|
4
|
+
class MPFlashError(Exception):
|
5
|
+
"""Base class for exceptions in this module."""
|
6
|
+
|
7
|
+
def __init__(self, message: str):
|
8
|
+
self.message = message
|
9
|
+
super().__init__(message)
|
mpflash/flash/__init__.py
CHANGED
@@ -1,55 +1,55 @@
|
|
1
|
-
from pathlib import Path
|
2
|
-
|
3
|
-
from loguru import logger as log
|
4
|
-
|
5
|
-
from mpflash.bootloader import enter_bootloader
|
6
|
-
from mpflash.common import PORT_FWTYPES, BootloaderMethod
|
7
|
-
|
8
|
-
from .esp import flash_esp
|
9
|
-
from .stm32 import flash_stm32
|
10
|
-
from .uf2 import flash_uf2
|
11
|
-
from .worklist import WorkList
|
12
|
-
|
13
|
-
# #########################################################################################################
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
def flash_list(
|
18
|
-
todo: WorkList,
|
19
|
-
fw_folder: Path,
|
20
|
-
erase: bool,
|
21
|
-
bootloader: BootloaderMethod,
|
22
|
-
):
|
23
|
-
"""Flash a list of boards with the specified firmware."""
|
24
|
-
UF2_PORTS = [port for port, exts in PORT_FWTYPES.items() if ".uf2" in exts]
|
25
|
-
flashed = []
|
26
|
-
for mcu, fw_info in todo:
|
27
|
-
fw_file = fw_folder / fw_info.filename
|
28
|
-
if not fw_file.exists():
|
29
|
-
log.error(f"File {fw_file} does not exist, skipping {mcu.board} on {mcu.serialport}")
|
30
|
-
continue
|
31
|
-
log.info(f"Updating {mcu.board} on {mcu.serialport} to {fw_info.version}")
|
32
|
-
updated = None
|
33
|
-
try:
|
34
|
-
if mcu.port in UF2_PORTS and fw_file.suffix == ".uf2":
|
35
|
-
if not enter_bootloader(mcu, bootloader):
|
36
|
-
continue
|
37
|
-
updated = flash_uf2(mcu, fw_file=fw_file, erase=erase)
|
38
|
-
elif mcu.port in ["stm32"]:
|
39
|
-
if not enter_bootloader(mcu, bootloader):
|
40
|
-
continue
|
41
|
-
updated = flash_stm32(mcu, fw_file, erase=erase)
|
42
|
-
elif mcu.port in ["esp32", "esp8266"]:
|
43
|
-
# bootloader is handled by esptool for esp32/esp8266
|
44
|
-
updated = flash_esp(mcu, fw_file=fw_file, erase=erase)
|
45
|
-
else:
|
46
|
-
log.error(f"Don't (yet) know how to flash {mcu.port}-{mcu.board} on {mcu.serialport}")
|
47
|
-
except Exception as e:
|
48
|
-
log.error(f"Failed to flash {mcu.board} on {mcu.serialport}")
|
49
|
-
log.exception(e)
|
50
|
-
|
51
|
-
if updated:
|
52
|
-
flashed.append(updated)
|
53
|
-
else:
|
54
|
-
log.error(f"Failed to flash {mcu.board} on {mcu.serialport}")
|
55
|
-
return flashed
|
1
|
+
from pathlib import Path
|
2
|
+
|
3
|
+
from loguru import logger as log
|
4
|
+
|
5
|
+
from mpflash.bootloader import enter_bootloader
|
6
|
+
from mpflash.common import PORT_FWTYPES, BootloaderMethod
|
7
|
+
|
8
|
+
from .esp import flash_esp
|
9
|
+
from .stm32 import flash_stm32
|
10
|
+
from .uf2 import flash_uf2
|
11
|
+
from .worklist import WorkList
|
12
|
+
|
13
|
+
# #########################################################################################################
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
def flash_list(
|
18
|
+
todo: WorkList,
|
19
|
+
fw_folder: Path,
|
20
|
+
erase: bool,
|
21
|
+
bootloader: BootloaderMethod,
|
22
|
+
):
|
23
|
+
"""Flash a list of boards with the specified firmware."""
|
24
|
+
UF2_PORTS = [port for port, exts in PORT_FWTYPES.items() if ".uf2" in exts]
|
25
|
+
flashed = []
|
26
|
+
for mcu, fw_info in todo:
|
27
|
+
fw_file = fw_folder / fw_info.filename
|
28
|
+
if not fw_file.exists():
|
29
|
+
log.error(f"File {fw_file} does not exist, skipping {mcu.board} on {mcu.serialport}")
|
30
|
+
continue
|
31
|
+
log.info(f"Updating {mcu.board} on {mcu.serialport} to {fw_info.version}")
|
32
|
+
updated = None
|
33
|
+
try:
|
34
|
+
if mcu.port in UF2_PORTS and fw_file.suffix == ".uf2":
|
35
|
+
if not enter_bootloader(mcu, bootloader):
|
36
|
+
continue
|
37
|
+
updated = flash_uf2(mcu, fw_file=fw_file, erase=erase)
|
38
|
+
elif mcu.port in ["stm32"]:
|
39
|
+
if not enter_bootloader(mcu, bootloader):
|
40
|
+
continue
|
41
|
+
updated = flash_stm32(mcu, fw_file, erase=erase)
|
42
|
+
elif mcu.port in ["esp32", "esp8266"]:
|
43
|
+
# bootloader is handled by esptool for esp32/esp8266
|
44
|
+
updated = flash_esp(mcu, fw_file=fw_file, erase=erase)
|
45
|
+
else:
|
46
|
+
log.error(f"Don't (yet) know how to flash {mcu.port}-{mcu.board} on {mcu.serialport}")
|
47
|
+
except Exception as e:
|
48
|
+
log.error(f"Failed to flash {mcu.board} on {mcu.serialport}")
|
49
|
+
log.exception(e)
|
50
|
+
|
51
|
+
if updated:
|
52
|
+
flashed.append(updated)
|
53
|
+
else:
|
54
|
+
log.error(f"Failed to flash {mcu.board} on {mcu.serialport}")
|
55
|
+
return flashed
|
mpflash/flash/esp.py
CHANGED
@@ -1,59 +1,59 @@
|
|
1
|
-
"""
|
2
|
-
# #########################################################################################################
|
3
|
-
# Flash ESP32 and ESP8266 via esptool
|
4
|
-
# #########################################################################################################
|
5
|
-
"""
|
6
|
-
|
7
|
-
from pathlib import Path
|
8
|
-
from typing import List, Optional
|
9
|
-
|
10
|
-
import esptool
|
11
|
-
from loguru import logger as log
|
12
|
-
|
13
|
-
from mpflash.mpboard_id import find_known_board
|
14
|
-
from mpflash.mpremoteboard import MPRemoteBoard
|
15
|
-
|
16
|
-
|
17
|
-
def flash_esp(mcu: MPRemoteBoard, fw_file: Path, *, erase: bool = True) -> Optional[MPRemoteBoard]:
|
18
|
-
if mcu.port not in ["esp32", "esp8266"] or mcu.board in ["ARDUINO_NANO_ESP32"]:
|
19
|
-
log.error(f"esptool not supported for {mcu.port} {mcu.board} on {mcu.serialport}")
|
20
|
-
return None
|
21
|
-
|
22
|
-
log.info(f"Flashing {fw_file} on {mcu.board} on {mcu.serialport}")
|
23
|
-
if not mcu.cpu:
|
24
|
-
# Lookup CPU based on the board name
|
25
|
-
mcu.cpu = find_known_board(mcu.board).cpu
|
26
|
-
|
27
|
-
cmds: List[List[str]] = []
|
28
|
-
if erase:
|
29
|
-
cmds.append(f"esptool --chip {mcu.cpu} --port {mcu.serialport} erase_flash".split())
|
30
|
-
|
31
|
-
if mcu.cpu.upper().startswith("ESP32"):
|
32
|
-
baud_rate = str(921_600)
|
33
|
-
if mcu.cpu.upper() in ("ESP32", "ESP32S2"):
|
34
|
-
start_addr = "0x1000"
|
35
|
-
elif mcu.cpu.upper() in ("ESP32S3", "ESP32C3"):
|
36
|
-
start_addr = "0x0"
|
37
|
-
cmds.append(
|
38
|
-
f"esptool --chip {mcu.cpu} --port {mcu.serialport} -b {baud_rate} write_flash --compress {start_addr}".split()
|
39
|
-
+ [str(fw_file)]
|
40
|
-
)
|
41
|
-
elif mcu.cpu.upper() == "ESP8266":
|
42
|
-
baud_rate = str(460_800)
|
43
|
-
start_addr = "0x0"
|
44
|
-
cmds.append(
|
45
|
-
f"esptool --chip {mcu.cpu} --port {mcu.serialport} -b {baud_rate} write_flash --flash_size=detect {start_addr}".split()
|
46
|
-
+ [str(fw_file)]
|
47
|
-
)
|
48
|
-
try:
|
49
|
-
for cmd in cmds:
|
50
|
-
log.info(f"Running {' '.join(cmd)} ")
|
51
|
-
esptool.main(cmd[1:])
|
52
|
-
except Exception as e:
|
53
|
-
log.error(f"Failed to flash {mcu.board} on {mcu.serialport} : {e}")
|
54
|
-
return None
|
55
|
-
|
56
|
-
log.info("Done flashing, resetting the board...")
|
57
|
-
mcu.wait_for_restart()
|
58
|
-
log.success(f"Flashed {mcu.serialport} to {mcu.board} {mcu.version}")
|
59
|
-
return mcu
|
1
|
+
"""
|
2
|
+
# #########################################################################################################
|
3
|
+
# Flash ESP32 and ESP8266 via esptool
|
4
|
+
# #########################################################################################################
|
5
|
+
"""
|
6
|
+
|
7
|
+
from pathlib import Path
|
8
|
+
from typing import List, Optional
|
9
|
+
|
10
|
+
import esptool
|
11
|
+
from loguru import logger as log
|
12
|
+
|
13
|
+
from mpflash.mpboard_id import find_known_board
|
14
|
+
from mpflash.mpremoteboard import MPRemoteBoard
|
15
|
+
|
16
|
+
|
17
|
+
def flash_esp(mcu: MPRemoteBoard, fw_file: Path, *, erase: bool = True) -> Optional[MPRemoteBoard]:
|
18
|
+
if mcu.port not in ["esp32", "esp8266"] or mcu.board in ["ARDUINO_NANO_ESP32"]:
|
19
|
+
log.error(f"esptool not supported for {mcu.port} {mcu.board} on {mcu.serialport}")
|
20
|
+
return None
|
21
|
+
|
22
|
+
log.info(f"Flashing {fw_file} on {mcu.board} on {mcu.serialport}")
|
23
|
+
if not mcu.cpu:
|
24
|
+
# Lookup CPU based on the board name
|
25
|
+
mcu.cpu = find_known_board(mcu.board).cpu
|
26
|
+
|
27
|
+
cmds: List[List[str]] = []
|
28
|
+
if erase:
|
29
|
+
cmds.append(f"esptool --chip {mcu.cpu} --port {mcu.serialport} erase_flash".split())
|
30
|
+
|
31
|
+
if mcu.cpu.upper().startswith("ESP32"):
|
32
|
+
baud_rate = str(921_600)
|
33
|
+
if mcu.cpu.upper() in ("ESP32", "ESP32S2"):
|
34
|
+
start_addr = "0x1000"
|
35
|
+
elif mcu.cpu.upper() in ("ESP32S3", "ESP32C3"):
|
36
|
+
start_addr = "0x0"
|
37
|
+
cmds.append(
|
38
|
+
f"esptool --chip {mcu.cpu} --port {mcu.serialport} -b {baud_rate} write_flash --compress {start_addr}".split()
|
39
|
+
+ [str(fw_file)]
|
40
|
+
)
|
41
|
+
elif mcu.cpu.upper() == "ESP8266":
|
42
|
+
baud_rate = str(460_800)
|
43
|
+
start_addr = "0x0"
|
44
|
+
cmds.append(
|
45
|
+
f"esptool --chip {mcu.cpu} --port {mcu.serialport} -b {baud_rate} write_flash --flash_size=detect {start_addr}".split()
|
46
|
+
+ [str(fw_file)]
|
47
|
+
)
|
48
|
+
try:
|
49
|
+
for cmd in cmds:
|
50
|
+
log.info(f"Running {' '.join(cmd)} ")
|
51
|
+
esptool.main(cmd[1:])
|
52
|
+
except Exception as e:
|
53
|
+
log.error(f"Failed to flash {mcu.board} on {mcu.serialport} : {e}")
|
54
|
+
return None
|
55
|
+
|
56
|
+
log.info("Done flashing, resetting the board...")
|
57
|
+
mcu.wait_for_restart()
|
58
|
+
log.success(f"Flashed {mcu.serialport} to {mcu.board} {mcu.version}")
|
59
|
+
return mcu
|
mpflash/flash/stm32.py
CHANGED
@@ -1,19 +1,19 @@
|
|
1
|
-
"""Flash STM32 boards using pydfu"""
|
2
|
-
|
3
|
-
from pathlib import Path
|
4
|
-
|
5
|
-
from loguru import logger as log
|
6
|
-
|
7
|
-
from mpflash.mpremoteboard import MPRemoteBoard
|
8
|
-
|
9
|
-
# from .flash_stm32_cube import flash_stm32_cubecli
|
10
|
-
from .stm32_dfu import dfu_init, flash_stm32_dfu
|
11
|
-
|
12
|
-
|
13
|
-
def flash_stm32(mcu: MPRemoteBoard, fw_file: Path, *, erase: bool):
|
14
|
-
# sourcery skip: lift-return-into-if
|
15
|
-
dfu_init()
|
16
|
-
if updated := flash_stm32_dfu(mcu, fw_file=fw_file, erase=erase):
|
17
|
-
mcu.wait_for_restart()
|
18
|
-
log.success(f"Flashed {mcu.version} to {mcu.board}")
|
19
|
-
return updated
|
1
|
+
"""Flash STM32 boards using pydfu"""
|
2
|
+
|
3
|
+
from pathlib import Path
|
4
|
+
|
5
|
+
from loguru import logger as log
|
6
|
+
|
7
|
+
from mpflash.mpremoteboard import MPRemoteBoard
|
8
|
+
|
9
|
+
# from .flash_stm32_cube import flash_stm32_cubecli
|
10
|
+
from .stm32_dfu import dfu_init, flash_stm32_dfu
|
11
|
+
|
12
|
+
|
13
|
+
def flash_stm32(mcu: MPRemoteBoard, fw_file: Path, *, erase: bool):
|
14
|
+
# sourcery skip: lift-return-into-if
|
15
|
+
dfu_init()
|
16
|
+
if updated := flash_stm32_dfu(mcu, fw_file=fw_file, erase=erase):
|
17
|
+
mcu.wait_for_restart()
|
18
|
+
log.success(f"Flashed {mcu.version} to {mcu.board}")
|
19
|
+
return updated
|