mpflash 0.8.8__py3-none-any.whl → 0.9.1__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.
Files changed (43) hide show
  1. mpflash/add_firmware.py +1 -1
  2. mpflash/ask_input.py +1 -1
  3. mpflash/bootloader/__init__.py +2 -37
  4. mpflash/bootloader/activate.py +60 -0
  5. mpflash/bootloader/detect.py +82 -0
  6. mpflash/bootloader/manual.py +10 -11
  7. mpflash/bootloader/micropython.py +2 -0
  8. mpflash/bootloader/touch1200.py +13 -22
  9. mpflash/cli_download.py +1 -1
  10. mpflash/cli_flash.py +3 -3
  11. mpflash/cli_group.py +18 -5
  12. mpflash/cli_main.py +3 -5
  13. mpflash/common.py +1 -0
  14. mpflash/config.py +6 -9
  15. mpflash/connected.py +9 -5
  16. mpflash/download.py +9 -5
  17. mpflash/downloaded.py +1 -1
  18. mpflash/{flash.py → flash/__init__.py} +20 -17
  19. mpflash/{flash_esp.py → flash/esp.py} +1 -1
  20. mpflash/flash/stm32.py +19 -0
  21. mpflash/{flash_stm32_dfu.py → flash/stm32_dfu.py} +1 -1
  22. mpflash/{flash_uf2.py → flash/uf2/__init__.py} +44 -23
  23. mpflash/{flash_uf2_linux.py → flash/uf2/linux.py} +15 -8
  24. mpflash/{flash_uf2_macos.py → flash/uf2/macos.py} +13 -5
  25. mpflash/{flash_uf2_windows.py → flash/uf2/windows.py} +16 -7
  26. mpflash/{worklist.py → flash/worklist.py} +7 -5
  27. mpflash/list.py +13 -3
  28. mpflash/mpboard_id/__init__.py +1 -1
  29. mpflash/mpboard_id/add_boards.py +2 -2
  30. mpflash/mpboard_id/board_id.py +1 -1
  31. mpflash/mpremoteboard/__init__.py +5 -4
  32. mpflash/{vendor/versions.py → versions.py} +10 -5
  33. {mpflash-0.8.8.dist-info → mpflash-0.9.1.dist-info}/METADATA +16 -5
  34. mpflash-0.9.1.dist-info/RECORD +52 -0
  35. mpflash/flash_stm32.py +0 -23
  36. mpflash/flash_stm32_cube.py +0 -111
  37. mpflash/vendor/basicgit.py +0 -288
  38. mpflash-0.8.8.dist-info/RECORD +0 -52
  39. /mpflash/{flash_uf2_boardid.py → flash/uf2/boardid.py} +0 -0
  40. /mpflash/{uf2disk.py → flash/uf2/uf2disk.py} +0 -0
  41. {mpflash-0.8.8.dist-info → mpflash-0.9.1.dist-info}/LICENSE +0 -0
  42. {mpflash-0.8.8.dist-info → mpflash-0.9.1.dist-info}/WHEEL +0 -0
  43. {mpflash-0.8.8.dist-info → mpflash-0.9.1.dist-info}/entry_points.txt +0 -0
@@ -4,20 +4,21 @@ Flash SAMD and RP2 via UF2
4
4
 
5
5
  import shutil
6
6
  import sys
7
- import time
8
7
  from pathlib import Path
9
8
  from typing import Optional
10
9
 
10
+ import tenacity
11
11
  from loguru import logger as log
12
- from rich.progress import track
12
+
13
+ from tenacity import stop_after_attempt, wait_fixed
13
14
 
14
15
  from mpflash.mpremoteboard import MPRemoteBoard
15
16
 
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
17
+ from mpflash.common import PORT_FWTYPES
18
+ from .boardid import get_board_id
19
+ from .linux import dismount_uf2_linux, wait_for_UF2_linux
20
+ from .macos import wait_for_UF2_macos
21
+ from .windows import wait_for_UF2_windows
21
22
 
22
23
 
23
24
  def flash_uf2(mcu: MPRemoteBoard, fw_file: Path, erase: bool) -> Optional[MPRemoteBoard]:
@@ -37,18 +38,9 @@ def flash_uf2(mcu: MPRemoteBoard, fw_file: Path, erase: bool) -> Optional[MPRemo
37
38
  log.error(f"UF2 not supported on {mcu.board} on {mcu.serialport}")
38
39
  return None
39
40
  if erase:
40
- log.info("Erasing not yet implemented for UF2 flashing.")
41
+ log.warning("Erase not (yet) supported on .UF2, skipping erase.")
41
42
 
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
43
+ destination = waitfor_uf2(board_id=mcu.port.upper())
52
44
 
53
45
  if not destination or not destination.exists() or not (destination / "INFO_UF2.TXT").exists():
54
46
  log.error("Board is not in bootloader mode")
@@ -57,11 +49,40 @@ def flash_uf2(mcu: MPRemoteBoard, fw_file: Path, erase: bool) -> Optional[MPRemo
57
49
  log.info("Board is in bootloader mode")
58
50
  board_id = get_board_id(destination) # type: ignore
59
51
  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")
52
+ try:
53
+ copy_firmware_to_uf2(fw_file, destination)
54
+ log.success("Done copying, resetting the board.")
55
+ except tenacity.RetryError:
56
+ log.error("Failed to copy the firmware file to the board.")
57
+ return None
58
+
63
59
  if sys.platform in ["linux"]:
64
60
  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
61
+
62
+ mcu.wait_for_restart()
67
63
  return mcu
64
+
65
+
66
+ def waitfor_uf2(board_id: str):
67
+ """
68
+ Wait for the UF2 drive to mount
69
+ """
70
+ if sys.platform == "linux":
71
+ return wait_for_UF2_linux(board_id=board_id)
72
+ elif sys.platform == "win32":
73
+ return wait_for_UF2_windows(board_id=board_id)
74
+ elif sys.platform == "darwin":
75
+ return wait_for_UF2_macos(board_id=board_id)
76
+ else:
77
+ log.warning(f"OS {sys.platform} not tested/supported")
78
+ return None
79
+
80
+
81
+ @tenacity.retry(stop=stop_after_attempt(3), wait=wait_fixed(1), reraise=False)
82
+ def copy_firmware_to_uf2(fw_file: Path, destination: Path):
83
+ """
84
+ Copy the firmware file to the destination,
85
+ Retry 3 times with 1s delay
86
+ """
87
+ log.info(f"Copying {fw_file} to {destination}.")
88
+ return shutil.copy(fw_file, destination)
@@ -12,7 +12,7 @@ from typing import List
12
12
  from loguru import logger as log
13
13
  from rich.progress import track
14
14
 
15
- from .flash_uf2_boardid import get_board_id
15
+ from .boardid import get_board_id
16
16
  from .uf2disk import UF2Disk
17
17
 
18
18
  glb_dismount_me: List[UF2Disk] = []
@@ -70,7 +70,7 @@ def pmount(disk: UF2Disk):
70
70
  log.debug(f"Mounted {disk.label} at {disk.mountpoint}")
71
71
  glb_dismount_me.append(disk)
72
72
  else:
73
- log.debug(f"\n{disk.label} already mounted at {disk.mountpoint}")
73
+ log.trace(f"\n{disk.label} already mounted at {disk.mountpoint}")
74
74
 
75
75
 
76
76
  def pumount(disk: UF2Disk):
@@ -95,24 +95,31 @@ def dismount_uf2_linux():
95
95
  glb_dismount_me = []
96
96
 
97
97
 
98
- def wait_for_UF2_linux(s_max: int = 10):
98
+ def wait_for_UF2_linux(board_id: str, s_max: int = 10):
99
99
  destination = ""
100
100
  wait = 10
101
101
  uf2_drives = []
102
102
  # while not destination and wait > 0:
103
103
  for _ in track(
104
- range(s_max), description="Waiting for mcu to mount as a drive", transient=True, refresh_per_second=2
104
+ range(s_max),
105
+ description=f"Waiting for mcu to mount as a drive ({s_max}s)",
106
+ transient=True,
107
+ show_speed=False,
108
+ refresh_per_second=1,
109
+ total=s_max,
105
110
  ):
106
- # log.info(f"Waiting for mcu to mount as a drive : {wait} seconds left")
107
111
  uf2_drives += list(get_uf2_drives())
108
112
  for drive in get_uf2_drives():
109
113
  pmount(drive)
110
114
  time.sleep(1)
111
115
  try:
112
116
  if Path(drive.mountpoint, "INFO_UF2.TXT").exists():
113
- board_id = get_board_id(Path(drive.mountpoint)) # type: ignore
114
- destination = Path(drive.mountpoint)
115
- break
117
+ this_board_id = get_board_id(Path(drive.mountpoint))
118
+ if not board_id or board_id.upper() in this_board_id.upper():
119
+ # is it the correct board?
120
+ destination = Path(drive.mountpoint)
121
+ break
122
+ continue
116
123
  except PermissionError:
117
124
  log.debug(f"Permission error on {drive.mountpoint}")
118
125
  continue
@@ -9,23 +9,31 @@ from typing import Optional
9
9
 
10
10
  from rich.progress import track
11
11
 
12
+ from .boardid import get_board_id
12
13
 
13
14
 
14
- def wait_for_UF2_macos(s_max: int = 10) -> Optional[Path]:
15
+ def wait_for_UF2_macos(board_id: str, s_max: int = 10) -> Optional[Path]:
15
16
  """Wait for the MCU to mount as a drive"""
16
17
  if s_max < 1:
17
18
  s_max = 10
18
19
  destination = None
19
20
  for _ in track(
20
- range(s_max), description="Waiting for mcu to mount as a drive", transient=True, refresh_per_second=2
21
+ range(s_max),
22
+ description=f"Waiting for mcu to mount as a drive ({s_max}s)",
23
+ transient=True,
24
+ show_speed=False,
25
+ refresh_per_second=1,
26
+ total=s_max,
21
27
  ):
22
- # log.info(f"Waiting for mcu to mount as a drive : {n} seconds left")
23
28
  vol_mounts = Path("/Volumes").iterdir()
24
29
  for vol in vol_mounts:
25
30
  try:
26
31
  if Path(vol, "INFO_UF2.TXT").exists():
27
- destination = Path(vol)
28
- break
32
+ this_board_id = get_board_id(Path(vol))
33
+ if not board_id or board_id.upper() in this_board_id.upper():
34
+ destination = Path(vol)
35
+ break
36
+ continue
29
37
  except OSError:
30
38
  pass
31
39
  if destination:
@@ -7,25 +7,34 @@ import time
7
7
  from pathlib import Path
8
8
  from typing import Optional
9
9
 
10
+ from .boardid import get_board_id
10
11
  import psutil
11
12
  from rich.progress import track
12
13
 
13
14
 
14
-
15
-
16
- def wait_for_UF2_windows(s_max: int = 10) -> Optional[Path]:
15
+ def wait_for_UF2_windows(board_id: str, s_max: int = 10)-> Optional[Path]:
17
16
  """Wait for the MCU to mount as a drive"""
18
17
  if s_max < 1:
19
18
  s_max = 10
20
19
  destination = None
21
- for _ in track(range(s_max), description="Waiting for mcu to mount as a drive", transient=True,refresh_per_second=2):
22
- # log.info(f"Waiting for mcu to mount as a drive : {n} seconds left")
20
+ for _ in track(
21
+ range(s_max),
22
+ description=f"Waiting for mcu to mount as a drive ({s_max}s)",
23
+ transient=True,
24
+ show_speed=False,
25
+ refresh_per_second=1,
26
+ total=s_max,
27
+ ):
23
28
  drives = [drive.device for drive in psutil.disk_partitions()]
24
29
  for drive in drives:
25
30
  try:
26
31
  if Path(drive, "INFO_UF2.TXT").exists():
27
- destination = Path(drive)
28
- break
32
+ this_board_id = get_board_id(Path(drive))
33
+ if not board_id or board_id.upper() in this_board_id.upper():
34
+ # is it the correct board?
35
+ destination = Path(drive)
36
+ break
37
+ continue
29
38
  except OSError:
30
39
  pass
31
40
  if destination:
@@ -1,15 +1,17 @@
1
+ """Worklist for updating boards"""
2
+
1
3
  from pathlib import Path
2
4
  from typing import Dict, List, Optional, Tuple
3
5
 
4
6
  from loguru import logger as log
5
7
 
6
- from mpflash.common import FWInfo, filtered_comports, PORT_FWTYPES
8
+ from mpflash.common import FWInfo, filtered_comports
7
9
  from mpflash.errors import MPFlashError
8
10
 
9
- from .downloaded import find_downloaded_firmware
10
- from .list import show_mcus
11
- from .mpboard_id import find_known_board
12
- from .mpremoteboard import MPRemoteBoard
11
+ from ..downloaded import find_downloaded_firmware
12
+ from ..list import show_mcus
13
+ from ..mpboard_id import find_known_board
14
+ from ..mpremoteboard import MPRemoteBoard
13
15
 
14
16
  # #########################################################################################################
15
17
  WorkList = List[Tuple[MPRemoteBoard, FWInfo]]
mpflash/list.py CHANGED
@@ -3,8 +3,9 @@ from typing import List
3
3
  from rich.progress import track
4
4
  from rich.table import Table
5
5
 
6
+ from mpflash.config import config
6
7
  from mpflash.mpremoteboard import MPRemoteBoard
7
- from mpflash.vendor.versions import clean_version
8
+ from mpflash.versions import clean_version
8
9
 
9
10
  from .logger import console
10
11
 
@@ -64,8 +65,15 @@ def mcu_table(
64
65
  table.add_column("Version", overflow="fold", min_width=5, max_width=16)
65
66
  if needs_build:
66
67
  table.add_column("Build" if is_wide else "Bld", justify="right")
67
-
68
- for mcu in track(conn_mcus, description="Updating board info", transient=True, refresh_per_second=2):
68
+ if config.usb:
69
+ table.add_column("Location", overflow="fold", max_width=40)
70
+ for mcu in track(
71
+ conn_mcus,
72
+ description="Updating board info",
73
+ transient=True,
74
+ show_speed=False,
75
+ refresh_per_second=1,
76
+ ):
69
77
  if refresh:
70
78
  try:
71
79
  mcu.get_mcu_info()
@@ -84,6 +92,8 @@ def mcu_table(
84
92
  row.append(clean_version(mcu.version))
85
93
  if needs_build:
86
94
  row.append(mcu.build)
95
+ if config.usb:
96
+ row.append(mcu.location)
87
97
 
88
98
  table.add_row(*row)
89
99
  return table
@@ -10,7 +10,7 @@ from typing import List, Optional, Tuple
10
10
  from mpflash.errors import MPFlashError
11
11
  from mpflash.mpboard_id.board import Board
12
12
  from mpflash.mpboard_id.store import read_known_boardinfo
13
- from mpflash.vendor.versions import clean_version
13
+ from mpflash.versions import clean_version
14
14
 
15
15
  # KNOWN ports and boards are sourced from the micropython repo,
16
16
  # this info is stored in the board_info.json file
@@ -12,11 +12,11 @@ import rich.table
12
12
  from rich.console import Console
13
13
  from rich.progress import track
14
14
 
15
- import mpflash.vendor.basicgit as git
15
+ import basicgit as git
16
16
  from mpflash.logger import log
17
17
  from mpflash.mpboard_id import Board
18
18
  from mpflash.mpboard_id.store import write_boardinfo_json
19
- from mpflash.vendor.versions import micropython_versions
19
+ from mpflash.versions import micropython_versions
20
20
 
21
21
  # look for all mpconfigboard.h files and extract the board name
22
22
  # from the #define MICROPY_HW_BOARD_NAME "PYBD_SF6"
@@ -9,7 +9,7 @@ from typing import Optional
9
9
  from mpflash.errors import MPFlashError
10
10
  from mpflash.logger import log
11
11
  from mpflash.mpboard_id.store import read_known_boardinfo
12
- from mpflash.vendor.versions import clean_version, get_stable_mp_version
12
+ from mpflash.versions import clean_version, get_stable_mp_version
13
13
 
14
14
 
15
15
  def find_board_id_by_description(
@@ -29,7 +29,7 @@ RETRIES = 3
29
29
  class MPRemoteBoard:
30
30
  """Class to run mpremote commands"""
31
31
 
32
- def __init__(self, serialport: str = "", update: bool = False):
32
+ def __init__(self, serialport: str = "", update: bool = False, *, location: str = ""):
33
33
  """
34
34
  Initialize MPRemoteBoard object.
35
35
 
@@ -37,7 +37,7 @@ class MPRemoteBoard:
37
37
  - serialport (str): The serial port to connect to. Default is an empty string.
38
38
  - update (bool): Whether to update the MCU information. Default is False.
39
39
  """
40
- self.serialport = serialport
40
+ self.serialport: str = serialport
41
41
  self.firmware = {}
42
42
 
43
43
  self.connected = False
@@ -51,6 +51,7 @@ class MPRemoteBoard:
51
51
  self.arch = ""
52
52
  self.mpy = ""
53
53
  self.build = ""
54
+ self.location = location
54
55
  if update:
55
56
  self.get_mcu_info()
56
57
 
@@ -207,11 +208,11 @@ class MPRemoteBoard:
207
208
  """wait for the board to restart"""
208
209
  for _ in track(
209
210
  range(timeout),
210
- description="Waiting for the board to restart",
211
+ description=f"Waiting for the board to restart ({timeout}s)",
211
212
  transient=True,
212
- get_time=lambda: time.time(),
213
213
  show_speed=False,
214
214
  refresh_per_second=1,
215
+ total=timeout,
215
216
  ):
216
217
  time.sleep(1)
217
218
  try:
@@ -4,12 +4,12 @@
4
4
  #############################################################
5
5
  """
6
6
 
7
- from functools import lru_cache
8
-
7
+ from cache_to_disk import cache_to_disk, NoCacheCondition
9
8
  from loguru import logger as log
10
9
  from packaging.version import parse
11
10
 
12
11
  from mpflash.common import GH_CLIENT
12
+
13
13
  OLDEST_VERSION = "1.16"
14
14
  "This is the oldest MicroPython version to build the stubs on"
15
15
 
@@ -70,9 +70,10 @@ def clean_version(
70
70
  return version
71
71
 
72
72
 
73
- @lru_cache(maxsize=10)
73
+ @cache_to_disk(n_days_to_cache=1)
74
74
  def micropython_versions(minver: str = "v1.20", reverse: bool = False):
75
75
  """Get the list of micropython versions from github tags"""
76
+ cache_it = True
76
77
  try:
77
78
  gh_client = GH_CLIENT
78
79
  repo = gh_client.get_repo("micropython/micropython")
@@ -100,10 +101,15 @@ def micropython_versions(minver: str = "v1.20", reverse: bool = False):
100
101
  "v1.11",
101
102
  "v1.10",
102
103
  ]
104
+ cache_it = False
103
105
  versions = [v for v in versions if parse(v) >= parse(minver)]
104
106
  # remove all but the most recent (preview) version
105
107
  versions = versions[:1] + [v for v in versions if "preview" not in v]
106
- return sorted(versions, reverse=reverse)
108
+ versions = sorted(versions, reverse=reverse)
109
+ if cache_it:
110
+ return versions
111
+ # returns - but does not cache
112
+ raise NoCacheCondition(function_value=versions)
107
113
 
108
114
 
109
115
  def get_stable_mp_version() -> str:
@@ -116,4 +122,3 @@ def get_preview_mp_version() -> str:
116
122
  # read the versions from the git tags
117
123
  all_versions = micropython_versions(minver=OLDEST_VERSION)
118
124
  return [v for v in all_versions if v.endswith(V_PREVIEW)][-1]
119
-
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mpflash
3
- Version: 0.8.8
3
+ Version: 0.9.1
4
4
  Summary: Flash and download tool for MicroPython firmwares
5
5
  Home-page: https://github.com/Josverl/micropython-stubber/blob/main/src/mpflash/README.md
6
6
  License: MIT
@@ -20,6 +20,7 @@ Classifier: Topic :: Software Development :: Build Tools
20
20
  Requires-Dist: beautifulsoup4 (>=4.12.3,<5.0.0)
21
21
  Requires-Dist: bincopy (>=20.0.0,<21.0.0)
22
22
  Requires-Dist: blkinfo (>=0.2.0,<0.3.0)
23
+ Requires-Dist: cache-to-disk (>=2.0.0,<3.0.0)
23
24
  Requires-Dist: cachetools (>=5.3.0,<6.0.0)
24
25
  Requires-Dist: esptool (>=4.7.0,<5.0.0)
25
26
  Requires-Dist: inquirer (>=3.2.4,<4.0.0)
@@ -52,8 +53,8 @@ This tool was initially created to be used in a CI/CD pipeline to automate the p
52
53
  `mpflash` has been tested on:
53
54
  - OS: Windows x64, Linux X64, but not (yet) macOS.
54
55
  - Micropython (hardware) ports:
55
- - `rp2`, using `.uf2`, using filecopy (macos not tested yet)
56
- - `samd`, using ` .uf2`, using filecopy (macos not tested yet)
56
+ - `rp2`, using `.uf2`, using filecopy
57
+ - `samd`, using ` .uf2`, using filecopy
57
58
  - `esp32`, using `.bin`, using esptool,
58
59
  - `esp8266`, using `.bin`, using esptool
59
60
  - `stm32`, using ` .dfu`, using pydfu
@@ -66,7 +67,7 @@ Not yet implemented: `nrf`, `cc3200`, `mimxrt`
66
67
  3. Flash one or all connected MicroPython boards with a specific firmware or version.
67
68
 
68
69
  ## Installation
69
- To install mpflash, you can use pip: `pip install mpflash`
70
+ To install mpflash, you can use: `pipx install mpflash` or `pip install mpflash`
70
71
 
71
72
  ## Basic usage
72
73
  You can use mpflash to perform various operations on your MicroPython boards. Here is an example of basic usage:
@@ -110,7 +111,7 @@ To download the MicroPython firmware for some boards, use the following command:
110
111
 
111
112
  These will try to download the prebuilt MicroPython firmware for the boards from https://micropython.org/download/ and save it in your downloads folder in the `firmware` directory.
112
113
  The stable version (default) is determined based on the most recent published release,
113
- other versions are `--version preview` and `--version x.y.z` to download the latest preview or version x.y.z respectively.
114
+ other options are `--version stable`, `--version preview` and `--version x.y.z` to download the latest stable, preview or version x.y.z respectively.
114
115
 
115
116
  By default the firmware will be downloaded to your OS's preferred `Downloads/firmware` folder, but you can speciy a different directory using the `--dir` option.
116
117
 
@@ -133,8 +134,18 @@ After you have downloaded a firmware you can flash the firmware to a board usin
133
134
  This will (try to) autodetect the connected boards, and determine the correct firmware to flash to each board.
134
135
 
135
136
  - `mpflash flash` will flash the latest stable firmware to all connected boards.
137
+ If you have a board withouth a running micropython version, you will need to specify the board and the serial port to flash.
136
138
  - `mpflash flash --serial ? --board ?` will prompt to select a specific serial port and board to flash. (the firmware must be dowloaded earlier)
137
139
 
140
+ In order to flash the firmware some boards need to be put in bootloader mode, this is done automatically by mpflash where possible and supported by the boards hardware and current bootloader.
141
+ The supported `--bootloader` options are:
142
+
143
+ - `touch1200` bootloader is activated by connecting to the board at 1200 baud
144
+ - `mpy` using micropython to enter the bootloader
145
+ - `manual` manual intervention is needed to enter the bootloader
146
+ - `none` mpflash assumes the board is ready to flash
147
+
148
+ For ESP32 and ESP8266 boards the `esptool` is used to flash the firmware, and this includes activating the bootloader.
138
149
 
139
150
  ### Flashing all connected boards with the latest stable firmware
140
151
  ```bash
@@ -0,0 +1,52 @@
1
+ mpflash/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ mpflash/add_firmware.py,sha256=h-Nu9AnXO6ug2CurmgLoUVG1gNy6CA1NjwQl1nUoMZ4,3330
3
+ mpflash/ask_input.py,sha256=EsPPlPS_wLC8j9f4o68yKIcqex0dV5tRH7k3rP3spG0,8710
4
+ mpflash/bootloader/__init__.py,sha256=cRIxVRtUc4jZAgtFggRNhEn0BW-9WFpzm5xRy5B4B2U,105
5
+ mpflash/bootloader/activate.py,sha256=sN2YuIuFGjLBd_PdG6P3N1yLuLyjnsVWDksrTMhzr_M,2301
6
+ mpflash/bootloader/detect.py,sha256=eXL_JPcowb8g0tpZmj9DQXYbpfZFoSrzq86lScKhkT4,2608
7
+ mpflash/bootloader/manual.py,sha256=qGInguhYil4v8EkUxPFlxzvs3m__KraPAj3LAKbV1Ts,3069
8
+ mpflash/bootloader/micropython.py,sha256=0KDrfdZPtK7fLaxh-_4VxSO-u4IUj7qCyNVw9-LQ74M,517
9
+ mpflash/bootloader/touch1200.py,sha256=tL2H4ERh0-YSdR8_v6aK_pDRPMjMevHWUGq4-TTFcWo,1083
10
+ mpflash/cli_download.py,sha256=Ip5HViXCVAiG88XgJ3Lg_hhBGIF5DKFTNpL-_gQkdV0,3520
11
+ mpflash/cli_flash.py,sha256=KFuJRNgOZ62m70I_KqxqLfLE69b4bOCj69MOfIWdZRo,7136
12
+ mpflash/cli_group.py,sha256=JFBtp4qhakJeQkuupEoObHeSFke8eWIU1HjnOZ-JfH0,2504
13
+ mpflash/cli_list.py,sha256=AvYq5_Z7l0Z4rkbr23TwFNzstuZsQgopFpdcrTLwUvs,1965
14
+ mpflash/cli_main.py,sha256=cElgh8Soq3U5TEAvrrD1sj7NDi-Eb-pei3QcMI0tlwE,1094
15
+ mpflash/common.py,sha256=h4pVuOpopn5oIy5NQdbggtOOktTL_c92cS_oUfPG4v8,5783
16
+ mpflash/config.py,sha256=h2Oq7kSe40tOnglpo02wkpaPHxHNVqyB3uGxreIu57U,1029
17
+ mpflash/connected.py,sha256=p6RMix-tFr0pfT9TErh0LD1nm24ApTr3CqVGcrnDHk8,3024
18
+ mpflash/download.py,sha256=mckR3pdMFQMYBKNmKBEJm9bJnTtQEnkuQ1vWYXcRRv8,13941
19
+ mpflash/downloaded.py,sha256=YPN0LDf8DSDvdB9gbVny61bvaJHIDbUs81XUwftTb1c,4808
20
+ mpflash/errors.py,sha256=6lUhVtECY3syV2bBGKzegGH4pPKXhevvhYQZd74sy6o,238
21
+ mpflash/flash/__init__.py,sha256=xX2ZJGNX9xpX2s8V7SEJ1It7eOEbl8WkdFzpRd3TLzk,2041
22
+ mpflash/flash/esp.py,sha256=LcOgjpE4zmPawHNwSd_6WFkaIYYazA__rf3ihGXR7I0,2228
23
+ mpflash/flash/stm32.py,sha256=W8SJ2_8FGXyMS6cRcZpfOvOM8iOC_cn4vK8xd8tKzI4,555
24
+ mpflash/flash/stm32_dfu.py,sha256=uTn06H0ZezzCv5O0hvry8ohBtuZXHe_GX2zNUfCxu58,2986
25
+ mpflash/flash/uf2/__init__.py,sha256=PWEVxzZEca3pfLx_Qy5c4zlHH4W5fAjd0BmDTkS7s6g,2766
26
+ mpflash/flash/uf2/boardid.py,sha256=2s4K3QiKWK5HKFKWYsDV3hI8alfWSxEOMeurER3eZtM,408
27
+ mpflash/flash/uf2/linux.py,sha256=4azbcx_YqLZ3RyYNWljejHG_Y6SU-wREL8hhkTYqCjI,4099
28
+ mpflash/flash/uf2/macos.py,sha256=sncXJsc2FVfm9rvLDjcEu7ZIyrDeHmazHiNQTUaf1Y0,1187
29
+ mpflash/flash/uf2/uf2disk.py,sha256=dQ8_U6e3qkFOyfXZDpWAsvEBIlMr-ZzLkzTDD8SADqM,286
30
+ mpflash/flash/uf2/windows.py,sha256=k9Yv71YswPnLx-Z5rf4KjhtVkEWr8SU8EXpeRv87h3A,1290
31
+ mpflash/flash/worklist.py,sha256=K16sbvzJCgkHNssYlBA3ezayI02RMuIcp19XAs74XeQ,5835
32
+ mpflash/list.py,sha256=O0tX4BvclmDMnnjMxCN9Zh8hdL6vnuvS9pLNxYLBya8,3112
33
+ mpflash/logger.py,sha256=BAVrSXMGZLfSDRFbtVBtvb7Rl0sTJxooCgBS5t-6bXo,1057
34
+ mpflash/mpboard_id/__init__.py,sha256=rQrPCN30GP-lfB2a2deA-lQ6iKvaKPK_xbtBoIavGsM,3716
35
+ mpflash/mpboard_id/add_boards.py,sha256=0tP-4Ibc5_BBTQx1oBFXmKo80n31BrW6E5KrWKpP2FU,9407
36
+ mpflash/mpboard_id/board.py,sha256=yQ8IDHQS09AelvTvmPhpmsL4oX3L7IXGqHorkxDOkoE,1114
37
+ mpflash/mpboard_id/board_id.py,sha256=wzGrxJu_ciOVT7n2861lhoKmPAjh1QjWnAdfcqNUUqc,2871
38
+ mpflash/mpboard_id/board_info.zip,sha256=F6YowS96DAqjten4ySe4MXgZwPtE-saZOUfY5OQkqKk,19759
39
+ mpflash/mpboard_id/store.py,sha256=lQQgHSxcaM_ZURcfZNSUv3-ZJjUKMC_xEOOSdpzVvBU,1493
40
+ mpflash/mpremoteboard/__init__.py,sha256=7uI-5HJgNsQz_EOCW3cRy2xtqXKt9kX51gDSx6HC0Kc,7522
41
+ mpflash/mpremoteboard/mpy_fw_info.py,sha256=BTupe4rZDTs3UHRqvs429XqWHCchSpwa05yACOiOt5U,4413
42
+ mpflash/mpremoteboard/runner.py,sha256=YUmo5Y0aOgMaww8CXSdNdgXD-wRKncILuMZ0OB_2qRU,4646
43
+ mpflash/vendor/click_aliases.py,sha256=K98inhtze8td1dw312kexJS7OX_0ojlptPQ5Z0SHxJY,3065
44
+ mpflash/vendor/dfu.py,sha256=jGsiD3lbSV1Ar9qJubhoY_hy-L8FI-K55aow8vgwoYQ,5590
45
+ mpflash/vendor/pydfu.py,sha256=1ObubGsPFrQ7T9M3JRlIPNIG2xx8uYffaEe0Y6bdf_g,19937
46
+ mpflash/vendor/readme.md,sha256=ZVg7kuUYyXcWcrWkaSJ0CunwebCqu2SiS2sqDadwrT8,84
47
+ mpflash/versions.py,sha256=SrXVZx6qVWcighHlg8pJ0RPRZ3gcYN7l2DnSicconAk,4098
48
+ mpflash-0.9.1.dist-info/LICENSE,sha256=xHwgxGNkI0R2iN4KNfbPbQSzRomWyRz7bJnR1O2mln8,1057
49
+ mpflash-0.9.1.dist-info/METADATA,sha256=81r3-DTSaPrLNwLUdQDjgnFT8WJhC-awFTW1FAC6sXU,16058
50
+ mpflash-0.9.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
51
+ mpflash-0.9.1.dist-info/entry_points.txt,sha256=Jk_visOhYOsZIcSP2Ms9hKqfKy1iorR-6dYltSoWCpY,52
52
+ mpflash-0.9.1.dist-info/RECORD,,
mpflash/flash_stm32.py DELETED
@@ -1,23 +0,0 @@
1
- """Flash STM32 boards using either STM32CubeProgrammer CLI or dfu-util"""
2
-
3
- from pathlib import Path
4
-
5
- from loguru import logger as log
6
-
7
- # from .flash_stm32_cube import flash_stm32_cubecli
8
- from .flash_stm32_dfu import dfu_init, flash_stm32_dfu
9
- from mpflash.mpremoteboard import MPRemoteBoard
10
-
11
-
12
- def flash_stm32(mcu: MPRemoteBoard, fw_file: Path, *, erase: bool, stm32_dfu: bool = True):
13
- # sourcery skip: lift-return-into-if
14
- dfu_init()
15
- updated = flash_stm32_dfu(mcu, fw_file=fw_file, erase=erase)
16
- # if stm32_dfu:
17
- # else:
18
- # log.info("Using STM32CubeProgrammer CLI")
19
- # updated = flash_stm32_cubecli(mcu, fw_file=fw_file, erase=erase)
20
-
21
- mcu.wait_for_restart()
22
- log.success(f"Flashed {mcu.version} to {mcu.board}")
23
- return updated
@@ -1,111 +0,0 @@
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