mpflash 0.9.0__py3-none-any.whl → 0.9.1.post1__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 (42) hide show
  1. mpflash/add_firmware.py +1 -1
  2. mpflash/ask_input.py +1 -1
  3. mpflash/{vendor/basicgit.py → basicgit.py} +3 -7
  4. mpflash/bootloader/__init__.py +2 -37
  5. mpflash/bootloader/activate.py +60 -0
  6. mpflash/bootloader/detect.py +82 -0
  7. mpflash/bootloader/manual.py +10 -11
  8. mpflash/bootloader/micropython.py +2 -0
  9. mpflash/bootloader/touch1200.py +13 -22
  10. mpflash/cli_download.py +1 -1
  11. mpflash/cli_flash.py +3 -3
  12. mpflash/cli_group.py +18 -5
  13. mpflash/cli_main.py +3 -5
  14. mpflash/common.py +1 -0
  15. mpflash/config.py +2 -1
  16. mpflash/connected.py +9 -5
  17. mpflash/download.py +9 -5
  18. mpflash/downloaded.py +1 -1
  19. mpflash/{flash.py → flash/__init__.py} +3 -3
  20. mpflash/{flash_esp.py → flash/esp.py} +1 -1
  21. mpflash/{flash_stm32.py → flash/stm32.py} +4 -3
  22. mpflash/{flash_stm32_dfu.py → flash/stm32_dfu.py} +1 -1
  23. mpflash/{flash_uf2.py → flash/uf2/__init__.py} +19 -20
  24. mpflash/{flash_uf2_linux.py → flash/uf2/linux.py} +12 -11
  25. mpflash/{flash_uf2_macos.py → flash/uf2/macos.py} +11 -6
  26. mpflash/{flash_uf2_windows.py → flash/uf2/windows.py} +11 -6
  27. mpflash/{worklist.py → flash/worklist.py} +7 -5
  28. mpflash/list.py +13 -3
  29. mpflash/mpboard_id/__init__.py +1 -1
  30. mpflash/mpboard_id/add_boards.py +3 -7
  31. mpflash/mpboard_id/board_id.py +1 -1
  32. mpflash/mpremoteboard/__init__.py +7 -11
  33. mpflash/{vendor/versions.py → versions.py} +10 -5
  34. {mpflash-0.9.0.dist-info → mpflash-0.9.1.post1.dist-info}/METADATA +16 -5
  35. mpflash-0.9.1.post1.dist-info/RECORD +53 -0
  36. mpflash/flash_stm32_cube.py +0 -111
  37. mpflash-0.9.0.dist-info/RECORD +0 -52
  38. /mpflash/{flash_uf2_boardid.py → flash/uf2/boardid.py} +0 -0
  39. /mpflash/{uf2disk.py → flash/uf2/uf2disk.py} +0 -0
  40. {mpflash-0.9.0.dist-info → mpflash-0.9.1.post1.dist-info}/LICENSE +0 -0
  41. {mpflash-0.9.0.dist-info → mpflash-0.9.1.post1.dist-info}/WHEEL +0 -0
  42. {mpflash-0.9.0.dist-info → mpflash-0.9.1.post1.dist-info}/entry_points.txt +0 -0
@@ -4,22 +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
13
12
 
14
- from mpflash.mpremoteboard import MPRemoteBoard
15
- import tenacity
16
13
  from tenacity import stop_after_attempt, wait_fixed
17
14
 
18
- from .common import PORT_FWTYPES
19
- from .flash_uf2_boardid import get_board_id
20
- from .flash_uf2_linux import dismount_uf2_linux, wait_for_UF2_linux
21
- from .flash_uf2_macos import wait_for_UF2_macos
22
- from .flash_uf2_windows import wait_for_UF2_windows
15
+ from mpflash.mpremoteboard import MPRemoteBoard
16
+
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
23
22
 
24
23
 
25
24
  def flash_uf2(mcu: MPRemoteBoard, fw_file: Path, erase: bool) -> Optional[MPRemoteBoard]:
@@ -39,7 +38,9 @@ def flash_uf2(mcu: MPRemoteBoard, fw_file: Path, erase: bool) -> Optional[MPRemo
39
38
  log.error(f"UF2 not supported on {mcu.board} on {mcu.serialport}")
40
39
  return None
41
40
  if erase:
42
- destination = waitfor_uf2()
41
+ log.warning("Erase not (yet) supported on .UF2, skipping erase.")
42
+
43
+ destination = waitfor_uf2(board_id=mcu.port.upper())
43
44
 
44
45
  if not destination or not destination.exists() or not (destination / "INFO_UF2.TXT").exists():
45
46
  log.error("Board is not in bootloader mode")
@@ -49,8 +50,8 @@ def flash_uf2(mcu: MPRemoteBoard, fw_file: Path, erase: bool) -> Optional[MPRemo
49
50
  board_id = get_board_id(destination) # type: ignore
50
51
  log.info(f"Board ID: {board_id}")
51
52
  try:
52
- cp_firmware_to_uf2(fw_file, destination)
53
- log.success("Done copying, resetting the board and wait for it to restart")
53
+ copy_firmware_to_uf2(fw_file, destination)
54
+ log.success("Done copying, resetting the board.")
54
55
  except tenacity.RetryError:
55
56
  log.error("Failed to copy the firmware file to the board.")
56
57
  return None
@@ -59,31 +60,29 @@ def flash_uf2(mcu: MPRemoteBoard, fw_file: Path, erase: bool) -> Optional[MPRemo
59
60
  dismount_uf2_linux()
60
61
 
61
62
  mcu.wait_for_restart()
62
- # time.sleep(1) # 5 secs to short on linux
63
63
  return mcu
64
64
 
65
65
 
66
- def waitfor_uf2():
66
+ def waitfor_uf2(board_id: str):
67
67
  """
68
68
  Wait for the UF2 drive to mount
69
69
  """
70
70
  if sys.platform == "linux":
71
- return wait_for_UF2_linux()
71
+ return wait_for_UF2_linux(board_id=board_id)
72
72
  elif sys.platform == "win32":
73
- return wait_for_UF2_windows()
73
+ return wait_for_UF2_windows(board_id=board_id)
74
74
  elif sys.platform == "darwin":
75
- log.warning(f"OS {sys.platform} not tested/supported")
76
- return wait_for_UF2_macos()
75
+ return wait_for_UF2_macos(board_id=board_id)
77
76
  else:
78
77
  log.warning(f"OS {sys.platform} not tested/supported")
79
78
  return None
80
79
 
81
80
 
82
81
  @tenacity.retry(stop=stop_after_attempt(3), wait=wait_fixed(1), reraise=False)
83
- def cp_firmware_to_uf2(fw_file, destination):
82
+ def copy_firmware_to_uf2(fw_file: Path, destination: Path):
84
83
  """
85
84
  Copy the firmware file to the destination,
86
85
  Retry 3 times with 1s delay
87
86
  """
88
87
  log.info(f"Copying {fw_file} to {destination}.")
89
- shutil.copy(fw_file, 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] = []
@@ -42,10 +42,7 @@ def get_uf2_drives():
42
42
  uf2.mountpoint = uf2_part["mountpoint"]
43
43
  yield uf2
44
44
  elif disk["type"] == "disk" and disk.get("children") and len(disk.get("children")) > 0:
45
- if (
46
- disk.get("children")[0]["type"] == "part"
47
- and disk.get("children")[0]["fstype"] == "vfat"
48
- ):
45
+ if disk.get("children")[0]["type"] == "part" and disk.get("children")[0]["fstype"] == "vfat":
49
46
  uf2_part = disk.get("children")[0]
50
47
  # print( json.dumps(uf2_part, indent=4))
51
48
  uf2 = UF2Disk()
@@ -98,16 +95,17 @@ def dismount_uf2_linux():
98
95
  glb_dismount_me = []
99
96
 
100
97
 
101
- def wait_for_UF2_linux(s_max: int = 10):
98
+ def wait_for_UF2_linux(board_id: str, s_max: int = 10):
102
99
  destination = ""
103
100
  wait = 10
104
101
  uf2_drives = []
105
102
  # while not destination and wait > 0:
106
103
  for _ in track(
107
104
  range(s_max),
108
- description="Waiting for mcu to mount as a drive",
105
+ description=f"Waiting for mcu to mount as a drive ({s_max}s)",
109
106
  transient=True,
110
- refresh_per_second=2,
107
+ show_speed=False,
108
+ refresh_per_second=1,
111
109
  total=s_max,
112
110
  ):
113
111
  uf2_drives += list(get_uf2_drives())
@@ -116,9 +114,12 @@ def wait_for_UF2_linux(s_max: int = 10):
116
114
  time.sleep(1)
117
115
  try:
118
116
  if Path(drive.mountpoint, "INFO_UF2.TXT").exists():
119
- board_id = get_board_id(Path(drive.mountpoint)) # type: ignore
120
- destination = Path(drive.mountpoint)
121
- 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
122
123
  except PermissionError:
123
124
  log.debug(f"Permission error on {drive.mountpoint}")
124
125
  continue
@@ -9,26 +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
- def wait_for_UF2_macos(s_max: int = 10) -> Optional[Path]:
14
+
15
+ def wait_for_UF2_macos(board_id: str, s_max: int = 10) -> Optional[Path]:
14
16
  """Wait for the MCU to mount as a drive"""
15
17
  if s_max < 1:
16
18
  s_max = 10
17
19
  destination = None
18
20
  for _ in track(
19
21
  range(s_max),
20
- description="Waiting for mcu to mount as a drive",
22
+ description=f"Waiting for mcu to mount as a drive ({s_max}s)",
21
23
  transient=True,
22
- refresh_per_second=2,
24
+ show_speed=False,
25
+ refresh_per_second=1,
23
26
  total=s_max,
24
27
  ):
25
- # log.info(f"Waiting for mcu to mount as a drive : {n} seconds left")
26
28
  vol_mounts = Path("/Volumes").iterdir()
27
29
  for vol in vol_mounts:
28
30
  try:
29
31
  if Path(vol, "INFO_UF2.TXT").exists():
30
- destination = Path(vol)
31
- 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
32
37
  except OSError:
33
38
  pass
34
39
  if destination:
@@ -7,29 +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
- 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]:
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
21
  range(s_max),
21
- description="Waiting for mcu to mount as a drive",
22
+ description=f"Waiting for mcu to mount as a drive ({s_max}s)",
22
23
  transient=True,
23
- refresh_per_second=2,
24
+ show_speed=False,
25
+ refresh_per_second=1,
24
26
  total=s_max,
25
27
  ):
26
- # log.info(f"Waiting for mcu to mount as a drive : {n} seconds left")
27
28
  drives = [drive.device for drive in psutil.disk_partitions()]
28
29
  for drive in drives:
29
30
  try:
30
31
  if Path(drive, "INFO_UF2.TXT").exists():
31
- destination = Path(drive)
32
- 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
33
38
  except OSError:
34
39
  pass
35
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 mpflash.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"
@@ -222,11 +222,7 @@ def make_table(board_list: List[Board]) -> rich.table.Table:
222
222
 
223
223
  def ask_mpy_path():
224
224
  """Ask the user for the path to the MicroPython repository."""
225
- questions = [
226
- inquirer.Text(
227
- "mpy_path", message="Enter the path to the MicroPython repository", default=".\\repos\\micropython"
228
- )
229
- ]
225
+ questions = [inquirer.Text("mpy_path", message="Enter the path to the MicroPython repository", default=".\\repos\\micropython")]
230
226
  if answers := inquirer.prompt(questions):
231
227
  return Path(answers["mpy_path"])
232
228
  else:
@@ -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
 
@@ -91,9 +92,7 @@ class MPRemoteBoard:
91
92
 
92
93
  if sys.platform == "win32":
93
94
  # Windows sort of comports by number - but fallback to device name
94
- return sorted(
95
- output, key=lambda x: int(x.split()[0][3:]) if x.split()[0][3:].isdigit() else x
96
- )
95
+ return sorted(output, key=lambda x: int(x.split()[0][3:]) if x.split()[0][3:].isdigit() else x)
97
96
  # sort by device name
98
97
  return sorted(output)
99
98
 
@@ -129,9 +128,7 @@ class MPRemoteBoard:
129
128
  self.description = descr = info["board"]
130
129
  pos = descr.rfind(" with")
131
130
  short_descr = descr[:pos].strip() if pos != -1 else ""
132
- if board_name := find_board_id_by_description(
133
- descr, short_descr, version=self.version
134
- ):
131
+ if board_name := find_board_id_by_description(descr, short_descr, version=self.version):
135
132
  self.board = board_name
136
133
  else:
137
134
  self.board = "UNKNOWN_BOARD"
@@ -211,11 +208,10 @@ class MPRemoteBoard:
211
208
  """wait for the board to restart"""
212
209
  for _ in track(
213
210
  range(timeout),
214
- description="Waiting for the board to restart",
211
+ description=f"Waiting for the board to restart ({timeout}s)",
215
212
  transient=True,
216
- get_time=lambda: time.time(),
217
213
  show_speed=False,
218
- refresh_per_second=2,
214
+ refresh_per_second=1,
219
215
  total=timeout,
220
216
  ):
221
217
  time.sleep(1)
@@ -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.9.0
3
+ Version: 0.9.1.post1
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,53 @@
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/basicgit.py,sha256=r_bI2U6QYFiS8ypUd6KtrjyZjK4JCANyK80L6wEzFoU,9213
5
+ mpflash/bootloader/__init__.py,sha256=cRIxVRtUc4jZAgtFggRNhEn0BW-9WFpzm5xRy5B4B2U,105
6
+ mpflash/bootloader/activate.py,sha256=sN2YuIuFGjLBd_PdG6P3N1yLuLyjnsVWDksrTMhzr_M,2301
7
+ mpflash/bootloader/detect.py,sha256=eXL_JPcowb8g0tpZmj9DQXYbpfZFoSrzq86lScKhkT4,2608
8
+ mpflash/bootloader/manual.py,sha256=qGInguhYil4v8EkUxPFlxzvs3m__KraPAj3LAKbV1Ts,3069
9
+ mpflash/bootloader/micropython.py,sha256=0KDrfdZPtK7fLaxh-_4VxSO-u4IUj7qCyNVw9-LQ74M,517
10
+ mpflash/bootloader/touch1200.py,sha256=tL2H4ERh0-YSdR8_v6aK_pDRPMjMevHWUGq4-TTFcWo,1083
11
+ mpflash/cli_download.py,sha256=Ip5HViXCVAiG88XgJ3Lg_hhBGIF5DKFTNpL-_gQkdV0,3520
12
+ mpflash/cli_flash.py,sha256=KFuJRNgOZ62m70I_KqxqLfLE69b4bOCj69MOfIWdZRo,7136
13
+ mpflash/cli_group.py,sha256=JFBtp4qhakJeQkuupEoObHeSFke8eWIU1HjnOZ-JfH0,2504
14
+ mpflash/cli_list.py,sha256=AvYq5_Z7l0Z4rkbr23TwFNzstuZsQgopFpdcrTLwUvs,1965
15
+ mpflash/cli_main.py,sha256=cElgh8Soq3U5TEAvrrD1sj7NDi-Eb-pei3QcMI0tlwE,1094
16
+ mpflash/common.py,sha256=h4pVuOpopn5oIy5NQdbggtOOktTL_c92cS_oUfPG4v8,5783
17
+ mpflash/config.py,sha256=h2Oq7kSe40tOnglpo02wkpaPHxHNVqyB3uGxreIu57U,1029
18
+ mpflash/connected.py,sha256=p6RMix-tFr0pfT9TErh0LD1nm24ApTr3CqVGcrnDHk8,3024
19
+ mpflash/download.py,sha256=mckR3pdMFQMYBKNmKBEJm9bJnTtQEnkuQ1vWYXcRRv8,13941
20
+ mpflash/downloaded.py,sha256=YPN0LDf8DSDvdB9gbVny61bvaJHIDbUs81XUwftTb1c,4808
21
+ mpflash/errors.py,sha256=6lUhVtECY3syV2bBGKzegGH4pPKXhevvhYQZd74sy6o,238
22
+ mpflash/flash/__init__.py,sha256=xX2ZJGNX9xpX2s8V7SEJ1It7eOEbl8WkdFzpRd3TLzk,2041
23
+ mpflash/flash/esp.py,sha256=LcOgjpE4zmPawHNwSd_6WFkaIYYazA__rf3ihGXR7I0,2228
24
+ mpflash/flash/stm32.py,sha256=W8SJ2_8FGXyMS6cRcZpfOvOM8iOC_cn4vK8xd8tKzI4,555
25
+ mpflash/flash/stm32_dfu.py,sha256=uTn06H0ZezzCv5O0hvry8ohBtuZXHe_GX2zNUfCxu58,2986
26
+ mpflash/flash/uf2/__init__.py,sha256=PWEVxzZEca3pfLx_Qy5c4zlHH4W5fAjd0BmDTkS7s6g,2766
27
+ mpflash/flash/uf2/boardid.py,sha256=2s4K3QiKWK5HKFKWYsDV3hI8alfWSxEOMeurER3eZtM,408
28
+ mpflash/flash/uf2/linux.py,sha256=4azbcx_YqLZ3RyYNWljejHG_Y6SU-wREL8hhkTYqCjI,4099
29
+ mpflash/flash/uf2/macos.py,sha256=sncXJsc2FVfm9rvLDjcEu7ZIyrDeHmazHiNQTUaf1Y0,1187
30
+ mpflash/flash/uf2/uf2disk.py,sha256=dQ8_U6e3qkFOyfXZDpWAsvEBIlMr-ZzLkzTDD8SADqM,286
31
+ mpflash/flash/uf2/windows.py,sha256=k9Yv71YswPnLx-Z5rf4KjhtVkEWr8SU8EXpeRv87h3A,1290
32
+ mpflash/flash/worklist.py,sha256=K16sbvzJCgkHNssYlBA3ezayI02RMuIcp19XAs74XeQ,5835
33
+ mpflash/list.py,sha256=O0tX4BvclmDMnnjMxCN9Zh8hdL6vnuvS9pLNxYLBya8,3112
34
+ mpflash/logger.py,sha256=BAVrSXMGZLfSDRFbtVBtvb7Rl0sTJxooCgBS5t-6bXo,1057
35
+ mpflash/mpboard_id/__init__.py,sha256=rQrPCN30GP-lfB2a2deA-lQ6iKvaKPK_xbtBoIavGsM,3716
36
+ mpflash/mpboard_id/add_boards.py,sha256=ehQn560S0XxAD3nsUMo4o_f6w8XTVAfO0GCnfTKa6-4,9379
37
+ mpflash/mpboard_id/board.py,sha256=yQ8IDHQS09AelvTvmPhpmsL4oX3L7IXGqHorkxDOkoE,1114
38
+ mpflash/mpboard_id/board_id.py,sha256=wzGrxJu_ciOVT7n2861lhoKmPAjh1QjWnAdfcqNUUqc,2871
39
+ mpflash/mpboard_id/board_info.zip,sha256=F6YowS96DAqjten4ySe4MXgZwPtE-saZOUfY5OQkqKk,19759
40
+ mpflash/mpboard_id/store.py,sha256=lQQgHSxcaM_ZURcfZNSUv3-ZJjUKMC_xEOOSdpzVvBU,1493
41
+ mpflash/mpremoteboard/__init__.py,sha256=7uI-5HJgNsQz_EOCW3cRy2xtqXKt9kX51gDSx6HC0Kc,7522
42
+ mpflash/mpremoteboard/mpy_fw_info.py,sha256=BTupe4rZDTs3UHRqvs429XqWHCchSpwa05yACOiOt5U,4413
43
+ mpflash/mpremoteboard/runner.py,sha256=YUmo5Y0aOgMaww8CXSdNdgXD-wRKncILuMZ0OB_2qRU,4646
44
+ mpflash/vendor/click_aliases.py,sha256=K98inhtze8td1dw312kexJS7OX_0ojlptPQ5Z0SHxJY,3065
45
+ mpflash/vendor/dfu.py,sha256=jGsiD3lbSV1Ar9qJubhoY_hy-L8FI-K55aow8vgwoYQ,5590
46
+ mpflash/vendor/pydfu.py,sha256=1ObubGsPFrQ7T9M3JRlIPNIG2xx8uYffaEe0Y6bdf_g,19937
47
+ mpflash/vendor/readme.md,sha256=ZVg7kuUYyXcWcrWkaSJ0CunwebCqu2SiS2sqDadwrT8,84
48
+ mpflash/versions.py,sha256=SrXVZx6qVWcighHlg8pJ0RPRZ3gcYN7l2DnSicconAk,4098
49
+ mpflash-0.9.1.post1.dist-info/LICENSE,sha256=xHwgxGNkI0R2iN4KNfbPbQSzRomWyRz7bJnR1O2mln8,1057
50
+ mpflash-0.9.1.post1.dist-info/METADATA,sha256=ZXUp9Y65hBRqeXjcZx4O6NQL_Jg8vZnQ6ROqDl6V86U,16064
51
+ mpflash-0.9.1.post1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
52
+ mpflash-0.9.1.post1.dist-info/entry_points.txt,sha256=Jk_visOhYOsZIcSP2Ms9hKqfKy1iorR-6dYltSoWCpY,52
53
+ mpflash-0.9.1.post1.dist-info/RECORD,,