mpflash 0.5.0__py3-none-any.whl → 0.7.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.
mpflash/common.py CHANGED
@@ -1,14 +1,12 @@
1
1
  import os
2
2
  import time
3
- from functools import lru_cache
4
3
  from typing import TypedDict
5
4
 
6
5
  from github import Auth, Github
7
- from loguru import logger as log
8
- from packaging.version import parse
9
6
  from rich.progress import track
10
7
 
11
- from mpflash.mpremoteboard import MPRemoteBoard
8
+ from mpflash.errors import MPFlashError
9
+ # from mpflash.mpremoteboard import MPRemoteBoard
12
10
 
13
11
  PORT_FWTYPES = {
14
12
  "stm32": [".dfu"], # need .dfu for pydfu.py - .hex for cube cli/GUI
@@ -38,125 +36,3 @@ class FWInfo(TypedDict):
38
36
  preview: bool
39
37
  version: str
40
38
  build: str
41
-
42
-
43
- #############################################################
44
- # Version handling copied from stubber/utils/versions.py
45
- #############################################################
46
- V_PREVIEW = "preview"
47
- "Latest preview version"
48
-
49
- SET_PREVIEW = {"preview", "latest", "master"}
50
-
51
-
52
- def clean_version(
53
- version: str,
54
- *,
55
- build: bool = False,
56
- patch: bool = False,
57
- commit: bool = False,
58
- drop_v: bool = False,
59
- flat: bool = False,
60
- ):
61
- "Clean up and transform the many flavours of versions"
62
- # 'v1.13.0-103-gb137d064e' --> 'v1.13-103'
63
- if version in {"", "-"}:
64
- return version
65
- if version.lower() == "stable":
66
- _v = get_stable_mp_version()
67
- if not _v:
68
- log.warning("Could not determine the latest stable version")
69
- return "stable"
70
- version = _v
71
- log.info(f"Using latest stable version: {version}")
72
- is_preview = "-preview" in version
73
- nibbles = version.split("-")
74
- ver_ = nibbles[0].lower().lstrip("v")
75
- if not patch and ver_ >= "1.10.0" and ver_ < "1.20.0" and ver_.endswith(".0"):
76
- # remove the last ".0" - but only for versions between 1.10 and 1.20 (because)
77
- nibbles[0] = nibbles[0][:-2]
78
- if len(nibbles) == 1:
79
- version = nibbles[0]
80
- elif build and not is_preview:
81
- version = "-".join(nibbles) if commit else "-".join(nibbles[:-1])
82
- else:
83
- # version = "-".join((nibbles[0], LATEST))
84
- # HACK: this is not always right, but good enough most of the time
85
- if is_preview:
86
- version = "-".join((nibbles[0], V_PREVIEW))
87
- else:
88
- version = V_PREVIEW
89
- if flat:
90
- version = version.strip().replace(".", "_").replace("-", "_")
91
- else:
92
- version = version.strip().replace("_preview", "-preview").replace("_", ".")
93
-
94
- if drop_v:
95
- version = version.lstrip("v")
96
- elif not version.startswith("v") and version.lower() not in SET_PREVIEW:
97
- version = "v" + version
98
- if version in SET_PREVIEW:
99
- version = V_PREVIEW
100
- return version
101
-
102
-
103
- @lru_cache(maxsize=10)
104
- def micropython_versions(minver: str = "v1.20"):
105
- """Get the list of micropython versions from github tags"""
106
- try:
107
- gh_client = GH_CLIENT
108
- repo = gh_client.get_repo("micropython/micropython")
109
- versions = [tag.name for tag in repo.get_tags() if parse(tag.name) >= parse(minver)]
110
- except Exception:
111
- versions = [
112
- "v9.99.9-preview",
113
- "v1.22.2",
114
- "v1.22.1",
115
- "v1.22.0",
116
- "v1.21.1",
117
- "v1.21.0",
118
- "v1.20.0",
119
- "v1.19.1",
120
- "v1.19",
121
- "v1.18",
122
- "v1.17",
123
- "v1.16",
124
- "v1.15",
125
- "v1.14",
126
- "v1.13",
127
- "v1.12",
128
- "v1.11",
129
- "v1.10",
130
- ]
131
- versions = [v for v in versions if parse(v) >= parse(minver)]
132
- return sorted(versions)
133
-
134
-
135
- def get_stable_mp_version() -> str:
136
- # read the versions from the git tags
137
- all_versions = micropython_versions(minver="v1.17")
138
- return [v for v in all_versions if not v.endswith(V_PREVIEW)][-1]
139
-
140
-
141
- def get_preview_mp_version() -> str:
142
- # read the versions from the git tags
143
- all_versions = micropython_versions(minver="v1.17")
144
- return [v for v in all_versions if v.endswith(V_PREVIEW)][-1]
145
-
146
-
147
- #############################################################
148
- def wait_for_restart(mcu: MPRemoteBoard, timeout: int = 10):
149
- """wait for the board to restart"""
150
- for _ in track(
151
- range(timeout),
152
- description="Waiting for the board to restart",
153
- transient=True,
154
- get_time=lambda: time.time(),
155
- show_speed=False,
156
- ):
157
- time.sleep(1)
158
- try:
159
- mcu.get_mcu_info()
160
- break
161
- except ConnectionError:
162
- pass
mpflash/download.py CHANGED
@@ -46,6 +46,9 @@ def get_board_urls(page_url: str) -> List[Dict[str, str]]:
46
46
  """
47
47
  Get the urls to all the board pages listed on this page.
48
48
  Assumes that all links to firmware have "class": "board-card"
49
+
50
+ Args:
51
+ page_url (str): The url of the page to get the board urls from.
49
52
  """
50
53
  downloads_html = get_page(page_url)
51
54
  soup = BeautifulSoup(downloads_html, "html.parser")
@@ -57,8 +60,17 @@ def get_board_urls(page_url: str) -> List[Dict[str, str]]:
57
60
  return [{"board": board, "url": page_url + board} for board in boards]
58
61
 
59
62
 
60
- def firmware_list(board_url: str, base_url: str, ext: str) -> List[str]:
61
- """Get the urls to all the firmware files for a board."""
63
+ def board_firmware_urls(board_url: str, base_url: str, ext: str) -> List[str]:
64
+ """
65
+ Get the urls to all the firmware files for a board.
66
+ Args:
67
+ page_url (str): The url of the page to get the board urls from.
68
+ ??? base_url (str): The base url to join the relative urls to.
69
+ ext (str): The extension of the firmware files to get. (with or withouth leading .)
70
+
71
+ the urls are relative urls to the site root
72
+
73
+ """
62
74
  html = get_page(board_url)
63
75
  soup = BeautifulSoup(html, "html.parser")
64
76
  # get all the a tags:
@@ -109,7 +121,7 @@ def get_boards(ports: List[str], boards: List[str], clean: bool) -> List[Firmwar
109
121
  # add a board to the list for each firmware found
110
122
  firmwares = []
111
123
  for ext in PORT_FWTYPES[port]:
112
- firmwares += firmware_list(board["url"], MICROPYTHON_ORG_URL, ext)
124
+ firmwares += board_firmware_urls(board["url"], MICROPYTHON_ORG_URL, ext)
113
125
 
114
126
  for _url in firmwares:
115
127
  board["firmware"] = _url
mpflash/downloaded.py ADDED
@@ -0,0 +1,108 @@
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 FWInfo
8
+ from mpflash.vendor.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.extend(iter(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 find_downloaded_firmware(
28
+ *,
29
+ board_id: str,
30
+ version: str = "",
31
+ port: str = "",
32
+ variants: bool = False,
33
+ fw_folder: Optional[Path] = None,
34
+ trie: int = 1,
35
+ selector: Optional[Dict[str, str]] = None,
36
+ ) -> List[FWInfo]:
37
+ if selector is None:
38
+ selector = {}
39
+ fw_folder = fw_folder or config.firmware_folder
40
+ # Use the information in firmwares.jsonl to find the firmware file
41
+ fw_list = downloaded_firmwares(fw_folder)
42
+ if not fw_list:
43
+ log.error("No firmware files found. Please download the firmware first.")
44
+ return []
45
+ # filter by version
46
+ version = clean_version(version, drop_v=True)
47
+ fw_list = filter_downloaded_fwlist(fw_list, board_id, version, port, variants, selector)
48
+
49
+ if not fw_list and trie < 3:
50
+ log.info(f"Try ({trie+1}) to find a firmware for the board {board_id}")
51
+ if trie == 1:
52
+ # ESP board naming conventions have changed by adding a PORT refix
53
+ if port.startswith("esp") and not board_id.startswith(port.upper()):
54
+ board_id = f"{port.upper()}_{board_id}"
55
+ # RP2 board naming conventions have changed by adding a _RPIprefix
56
+ if port == "rp2" and not board_id.startswith("RPI_"):
57
+ board_id = f"RPI_{board_id}"
58
+ elif trie == 2:
59
+ board_id = board_id.replace("_", "-")
60
+
61
+ fw_list = find_downloaded_firmware(
62
+ fw_folder=fw_folder,
63
+ board_id=board_id,
64
+ version=version,
65
+ port=port,
66
+ trie=trie + 1,
67
+ selector=selector,
68
+ )
69
+ # hope we have a match now for the board
70
+ # sort by filename
71
+ fw_list.sort(key=lambda x: x["filename"])
72
+ return fw_list
73
+
74
+
75
+ def filter_downloaded_fwlist(
76
+ fw_list: List[FWInfo],
77
+ board_id: str,
78
+ version: str,
79
+ port: str,
80
+ # preview: bool,
81
+ variants: bool,
82
+ selector: dict,
83
+ ) -> List[FWInfo]:
84
+ """Filter the downloaded firmware list based on the provided parameters"""
85
+ if "preview" in version:
86
+ # never get a preview for an older version
87
+ fw_list = [fw for fw in fw_list if fw["preview"]]
88
+ else:
89
+ fw_list = [fw for fw in fw_list if fw["version"] == version]
90
+
91
+ # filter by port
92
+ if port:
93
+ fw_list = [fw for fw in fw_list if fw["port"] == port]
94
+
95
+ if board_id:
96
+ if variants:
97
+ # any variant of this board_id
98
+ fw_list = [fw for fw in fw_list if fw["board"] == board_id]
99
+ else:
100
+ # the firmware variant should match exactly the board_id
101
+ fw_list = [fw for fw in fw_list if fw["variant"] == board_id]
102
+ if selector and port in selector:
103
+ fw_list = [fw for fw in fw_list if fw["filename"].endswith(selector[port])]
104
+ return fw_list
105
+
106
+
107
+ # #########################################################################################################
108
+ #
mpflash/errors.py ADDED
@@ -0,0 +1,5 @@
1
+ """Custom exceptions for the MPFlash package."""
2
+
3
+
4
+ class MPFlashError(Exception):
5
+ pass
mpflash/flash.py CHANGED
@@ -1,150 +1,55 @@
1
1
  import time
2
2
  from pathlib import Path
3
- from typing import Dict, List, Optional, Tuple
4
3
 
5
- import jsonlines
6
4
  from loguru import logger as log
7
5
 
6
+ from mpflash.common import PORT_FWTYPES
8
7
  from mpflash.mpremoteboard import MPRemoteBoard
9
8
 
10
- from .common import FWInfo, clean_version
11
- from .config import config
9
+ from .flash_esp import flash_esp
10
+ from .flash_stm32 import flash_stm32
11
+ from .flash_uf2 import flash_uf2
12
+ from .worklist import WorkList
12
13
 
13
14
  # #########################################################################################################
14
- WorkList = List[Tuple[MPRemoteBoard, FWInfo]]
15
15
 
16
16
 
17
- # #########################################################################################################
18
- def local_firmwares(fw_folder: Path) -> List[FWInfo]:
19
- """Load a list of locally available firmwares from the jsonl file"""
20
- firmwares: List[FWInfo] = []
21
- try:
22
- with jsonlines.open(fw_folder / "firmware.jsonl") as reader:
23
- firmwares.extend(iter(reader))
24
- except FileNotFoundError:
25
- log.error(f"No firmware.jsonl found in {fw_folder}")
26
- # sort by filename
27
- firmwares.sort(key=lambda x: x["filename"])
28
- return firmwares
29
-
30
-
31
- def find_firmware(
32
- *,
33
- board: str,
34
- version: str = "",
35
- port: str = "",
36
- variants: bool = False,
37
- fw_folder: Optional[Path] = None,
38
- trie: int = 1,
39
- selector: Optional[Dict[str, str]] = None,
40
- ) -> List[FWInfo]:
41
- if selector is None:
42
- selector = {}
43
- fw_folder = fw_folder or config.firmware_folder
44
- # Use the information in firmwares.jsonl to find the firmware file
45
- fw_list = local_firmwares(fw_folder)
46
- if not fw_list:
47
- log.error("No firmware files found. Please download the firmware first.")
48
- return []
49
- # filter by version
50
- version = clean_version(version, drop_v=True)
51
- fw_list = filter_fwlist(fw_list, board, version, port, variants, selector)
52
-
53
- if not fw_list and trie < 2:
54
- board_id = board.replace("_", "-")
55
- # ESP board naming conventions have changed by adding a PORT refix
56
- if port.startswith("esp") and not board_id.startswith(port.upper()):
57
- board_id = f"{port.upper()}_{board_id}"
58
- # RP2 board naming conventions have changed by adding a _RPIprefix
59
- if port == "rp2" and not board_id.startswith("RPI_"):
60
- board_id = f"RPI_{board_id}"
61
-
62
- log.info(f"Try ({trie}) to find a firmware for the board {board_id}")
63
- fw_list = find_firmware(
64
- fw_folder=fw_folder,
65
- board=board_id,
66
- version=version,
67
- port=port,
68
- trie=trie + 1,
69
- selector=selector,
70
- )
71
- # hope we have a match now for the board
72
- # sort by filename
73
- fw_list.sort(key=lambda x: x["filename"])
74
- return fw_list
75
-
76
-
77
- def filter_fwlist(
78
- fw_list: List[FWInfo],
79
- board: str,
80
- version: str,
81
- port: str,
82
- # preview: bool,
83
- variants: bool,
84
- selector: dict,
85
- ) -> List[FWInfo]:
86
- """Filter the firmware list based on the provided parameters"""
87
- if "preview" in version:
88
- # never get a preview for an older version
89
- fw_list = [fw for fw in fw_list if fw["preview"]]
90
- else:
91
- fw_list = [fw for fw in fw_list if fw["version"] == version]
92
-
93
- # filter by port
94
- if port:
95
- fw_list = [fw for fw in fw_list if fw["port"] == port]
96
-
97
- if board:
98
- if variants:
99
- fw_list = [fw for fw in fw_list if fw["board"] == board]
100
- else:
101
- # the variant should match exactly the board name
102
- fw_list = [fw for fw in fw_list if fw["variant"] == board]
103
- if selector and port in selector:
104
- fw_list = [fw for fw in fw_list if fw["filename"].endswith(selector[port])]
105
- return fw_list
106
-
107
-
108
- # #########################################################################################################
109
- #
110
-
111
-
112
- def auto_update(
113
- conn_boards: List[MPRemoteBoard],
114
- target_version: str,
17
+ def flash_list(
18
+ todo: WorkList,
115
19
  fw_folder: Path,
116
- *,
117
- selector: Optional[Dict[str, str]] = None,
118
- ) -> WorkList:
119
- """Builds a list of boards to update based on the connected boards and the firmware available"""
120
- if selector is None:
121
- selector = {}
122
- wl: WorkList = []
123
- for mcu in conn_boards:
124
- if mcu.family != "micropython":
125
- log.warning(
126
- f"Skipping {mcu.family} {mcu.port} {mcu.board} on {mcu.serialport} as it is a MicroPython firmware"
127
- )
128
- continue
129
- board_firmwares = find_firmware(
130
- fw_folder=fw_folder,
131
- board=mcu.board,
132
- version=target_version,
133
- port=mcu.port,
134
- selector=selector,
135
- )
136
-
137
- if not board_firmwares:
138
- log.error(f"No {target_version} firmware found for {mcu.board} on {mcu.serialport}.")
20
+ erase: bool,
21
+ bootloader: bool,
22
+ ):
23
+ """Flash a list of boards with the specified firmware."""
24
+ flashed = []
25
+ for mcu, fw_info in todo:
26
+ fw_file = fw_folder / fw_info["filename"] # type: ignore
27
+ if not fw_file.exists():
28
+ log.error(f"File {fw_file} does not exist, skipping {mcu.board} on {mcu.serialport}")
139
29
  continue
140
- if len(board_firmwares) > 1:
141
- log.debug(f"Multiple {target_version} firmwares found for {mcu.board} on {mcu.serialport}.")
30
+ log.info(f"Updating {mcu.board} on {mcu.serialport} to {fw_info['version']}")
31
+ updated = None
32
+ # try:
33
+ if mcu.port in [port for port, exts in PORT_FWTYPES.items() if ".uf2" in exts] and fw_file.suffix == ".uf2":
34
+ # any .uf2 port ["samd", "rp2", "nrf"]:
35
+ if bootloader:
36
+ enter_bootloader(mcu)
37
+ updated = flash_uf2(mcu, fw_file=fw_file, erase=erase)
38
+ elif mcu.port in ["stm32"]:
39
+ if bootloader:
40
+ enter_bootloader(mcu)
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}")
142
47
 
143
- # just use the last firmware
144
- fw_info = board_firmwares[-1]
145
- log.info(f"Found {target_version} firmware {fw_info['filename']} for {mcu.board} on {mcu.serialport}.")
146
- wl.append((mcu, fw_info))
147
- return wl
48
+ if updated:
49
+ flashed.append(updated)
50
+ else:
51
+ log.error(f"Failed to flash {mcu.board} on {mcu.serialport}")
52
+ return flashed
148
53
 
149
54
 
150
55
  def enter_bootloader(mcu: MPRemoteBoard, timeout: int = 10, wait_after: int = 2):
mpflash/flash_esp.py CHANGED
@@ -10,11 +10,9 @@ from typing import List, Optional
10
10
  import esptool
11
11
  from loguru import logger as log
12
12
 
13
- from mpflash.mpboard_id.api import find_mp_board
13
+ from mpflash.mpboard_id import find_stored_board
14
14
  from mpflash.mpremoteboard import MPRemoteBoard
15
15
 
16
- from .common import wait_for_restart
17
-
18
16
 
19
17
  def flash_esp(mcu: MPRemoteBoard, fw_file: Path, *, erase: bool = True) -> Optional[MPRemoteBoard]:
20
18
  if mcu.port not in ["esp32", "esp8266"] or mcu.board in ["ARDUINO_NANO_ESP32"]:
@@ -24,27 +22,24 @@ def flash_esp(mcu: MPRemoteBoard, fw_file: Path, *, erase: bool = True) -> Optio
24
22
  log.info(f"Flashing {fw_file} on {mcu.board} on {mcu.serialport}")
25
23
  if not mcu.cpu:
26
24
  # Lookup CPU based on the board name
27
- mcu.cpu = find_mp_board(mcu.board)["cpu"]
25
+ mcu.cpu = find_stored_board(mcu.board)["cpu"]
28
26
 
29
- if mcu.port == "esp8266":
30
- baud_rate = str(460_800)
31
- else:
32
- baud_rate = str(512_000)
33
- # baud_rate = str(115_200)
34
27
  cmds: List[List[str]] = []
35
28
  if erase:
36
29
  cmds.append(f"esptool --chip {mcu.cpu} --port {mcu.serialport} erase_flash".split())
37
30
 
38
- if mcu.cpu.upper() in ("ESP32", "ESP32S2"):
39
- start_addr = "0x1000"
40
- elif mcu.cpu.upper() in ("ESP32S3", "ESP32C3"):
41
- start_addr = "0x0"
42
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"
43
37
  cmds.append(
44
38
  f"esptool --chip {mcu.cpu} --port {mcu.serialport} -b {baud_rate} write_flash --compress {start_addr}".split()
45
39
  + [str(fw_file)]
46
40
  )
47
41
  elif mcu.cpu.upper() == "ESP8266":
42
+ baud_rate = str(460_800)
48
43
  start_addr = "0x0"
49
44
  cmds.append(
50
45
  f"esptool --chip {mcu.cpu} --port {mcu.serialport} -b {baud_rate} write_flash --flash_size=detect {start_addr}".split()
@@ -59,6 +54,6 @@ def flash_esp(mcu: MPRemoteBoard, fw_file: Path, *, erase: bool = True) -> Optio
59
54
  return None
60
55
 
61
56
  log.info("Done flashing, resetting the board and wait for it to restart")
62
- wait_for_restart(mcu)
63
- log.success(f"Flashed {mcu.version} to {mcu.board}")
57
+ mcu.wait_for_restart()
58
+ log.success(f"Flashed {mcu.serialport} to {mcu.board} {mcu.version}")
64
59
  return mcu
mpflash/flash_stm32.py CHANGED
@@ -4,8 +4,6 @@ from pathlib import Path
4
4
 
5
5
  from loguru import logger as log
6
6
 
7
- from mpflash.common import wait_for_restart
8
-
9
7
  # from .flash_stm32_cube import flash_stm32_cubecli
10
8
  from .flash_stm32_dfu import dfu_init, flash_stm32_dfu
11
9
  from mpflash.mpremoteboard import MPRemoteBoard
@@ -21,6 +19,6 @@ def flash_stm32(mcu: MPRemoteBoard, fw_file: Path, *, erase: bool, stm32_dfu: bo
21
19
  # log.info("Using STM32CubeProgrammer CLI")
22
20
  # updated = flash_stm32_cubecli(mcu, fw_file=fw_file, erase=erase)
23
21
 
24
- wait_for_restart(mcu)
22
+ mcu.wait_for_restart()
25
23
  log.success(f"Flashed {mcu.version} to {mcu.board}")
26
24
  return updated
@@ -16,7 +16,6 @@
16
16
  # from rich.progress import track
17
17
  # from strip_ansi import strip_ansi
18
18
 
19
- # from .common import wait_for_restart
20
19
  # from .mpremoteboard.mpremoteboard import MPRemoteBoard
21
20
 
22
21
  # STM32_CLI_WIN = "C:\\Program Files\\STMicroelectronics\\STM32Cube\\STM32CubeProgrammer\\bin\\STM32_Programmer_CLI.exe"
@@ -8,7 +8,12 @@ from mpflash.mpremoteboard import MPRemoteBoard
8
8
 
9
9
 
10
10
  def init_libusb_windows() -> bool:
11
- # on windows we need to initialze the libusb backend with the correct dll
11
+ """
12
+ Initializes the libusb backend on Windows.
13
+
14
+ Returns:
15
+ bool: True if the initialization is successful, False otherwise.
16
+ """
12
17
  import libusb # type: ignore
13
18
  import usb.backend.libusb1 as libusb1
14
19
 
@@ -21,12 +26,15 @@ def init_libusb_windows() -> bool:
21
26
 
22
27
 
23
28
  try:
24
- from .vendored import pydfu as pydfu
29
+ from .vendor import pydfu as pydfu
25
30
  except ImportError:
26
31
  pydfu = None
27
32
 
28
33
 
29
34
  def dfu_init():
35
+ """
36
+ Initializes the DFU (Device Firmware Upgrade) process.
37
+ """
30
38
  if not pydfu:
31
39
  log.error("pydfu not found")
32
40
  return None
@@ -40,11 +48,17 @@ def flash_stm32_dfu(
40
48
  *,
41
49
  erase: bool = True,
42
50
  ) -> Optional[MPRemoteBoard]:
51
+ """
52
+ Flashes the STM32 microcontroller using DFU (Device Firmware Upgrade).
43
53
 
44
- # if sys.platform == "win32":
45
- # log.error(f"OS {sys.platform} not supported")
46
- # return None
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.
47
58
 
59
+ Returns:
60
+ Optional[MPRemoteBoard]: The flashed remote board if successful, None otherwise.
61
+ """
48
62
  if not pydfu:
49
63
  log.error("pydfu not found, please install it with 'pip install pydfu' if supported")
50
64
  return None
mpflash/flash_uf2.py CHANGED
@@ -56,6 +56,6 @@ def flash_uf2(mcu: MPRemoteBoard, fw_file: Path, erase: bool) -> Optional[MPRemo
56
56
  log.success("Done copying, resetting the board and wait for it to restart")
57
57
  if sys.platform in ["linux", "darwin"]:
58
58
  dismount_uf2()
59
- for _ in track(range(5 + 2)):
59
+ for _ in track(range(5 + 2), description="Waiting for the board to restart", transient=True):
60
60
  time.sleep(1) # 5 secs to short on linux
61
61
  return mcu