mpflash 0.8.5__py3-none-any.whl → 0.8.7__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/bootloader/__init__.py +37 -36
- mpflash/bootloader/manual.py +102 -102
- mpflash/bootloader/micropython.py +10 -10
- mpflash/bootloader/touch1200.py +45 -45
- mpflash/cli_download.py +129 -129
- mpflash/cli_flash.py +219 -219
- mpflash/cli_group.py +98 -98
- mpflash/cli_list.py +81 -81
- mpflash/cli_main.py +41 -41
- mpflash/common.py +164 -164
- mpflash/config.py +47 -47
- mpflash/connected.py +74 -74
- mpflash/download.py +360 -360
- mpflash/downloaded.py +129 -129
- mpflash/errors.py +9 -9
- mpflash/flash.py +52 -52
- mpflash/flash_esp.py +59 -59
- mpflash/flash_stm32.py +24 -24
- mpflash/flash_stm32_cube.py +111 -111
- mpflash/flash_stm32_dfu.py +101 -101
- mpflash/flash_uf2.py +67 -67
- mpflash/flash_uf2_boardid.py +15 -15
- mpflash/flash_uf2_linux.py +123 -123
- mpflash/flash_uf2_macos.py +34 -34
- mpflash/flash_uf2_windows.py +34 -34
- mpflash/list.py +89 -89
- mpflash/logger.py +41 -41
- mpflash/mpboard_id/__init__.py +93 -93
- mpflash/mpboard_id/add_boards.py +255 -255
- 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 +221 -221
- mpflash/mpremoteboard/mpy_fw_info.py +141 -141
- mpflash/mpremoteboard/runner.py +140 -140
- mpflash/uf2disk.py +12 -12
- mpflash/vendor/basicgit.py +288 -288
- 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/vendor/versions.py +119 -117
- mpflash/worklist.py +170 -170
- {mpflash-0.8.5.dist-info → mpflash-0.8.7.dist-info}/LICENSE +20 -20
- {mpflash-0.8.5.dist-info → mpflash-0.8.7.dist-info}/METADATA +1 -1
- mpflash-0.8.7.dist-info/RECORD +52 -0
- mpflash-0.8.5.dist-info/RECORD +0 -52
- {mpflash-0.8.5.dist-info → mpflash-0.8.7.dist-info}/WHEEL +0 -0
- {mpflash-0.8.5.dist-info → mpflash-0.8.7.dist-info}/entry_points.txt +0 -0
mpflash/flash_stm32_cube.py
CHANGED
@@ -1,111 +1,111 @@
|
|
1
|
-
# """
|
2
|
-
# Flash STM32 using STM32CubeProgrammer
|
3
|
-
# needs to be installed independenty from https://www.st.com/en/development-tools/stm32cubeprog.html
|
4
|
-
|
5
|
-
# On Linux needs to be run with sudo - unless udev rules are set to allow access to the device as a regular user
|
6
|
-
# """
|
7
|
-
|
8
|
-
# import subprocess
|
9
|
-
# import sys
|
10
|
-
# import time
|
11
|
-
# from pathlib import Path
|
12
|
-
# from typing import Optional
|
13
|
-
|
14
|
-
# import bincopy
|
15
|
-
# from loguru import logger as log
|
16
|
-
# from rich.progress import track
|
17
|
-
# from strip_ansi import strip_ansi
|
18
|
-
|
19
|
-
# from .mpremoteboard.mpremoteboard import MPRemoteBoard
|
20
|
-
|
21
|
-
# STM32_CLI_WIN = "C:\\Program Files\\STMicroelectronics\\STM32Cube\\STM32CubeProgrammer\\bin\\STM32_Programmer_CLI.exe"
|
22
|
-
# STM32_CLI_LINUX = "~/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin/STM32_Programmer_CLI"
|
23
|
-
|
24
|
-
|
25
|
-
# def get_stm32_start_address(fw_file: Path):
|
26
|
-
# """
|
27
|
-
# Get the start address of the firmware file, to allow automatic restart from that address after flashing
|
28
|
-
# """
|
29
|
-
# try:
|
30
|
-
# fw_hex = bincopy.BinFile(str(fw_file))
|
31
|
-
# return f"0x{fw_hex.execution_start_address:08X}"
|
32
|
-
# except Exception:
|
33
|
-
|
34
|
-
# return ""
|
35
|
-
|
36
|
-
|
37
|
-
# def flash_stm32_cubecli(mcu: MPRemoteBoard, fw_file: Path, *, erase: bool = True) -> Optional[MPRemoteBoard]:
|
38
|
-
# """
|
39
|
-
# Flash STM32 devices using STM32CubeProgrammer CLI
|
40
|
-
# - Enter bootloader mode
|
41
|
-
# - wait 2s for the device to be detected
|
42
|
-
# - list the connected DFU devices
|
43
|
-
|
44
|
-
# On Linux: requires udev rules to allow access to the device as a regular user
|
45
|
-
# """
|
46
|
-
# if sys.platform == "linux":
|
47
|
-
# STM32_CLI = Path(STM32_CLI_LINUX).expanduser().as_posix()
|
48
|
-
# elif sys.platform == "win32":
|
49
|
-
# STM32_CLI = str(Path(STM32_CLI_WIN).expanduser())
|
50
|
-
# else:
|
51
|
-
# log.error(f"OS {sys.platform} not supported")
|
52
|
-
# return None
|
53
|
-
|
54
|
-
# if not Path(STM32_CLI).exists():
|
55
|
-
# log.error(
|
56
|
-
# f"STM32CubeProgrammer not found at {STM32_CLI}\nPlease install it from https://www.st.com/en/development-tools/stm32cubeprog.html"
|
57
|
-
# )
|
58
|
-
# return None
|
59
|
-
|
60
|
-
# # run STM32_Programmer_CLI.exe --list
|
61
|
-
# cmd = [
|
62
|
-
# STM32_CLI,
|
63
|
-
# "--list",
|
64
|
-
# ]
|
65
|
-
# results = subprocess.run(cmd, capture_output=True, text=True).stdout.splitlines()
|
66
|
-
# results = [strip_ansi(line) for line in results]
|
67
|
-
# if not any(["Product ID : STM32 BOOTLOADER" in l for l in results]):
|
68
|
-
# log.error("No STM32 BOOTLOADER detected")
|
69
|
-
# return None
|
70
|
-
# echo = False
|
71
|
-
# for line in results:
|
72
|
-
# if line.startswith("===== DFU Interface"):
|
73
|
-
# echo = True
|
74
|
-
# if line.startswith("===== STLink"):
|
75
|
-
# echo = False
|
76
|
-
# if echo:
|
77
|
-
# print(line)
|
78
|
-
# # Try to connect - no action
|
79
|
-
# cmd = [
|
80
|
-
# STM32_CLI,
|
81
|
-
# "--connect",
|
82
|
-
# "port=USB1",
|
83
|
-
# ]
|
84
|
-
# results = subprocess.run(cmd, capture_output=True, text=True).stdout.splitlines()
|
85
|
-
# if erase:
|
86
|
-
# log.info("Erasing flash")
|
87
|
-
# cmd = [
|
88
|
-
# STM32_CLI,
|
89
|
-
# "--connect",
|
90
|
-
# "port=USB1",
|
91
|
-
# "--erase",
|
92
|
-
# "all",
|
93
|
-
# ]
|
94
|
-
# results = subprocess.run(cmd, capture_output=True, text=True).stdout.splitlines()
|
95
|
-
# results = [strip_ansi(line) for line in results]
|
96
|
-
# log.info(f"Flashing {fw_file.name} using STM32CubeProgrammer CLI")
|
97
|
-
# start_address = get_stm32_start_address(fw_file)
|
98
|
-
|
99
|
-
# log.trace(f"STM32_Programmer_CLI --connect port=USB1 --write {str(fw_file)} --go {start_address}")
|
100
|
-
# cmd = [
|
101
|
-
# STM32_CLI,
|
102
|
-
# "--connect",
|
103
|
-
# "port=USB1",
|
104
|
-
# "--write",
|
105
|
-
# str(fw_file),
|
106
|
-
# "--go",
|
107
|
-
# start_address,
|
108
|
-
# ]
|
109
|
-
# results = subprocess.run(cmd, capture_output=True, text=True).stdout.splitlines()
|
110
|
-
# log.success("Done flashing, resetting the board and wait for it to restart")
|
111
|
-
# return mcu
|
1
|
+
# """
|
2
|
+
# Flash STM32 using STM32CubeProgrammer
|
3
|
+
# needs to be installed independenty from https://www.st.com/en/development-tools/stm32cubeprog.html
|
4
|
+
|
5
|
+
# On Linux needs to be run with sudo - unless udev rules are set to allow access to the device as a regular user
|
6
|
+
# """
|
7
|
+
|
8
|
+
# import subprocess
|
9
|
+
# import sys
|
10
|
+
# import time
|
11
|
+
# from pathlib import Path
|
12
|
+
# from typing import Optional
|
13
|
+
|
14
|
+
# import bincopy
|
15
|
+
# from loguru import logger as log
|
16
|
+
# from rich.progress import track
|
17
|
+
# from strip_ansi import strip_ansi
|
18
|
+
|
19
|
+
# from .mpremoteboard.mpremoteboard import MPRemoteBoard
|
20
|
+
|
21
|
+
# STM32_CLI_WIN = "C:\\Program Files\\STMicroelectronics\\STM32Cube\\STM32CubeProgrammer\\bin\\STM32_Programmer_CLI.exe"
|
22
|
+
# STM32_CLI_LINUX = "~/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin/STM32_Programmer_CLI"
|
23
|
+
|
24
|
+
|
25
|
+
# def get_stm32_start_address(fw_file: Path):
|
26
|
+
# """
|
27
|
+
# Get the start address of the firmware file, to allow automatic restart from that address after flashing
|
28
|
+
# """
|
29
|
+
# try:
|
30
|
+
# fw_hex = bincopy.BinFile(str(fw_file))
|
31
|
+
# return f"0x{fw_hex.execution_start_address:08X}"
|
32
|
+
# except Exception:
|
33
|
+
|
34
|
+
# return ""
|
35
|
+
|
36
|
+
|
37
|
+
# def flash_stm32_cubecli(mcu: MPRemoteBoard, fw_file: Path, *, erase: bool = True) -> Optional[MPRemoteBoard]:
|
38
|
+
# """
|
39
|
+
# Flash STM32 devices using STM32CubeProgrammer CLI
|
40
|
+
# - Enter bootloader mode
|
41
|
+
# - wait 2s for the device to be detected
|
42
|
+
# - list the connected DFU devices
|
43
|
+
|
44
|
+
# On Linux: requires udev rules to allow access to the device as a regular user
|
45
|
+
# """
|
46
|
+
# if sys.platform == "linux":
|
47
|
+
# STM32_CLI = Path(STM32_CLI_LINUX).expanduser().as_posix()
|
48
|
+
# elif sys.platform == "win32":
|
49
|
+
# STM32_CLI = str(Path(STM32_CLI_WIN).expanduser())
|
50
|
+
# else:
|
51
|
+
# log.error(f"OS {sys.platform} not supported")
|
52
|
+
# return None
|
53
|
+
|
54
|
+
# if not Path(STM32_CLI).exists():
|
55
|
+
# log.error(
|
56
|
+
# f"STM32CubeProgrammer not found at {STM32_CLI}\nPlease install it from https://www.st.com/en/development-tools/stm32cubeprog.html"
|
57
|
+
# )
|
58
|
+
# return None
|
59
|
+
|
60
|
+
# # run STM32_Programmer_CLI.exe --list
|
61
|
+
# cmd = [
|
62
|
+
# STM32_CLI,
|
63
|
+
# "--list",
|
64
|
+
# ]
|
65
|
+
# results = subprocess.run(cmd, capture_output=True, text=True).stdout.splitlines()
|
66
|
+
# results = [strip_ansi(line) for line in results]
|
67
|
+
# if not any(["Product ID : STM32 BOOTLOADER" in l for l in results]):
|
68
|
+
# log.error("No STM32 BOOTLOADER detected")
|
69
|
+
# return None
|
70
|
+
# echo = False
|
71
|
+
# for line in results:
|
72
|
+
# if line.startswith("===== DFU Interface"):
|
73
|
+
# echo = True
|
74
|
+
# if line.startswith("===== STLink"):
|
75
|
+
# echo = False
|
76
|
+
# if echo:
|
77
|
+
# print(line)
|
78
|
+
# # Try to connect - no action
|
79
|
+
# cmd = [
|
80
|
+
# STM32_CLI,
|
81
|
+
# "--connect",
|
82
|
+
# "port=USB1",
|
83
|
+
# ]
|
84
|
+
# results = subprocess.run(cmd, capture_output=True, text=True).stdout.splitlines()
|
85
|
+
# if erase:
|
86
|
+
# log.info("Erasing flash")
|
87
|
+
# cmd = [
|
88
|
+
# STM32_CLI,
|
89
|
+
# "--connect",
|
90
|
+
# "port=USB1",
|
91
|
+
# "--erase",
|
92
|
+
# "all",
|
93
|
+
# ]
|
94
|
+
# results = subprocess.run(cmd, capture_output=True, text=True).stdout.splitlines()
|
95
|
+
# results = [strip_ansi(line) for line in results]
|
96
|
+
# log.info(f"Flashing {fw_file.name} using STM32CubeProgrammer CLI")
|
97
|
+
# start_address = get_stm32_start_address(fw_file)
|
98
|
+
|
99
|
+
# log.trace(f"STM32_Programmer_CLI --connect port=USB1 --write {str(fw_file)} --go {start_address}")
|
100
|
+
# cmd = [
|
101
|
+
# STM32_CLI,
|
102
|
+
# "--connect",
|
103
|
+
# "port=USB1",
|
104
|
+
# "--write",
|
105
|
+
# str(fw_file),
|
106
|
+
# "--go",
|
107
|
+
# start_address,
|
108
|
+
# ]
|
109
|
+
# results = subprocess.run(cmd, capture_output=True, text=True).stdout.splitlines()
|
110
|
+
# log.success("Done flashing, resetting the board and wait for it to restart")
|
111
|
+
# return mcu
|
mpflash/flash_stm32_dfu.py
CHANGED
@@ -1,101 +1,101 @@
|
|
1
|
-
import platform
|
2
|
-
from pathlib import Path
|
3
|
-
from typing import Optional
|
4
|
-
|
5
|
-
from loguru import logger as log
|
6
|
-
|
7
|
-
from mpflash.mpremoteboard import MPRemoteBoard
|
8
|
-
|
9
|
-
|
10
|
-
def init_libusb_windows() -> bool:
|
11
|
-
"""
|
12
|
-
Initializes the libusb backend on Windows.
|
13
|
-
|
14
|
-
Returns:
|
15
|
-
bool: True if the initialization is successful, False otherwise.
|
16
|
-
"""
|
17
|
-
import libusb # type: ignore
|
18
|
-
import usb.backend.libusb1 as libusb1
|
19
|
-
|
20
|
-
arch = "x64" if platform.architecture()[0] == "64bit" else "x86"
|
21
|
-
libusb1_dll = Path(libusb.__file__).parent / f"_platform\\_windows\\{arch}\\libusb-1.0.dll"
|
22
|
-
if not libusb1_dll.exists():
|
23
|
-
raise FileNotFoundError(f"libusb1.dll not found at {libusb1_dll}")
|
24
|
-
backend = libusb1.get_backend(find_library=lambda x: libusb1_dll.as_posix())
|
25
|
-
return backend is not None
|
26
|
-
|
27
|
-
|
28
|
-
try:
|
29
|
-
from .vendor import pydfu as pydfu
|
30
|
-
except ImportError:
|
31
|
-
pydfu = None
|
32
|
-
|
33
|
-
|
34
|
-
def dfu_init():
|
35
|
-
"""
|
36
|
-
Initializes the DFU (Device Firmware Upgrade) process.
|
37
|
-
"""
|
38
|
-
if not pydfu:
|
39
|
-
log.error("pydfu not found")
|
40
|
-
return None
|
41
|
-
if platform.system() == "Windows":
|
42
|
-
init_libusb_windows()
|
43
|
-
|
44
|
-
|
45
|
-
def flash_stm32_dfu(
|
46
|
-
mcu: MPRemoteBoard,
|
47
|
-
fw_file: Path,
|
48
|
-
*,
|
49
|
-
erase: bool = True,
|
50
|
-
) -> Optional[MPRemoteBoard]:
|
51
|
-
"""
|
52
|
-
Flashes the STM32 microcontroller using DFU (Device Firmware Upgrade).
|
53
|
-
|
54
|
-
Args:
|
55
|
-
mcu (MPRemoteBoard): The remote board to flash.
|
56
|
-
fw_file (Path): The path to the firmware file (.dfu).
|
57
|
-
erase (bool, optional): Whether to erase the memory before flashing. Defaults to True.
|
58
|
-
|
59
|
-
Returns:
|
60
|
-
Optional[MPRemoteBoard]: The flashed remote board if successful, None otherwise.
|
61
|
-
"""
|
62
|
-
if not pydfu:
|
63
|
-
log.error("pydfu not found, please install it with 'pip install pydfu' if supported")
|
64
|
-
return None
|
65
|
-
|
66
|
-
if not fw_file.exists():
|
67
|
-
log.error(f"File {fw_file} not found")
|
68
|
-
return None
|
69
|
-
|
70
|
-
if fw_file.suffix != ".dfu":
|
71
|
-
log.error(f"File {fw_file} is not a .dfu file")
|
72
|
-
return None
|
73
|
-
|
74
|
-
kwargs = {"idVendor": 0x0483, "idProduct": 0xDF11}
|
75
|
-
log.debug("List SPECIFIED DFU devices...")
|
76
|
-
try:
|
77
|
-
pydfu.list_dfu_devices(**kwargs)
|
78
|
-
except ValueError as e:
|
79
|
-
log.error(f"Insuffient permissions to access usb DFU devices: {e}")
|
80
|
-
return None
|
81
|
-
|
82
|
-
# Needs to be a list of serial ports
|
83
|
-
log.debug("Inititialize pydfu...")
|
84
|
-
pydfu.init(**kwargs)
|
85
|
-
|
86
|
-
if erase:
|
87
|
-
log.info("Mass erase...")
|
88
|
-
pydfu.mass_erase()
|
89
|
-
|
90
|
-
log.debug("Read DFU file...")
|
91
|
-
elements = pydfu.read_dfu_file(fw_file)
|
92
|
-
if not elements:
|
93
|
-
print("No data in dfu file")
|
94
|
-
return
|
95
|
-
log.info("Writing memory...")
|
96
|
-
pydfu.write_elements(elements, False, progress=pydfu.cli_progress)
|
97
|
-
|
98
|
-
log.debug("Exiting DFU...")
|
99
|
-
pydfu.exit_dfu()
|
100
|
-
log.success("Done flashing, resetting the board and wait for it to restart")
|
101
|
-
return mcu
|
1
|
+
import platform
|
2
|
+
from pathlib import Path
|
3
|
+
from typing import Optional
|
4
|
+
|
5
|
+
from loguru import logger as log
|
6
|
+
|
7
|
+
from mpflash.mpremoteboard import MPRemoteBoard
|
8
|
+
|
9
|
+
|
10
|
+
def init_libusb_windows() -> bool:
|
11
|
+
"""
|
12
|
+
Initializes the libusb backend on Windows.
|
13
|
+
|
14
|
+
Returns:
|
15
|
+
bool: True if the initialization is successful, False otherwise.
|
16
|
+
"""
|
17
|
+
import libusb # type: ignore
|
18
|
+
import usb.backend.libusb1 as libusb1
|
19
|
+
|
20
|
+
arch = "x64" if platform.architecture()[0] == "64bit" else "x86"
|
21
|
+
libusb1_dll = Path(libusb.__file__).parent / f"_platform\\_windows\\{arch}\\libusb-1.0.dll"
|
22
|
+
if not libusb1_dll.exists():
|
23
|
+
raise FileNotFoundError(f"libusb1.dll not found at {libusb1_dll}")
|
24
|
+
backend = libusb1.get_backend(find_library=lambda x: libusb1_dll.as_posix())
|
25
|
+
return backend is not None
|
26
|
+
|
27
|
+
|
28
|
+
try:
|
29
|
+
from .vendor import pydfu as pydfu
|
30
|
+
except ImportError:
|
31
|
+
pydfu = None
|
32
|
+
|
33
|
+
|
34
|
+
def dfu_init():
|
35
|
+
"""
|
36
|
+
Initializes the DFU (Device Firmware Upgrade) process.
|
37
|
+
"""
|
38
|
+
if not pydfu:
|
39
|
+
log.error("pydfu not found")
|
40
|
+
return None
|
41
|
+
if platform.system() == "Windows":
|
42
|
+
init_libusb_windows()
|
43
|
+
|
44
|
+
|
45
|
+
def flash_stm32_dfu(
|
46
|
+
mcu: MPRemoteBoard,
|
47
|
+
fw_file: Path,
|
48
|
+
*,
|
49
|
+
erase: bool = True,
|
50
|
+
) -> Optional[MPRemoteBoard]:
|
51
|
+
"""
|
52
|
+
Flashes the STM32 microcontroller using DFU (Device Firmware Upgrade).
|
53
|
+
|
54
|
+
Args:
|
55
|
+
mcu (MPRemoteBoard): The remote board to flash.
|
56
|
+
fw_file (Path): The path to the firmware file (.dfu).
|
57
|
+
erase (bool, optional): Whether to erase the memory before flashing. Defaults to True.
|
58
|
+
|
59
|
+
Returns:
|
60
|
+
Optional[MPRemoteBoard]: The flashed remote board if successful, None otherwise.
|
61
|
+
"""
|
62
|
+
if not pydfu:
|
63
|
+
log.error("pydfu not found, please install it with 'pip install pydfu' if supported")
|
64
|
+
return None
|
65
|
+
|
66
|
+
if not fw_file.exists():
|
67
|
+
log.error(f"File {fw_file} not found")
|
68
|
+
return None
|
69
|
+
|
70
|
+
if fw_file.suffix != ".dfu":
|
71
|
+
log.error(f"File {fw_file} is not a .dfu file")
|
72
|
+
return None
|
73
|
+
|
74
|
+
kwargs = {"idVendor": 0x0483, "idProduct": 0xDF11}
|
75
|
+
log.debug("List SPECIFIED DFU devices...")
|
76
|
+
try:
|
77
|
+
pydfu.list_dfu_devices(**kwargs)
|
78
|
+
except ValueError as e:
|
79
|
+
log.error(f"Insuffient permissions to access usb DFU devices: {e}")
|
80
|
+
return None
|
81
|
+
|
82
|
+
# Needs to be a list of serial ports
|
83
|
+
log.debug("Inititialize pydfu...")
|
84
|
+
pydfu.init(**kwargs)
|
85
|
+
|
86
|
+
if erase:
|
87
|
+
log.info("Mass erase...")
|
88
|
+
pydfu.mass_erase()
|
89
|
+
|
90
|
+
log.debug("Read DFU file...")
|
91
|
+
elements = pydfu.read_dfu_file(fw_file)
|
92
|
+
if not elements:
|
93
|
+
print("No data in dfu file")
|
94
|
+
return
|
95
|
+
log.info("Writing memory...")
|
96
|
+
pydfu.write_elements(elements, False, progress=pydfu.cli_progress)
|
97
|
+
|
98
|
+
log.debug("Exiting DFU...")
|
99
|
+
pydfu.exit_dfu()
|
100
|
+
log.success("Done flashing, resetting the board and wait for it to restart")
|
101
|
+
return mcu
|
mpflash/flash_uf2.py
CHANGED
@@ -1,67 +1,67 @@
|
|
1
|
-
"""
|
2
|
-
Flash SAMD and RP2 via UF2
|
3
|
-
"""
|
4
|
-
|
5
|
-
import shutil
|
6
|
-
import sys
|
7
|
-
import time
|
8
|
-
from pathlib import Path
|
9
|
-
from typing import Optional
|
10
|
-
|
11
|
-
from loguru import logger as log
|
12
|
-
from rich.progress import track
|
13
|
-
|
14
|
-
from mpflash.mpremoteboard import MPRemoteBoard
|
15
|
-
|
16
|
-
from .common import PORT_FWTYPES
|
17
|
-
from .flash_uf2_boardid import get_board_id
|
18
|
-
from .flash_uf2_linux import dismount_uf2_linux, wait_for_UF2_linux
|
19
|
-
from .flash_uf2_macos import wait_for_UF2_macos
|
20
|
-
from .flash_uf2_windows import wait_for_UF2_windows
|
21
|
-
|
22
|
-
|
23
|
-
def flash_uf2(mcu: MPRemoteBoard, fw_file: Path, erase: bool) -> Optional[MPRemoteBoard]:
|
24
|
-
"""
|
25
|
-
Flash .UF2 devices via bootloader and filecopy
|
26
|
-
- mpremote bootloader
|
27
|
-
- Wait for the device to mount as a drive (up to 5s)
|
28
|
-
- detect new drive with INFO_UF2.TXT
|
29
|
-
- copy the firmware file to the drive
|
30
|
-
- wait for the device to restart (5s)
|
31
|
-
|
32
|
-
for Linux - to support headless operation ( GH Actions ) :
|
33
|
-
pmount and pumount are used to mount and unmount the drive
|
34
|
-
as this is not done automatically by the OS in headless mode.
|
35
|
-
"""
|
36
|
-
if ".uf2" not in PORT_FWTYPES[mcu.port]:
|
37
|
-
log.error(f"UF2 not supported on {mcu.board} on {mcu.serialport}")
|
38
|
-
return None
|
39
|
-
if erase:
|
40
|
-
log.info("Erasing not yet implemented for UF2 flashing.")
|
41
|
-
|
42
|
-
if sys.platform == "linux":
|
43
|
-
destination = wait_for_UF2_linux()
|
44
|
-
elif sys.platform == "win32":
|
45
|
-
destination = wait_for_UF2_windows()
|
46
|
-
elif sys.platform == "darwin":
|
47
|
-
log.warning(f"OS {sys.platform} not tested/supported")
|
48
|
-
destination = wait_for_UF2_macos()
|
49
|
-
else:
|
50
|
-
log.warning(f"OS {sys.platform} not tested/supported")
|
51
|
-
return None
|
52
|
-
|
53
|
-
if not destination or not destination.exists() or not (destination / "INFO_UF2.TXT").exists():
|
54
|
-
log.error("Board is not in bootloader mode")
|
55
|
-
return None
|
56
|
-
|
57
|
-
log.info("Board is in bootloader mode")
|
58
|
-
board_id = get_board_id(destination) # type: ignore
|
59
|
-
log.info(f"Board ID: {board_id}")
|
60
|
-
log.info(f"Copying {fw_file} to {destination}.")
|
61
|
-
shutil.copy(fw_file, destination)
|
62
|
-
log.success("Done copying, resetting the board and wait for it to restart")
|
63
|
-
if sys.platform in ["linux"]:
|
64
|
-
dismount_uf2_linux()
|
65
|
-
for _ in track(range(5 + 2), description="Waiting for the board to restart", transient=True, refresh_per_second=2):
|
66
|
-
time.sleep(1) # 5 secs to short on linux
|
67
|
-
return mcu
|
1
|
+
"""
|
2
|
+
Flash SAMD and RP2 via UF2
|
3
|
+
"""
|
4
|
+
|
5
|
+
import shutil
|
6
|
+
import sys
|
7
|
+
import time
|
8
|
+
from pathlib import Path
|
9
|
+
from typing import Optional
|
10
|
+
|
11
|
+
from loguru import logger as log
|
12
|
+
from rich.progress import track
|
13
|
+
|
14
|
+
from mpflash.mpremoteboard import MPRemoteBoard
|
15
|
+
|
16
|
+
from .common import PORT_FWTYPES
|
17
|
+
from .flash_uf2_boardid import get_board_id
|
18
|
+
from .flash_uf2_linux import dismount_uf2_linux, wait_for_UF2_linux
|
19
|
+
from .flash_uf2_macos import wait_for_UF2_macos
|
20
|
+
from .flash_uf2_windows import wait_for_UF2_windows
|
21
|
+
|
22
|
+
|
23
|
+
def flash_uf2(mcu: MPRemoteBoard, fw_file: Path, erase: bool) -> Optional[MPRemoteBoard]:
|
24
|
+
"""
|
25
|
+
Flash .UF2 devices via bootloader and filecopy
|
26
|
+
- mpremote bootloader
|
27
|
+
- Wait for the device to mount as a drive (up to 5s)
|
28
|
+
- detect new drive with INFO_UF2.TXT
|
29
|
+
- copy the firmware file to the drive
|
30
|
+
- wait for the device to restart (5s)
|
31
|
+
|
32
|
+
for Linux - to support headless operation ( GH Actions ) :
|
33
|
+
pmount and pumount are used to mount and unmount the drive
|
34
|
+
as this is not done automatically by the OS in headless mode.
|
35
|
+
"""
|
36
|
+
if ".uf2" not in PORT_FWTYPES[mcu.port]:
|
37
|
+
log.error(f"UF2 not supported on {mcu.board} on {mcu.serialport}")
|
38
|
+
return None
|
39
|
+
if erase:
|
40
|
+
log.info("Erasing not yet implemented for UF2 flashing.")
|
41
|
+
|
42
|
+
if sys.platform == "linux":
|
43
|
+
destination = wait_for_UF2_linux()
|
44
|
+
elif sys.platform == "win32":
|
45
|
+
destination = wait_for_UF2_windows()
|
46
|
+
elif sys.platform == "darwin":
|
47
|
+
log.warning(f"OS {sys.platform} not tested/supported")
|
48
|
+
destination = wait_for_UF2_macos()
|
49
|
+
else:
|
50
|
+
log.warning(f"OS {sys.platform} not tested/supported")
|
51
|
+
return None
|
52
|
+
|
53
|
+
if not destination or not destination.exists() or not (destination / "INFO_UF2.TXT").exists():
|
54
|
+
log.error("Board is not in bootloader mode")
|
55
|
+
return None
|
56
|
+
|
57
|
+
log.info("Board is in bootloader mode")
|
58
|
+
board_id = get_board_id(destination) # type: ignore
|
59
|
+
log.info(f"Board ID: {board_id}")
|
60
|
+
log.info(f"Copying {fw_file} to {destination}.")
|
61
|
+
shutil.copy(fw_file, destination)
|
62
|
+
log.success("Done copying, resetting the board and wait for it to restart")
|
63
|
+
if sys.platform in ["linux"]:
|
64
|
+
dismount_uf2_linux()
|
65
|
+
for _ in track(range(5 + 2), description="Waiting for the board to restart", transient=True, refresh_per_second=2):
|
66
|
+
time.sleep(1) # 5 secs to short on linux
|
67
|
+
return mcu
|
mpflash/flash_uf2_boardid.py
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
from pathlib import Path
|
2
|
-
|
3
|
-
from loguru import logger as log
|
4
|
-
|
5
|
-
|
6
|
-
def get_board_id(path: Path):
|
7
|
-
# Option : read Board-ID from INFO_UF2.TXT
|
8
|
-
board_id = "Unknown"
|
9
|
-
with open(path / "INFO_UF2.TXT") as f:
|
10
|
-
data = f.readlines()
|
11
|
-
for line in data:
|
12
|
-
if line.startswith("Board-ID"):
|
13
|
-
board_id = line[9:].strip()
|
14
|
-
log.debug(f"INFO_UF2.TXT Board-ID={board_id}")
|
15
|
-
return board_id
|
1
|
+
from pathlib import Path
|
2
|
+
|
3
|
+
from loguru import logger as log
|
4
|
+
|
5
|
+
|
6
|
+
def get_board_id(path: Path):
|
7
|
+
# Option : read Board-ID from INFO_UF2.TXT
|
8
|
+
board_id = "Unknown"
|
9
|
+
with open(path / "INFO_UF2.TXT") as f:
|
10
|
+
data = f.readlines()
|
11
|
+
for line in data:
|
12
|
+
if line.startswith("Board-ID"):
|
13
|
+
board_id = line[9:].strip()
|
14
|
+
log.debug(f"INFO_UF2.TXT Board-ID={board_id}")
|
15
|
+
return board_id
|