mpflash 0.6.0__py3-none-any.whl → 0.7.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.
mpflash/ask_input.py CHANGED
@@ -12,7 +12,7 @@ from typing import Dict, List, Sequence, Tuple, Union
12
12
  from loguru import logger as log
13
13
 
14
14
  from mpflash.config import config
15
- from mpflash.mpboard_id import known_stored_boards, local_mp_ports
15
+ from mpflash.mpboard_id import get_stored_boards_for_port, known_stored_boards, local_mp_ports
16
16
  from mpflash.mpremoteboard import MPRemoteBoard
17
17
  from mpflash.vendor.versions import micropython_versions
18
18
 
@@ -131,7 +131,7 @@ def filter_matching_boards(answers: dict) -> Sequence[Tuple[str, str]]:
131
131
  # Get the values of the dictionary, which are the unique items from the original list
132
132
  some_boards = list(unique_dict.values())
133
133
  else:
134
- some_boards = [("No boards found", "")]
134
+ some_boards = [(f"No {answers['port']} boards found for version(s) {_versions}", "")]
135
135
  return some_boards
136
136
 
137
137
 
@@ -186,12 +186,27 @@ def ask_versions(questions: list, *, action: str):
186
186
  """
187
187
  # import only when needed to reduce load time
188
188
  import inquirer
189
+ import inquirer.errors
189
190
 
190
191
  input_ux = inquirer.Checkbox if action == "download" else inquirer.List
191
192
  mp_versions: List[str] = micropython_versions()
192
193
  mp_versions = [v for v in mp_versions if "preview" not in v]
194
+
195
+ # remove the versions for which there are no known boards in the board_info.json
196
+ # todo: this may be a little slow
197
+ mp_versions = [v for v in mp_versions if get_stored_boards_for_port("stm32", [v])]
198
+
193
199
  mp_versions.append("preview")
194
200
  mp_versions.reverse() # newest first
201
+
202
+ def at_least_one_validation(answers, current) -> bool:
203
+ if not current:
204
+ raise inquirer.errors.ValidationError("", reason="Please select at least one version")
205
+ if isinstance(current, list):
206
+ if not any(current):
207
+ raise inquirer.errors.ValidationError("", reason="Please select at least one version")
208
+ return True
209
+
195
210
  questions.append(
196
211
  input_ux(
197
212
  # inquirer.List(
@@ -201,7 +216,7 @@ def ask_versions(questions: list, *, action: str):
201
216
  # hints=["Use space to select multiple options"],
202
217
  choices=mp_versions,
203
218
  autocomplete=True,
204
- validate=lambda _, x: True if x else "Please select at least one version", # type: ignore
219
+ validate=at_least_one_validation,
205
220
  )
206
221
  )
207
222
 
mpflash/cli_download.py CHANGED
@@ -6,6 +6,7 @@ from typing import List, Tuple
6
6
  import rich_click as click
7
7
  from loguru import logger as log
8
8
 
9
+ from mpflash.errors import MPFlashError
9
10
  from mpflash.mpboard_id import find_stored_board
10
11
  from mpflash.vendor.versions import clean_version
11
12
 
@@ -62,9 +63,7 @@ from .download import download
62
63
  show_default=True,
63
64
  help="""Force download of firmware even if it already exists.""",
64
65
  )
65
- def cli_download(
66
- **kwargs,
67
- ):
66
+ def cli_download(**kwargs) -> int:
68
67
  params = DownloadParams(**kwargs)
69
68
  params.versions = list(params.versions)
70
69
  params.boards = list(params.boards)
@@ -77,18 +76,23 @@ def cli_download(
77
76
 
78
77
  params = ask_missing_params(params, action="download")
79
78
  if not params: # Cancelled by user
80
- exit(1)
79
+ return 2
81
80
  params.versions = [clean_version(v, drop_v=True) for v in params.versions]
82
81
  assert isinstance(params, DownloadParams)
83
82
 
84
- download(
85
- params.fw_folder,
86
- params.ports,
87
- params.boards,
88
- params.versions,
89
- params.force,
90
- params.clean,
91
- )
83
+ try:
84
+ download(
85
+ params.fw_folder,
86
+ params.ports,
87
+ params.boards,
88
+ params.versions,
89
+ params.force,
90
+ params.clean,
91
+ )
92
+ return 0
93
+ except MPFlashError as e:
94
+ log.error(f"{e}")
95
+ return 1
92
96
 
93
97
 
94
98
  def connected_ports_boards() -> Tuple[List[str], List[str]]:
mpflash/cli_flash.py CHANGED
@@ -13,7 +13,7 @@ from .cli_group import cli
13
13
  from .cli_list import show_mcus
14
14
  from .config import config
15
15
  from .flash import flash_list
16
- from .worklist import WorkList, full_auto_worklist, manual_worklist, single_auto_worklist
16
+ from .worklist import MPRemoteBoard, WorkList, full_auto_worklist, manual_worklist, single_auto_worklist
17
17
 
18
18
  # #########################################################################################################
19
19
  # CLI
@@ -28,7 +28,7 @@ from .worklist import WorkList, full_auto_worklist, manual_worklist, single_auto
28
28
  "--firmware",
29
29
  "-f",
30
30
  "fw_folder",
31
- type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
31
+ type=click.Path(file_okay=False, dir_okay=True, path_type=Path),
32
32
  default=config.firmware_folder,
33
33
  show_default=True,
34
34
  help="The folder to retrieve the firmware from.",
@@ -91,7 +91,7 @@ from .worklist import WorkList, full_auto_worklist, manual_worklist, single_auto
91
91
  show_default=True,
92
92
  help="""Enter micropython bootloader mode before flashing.""",
93
93
  )
94
- def cli_flash_board(**kwargs):
94
+ def cli_flash_board(**kwargs) -> int:
95
95
  # version to versions, board to boards
96
96
  kwargs["versions"] = [kwargs.pop("version")] if kwargs["version"] != None else []
97
97
  if kwargs["board"] is None:
@@ -104,6 +104,11 @@ def cli_flash_board(**kwargs):
104
104
  if not params.boards or params.boards == []:
105
105
  # nothing specified - detect connected boards
106
106
  params.ports, params.boards = connected_ports_boards()
107
+ if params.boards == []:
108
+ # No MicroPython boards detected, but it could be unflashed or not in bootloader mode
109
+ # Ask for serial port and board_id to flash
110
+ params.serial = "?"
111
+ params.boards = ["?"]
107
112
  else:
108
113
  for board_id in params.boards:
109
114
  if board_id == "":
@@ -122,7 +127,7 @@ def cli_flash_board(**kwargs):
122
127
  # Ask for missing input if needed
123
128
  params = ask_missing_params(params, action="flash")
124
129
  if not params: # Cancelled by user
125
- exit(1)
130
+ return 2
126
131
  # TODO: Just in time Download of firmware
127
132
 
128
133
  assert isinstance(params, FlashParams)
@@ -130,9 +135,9 @@ def cli_flash_board(**kwargs):
130
135
  if len(params.versions) > 1:
131
136
  log.error(f"Only one version can be flashed at a time, not {params.versions}")
132
137
  raise MPFlashError("Only one version can be flashed at a time")
133
- if len(params.boards) > 1:
134
- log.error(f"Only one board can be flashed at a time, not {params.boards}")
135
- raise MPFlashError("Only one board can be flashed at a time")
138
+ # if len(params.boards) > 1:
139
+ # log.error(f"Only one board can be flashed at a time, not {params.boards}")
140
+ # raise MPFlashError("Only one board can be flashed at a time")
136
141
 
137
142
  params.versions = [clean_version(v) for v in params.versions]
138
143
  worklist: WorkList = []
@@ -163,3 +168,7 @@ def cli_flash_board(**kwargs):
163
168
  ):
164
169
  log.info(f"Flashed {len(flashed)} boards")
165
170
  show_mcus(flashed, title="Updated boards after flashing")
171
+ return 0
172
+ else:
173
+ log.error("No boards were flashed")
174
+ return 1
mpflash/cli_group.py CHANGED
@@ -11,7 +11,7 @@ from .logger import make_quiet, set_loglevel
11
11
 
12
12
  def cb_verbose(ctx, param, value):
13
13
  """Callback to set the log level to DEBUG if verbose is set"""
14
- if value:
14
+ if value and not config.quiet:
15
15
  set_loglevel("DEBUG")
16
16
  config.verbose = True
17
17
  else:
mpflash/cli_list.py CHANGED
@@ -26,7 +26,7 @@ from .logger import make_quiet
26
26
  show_default=True,
27
27
  help="""Show progress""",
28
28
  )
29
- def cli_list_mcus(as_json: bool, progress: bool = True):
29
+ def cli_list_mcus(as_json: bool, progress: bool = True) -> int:
30
30
  """List the connected MCU boards, and output in a nice table or json."""
31
31
  if as_json:
32
32
  # avoid noise in json output
@@ -38,4 +38,4 @@ def cli_list_mcus(as_json: bool, progress: bool = True):
38
38
  progress = False
39
39
  if progress:
40
40
  show_mcus(conn_mcus, refresh=False)
41
- return conn_mcus
41
+ return 0 if conn_mcus else 1
mpflash/cli_main.py CHANGED
@@ -2,13 +2,13 @@
2
2
 
3
3
  # import rich_click as click
4
4
 
5
+ import click
6
+
5
7
  from .cli_download import cli_download
6
8
  from .cli_flash import cli_flash_board
7
9
  from .cli_group import cli
8
10
  from .cli_list import cli_list_mcus
9
11
 
10
- # from loguru import logger as log
11
-
12
12
 
13
13
  def mpflash():
14
14
  cli.add_command(cli_flash_board)
@@ -16,7 +16,8 @@ def mpflash():
16
16
  cli.add_command(cli_download)
17
17
  # cli(auto_envvar_prefix="MPFLASH")
18
18
  try:
19
- exit(cli())
19
+ result = cli(standalone_mode=False)
20
+ exit(result)
20
21
  except AttributeError as e:
21
22
  print(f"Error: {e}")
22
23
  exit(-1)
mpflash/download.py CHANGED
@@ -19,6 +19,7 @@ from loguru import logger as log
19
19
  from rich.progress import track
20
20
 
21
21
  from mpflash.common import PORT_FWTYPES
22
+ from mpflash.errors import MPFlashError
22
23
 
23
24
  jsonlines.ujson = None # type: ignore
24
25
  # #########################################################################################################
@@ -165,7 +166,7 @@ def download_firmwares(
165
166
  *,
166
167
  force: bool = False,
167
168
  clean: bool = True,
168
- ):
169
+ ) -> int:
169
170
  skipped = downloaded = 0
170
171
  if versions is None:
171
172
  versions = []
@@ -200,6 +201,7 @@ def download_firmwares(
200
201
  writer.write(board)
201
202
  downloaded += 1
202
203
  log.info(f"Downloaded {downloaded} firmwares, skipped {skipped} existing files.")
204
+ return downloaded + skipped
203
205
 
204
206
 
205
207
  def get_firmware_list(ports: List[str], boards: List[str], versions: List[str], clean: bool):
@@ -246,7 +248,7 @@ def download(
246
248
  versions: List[str],
247
249
  force: bool,
248
250
  clean: bool,
249
- ):
251
+ ) -> int:
250
252
  """
251
253
  Downloads firmware files based on the specified destination, ports, boards, versions, force flag, and clean flag.
252
254
 
@@ -259,19 +261,20 @@ def download(
259
261
  clean : A flag indicating whether to perform a clean download.
260
262
 
261
263
  Returns:
262
- None
264
+ int: The number of downloaded firmware files.
263
265
 
264
266
  Raises:
265
- SystemExit: If no boards are found or specified.
267
+ MPFlashError : If no boards are found or specified.
266
268
 
267
269
  """
268
270
  if not boards:
269
271
  log.critical("No boards found, please connect a board or specify boards to download firmware for.")
270
- exit(1)
272
+ raise MPFlashError("No boards found")
271
273
  # versions = [clean_version(v, drop_v=True) for v in versions] # remove leading v from version
272
274
  try:
273
275
  destination.mkdir(exist_ok=True, parents=True)
274
276
  except (PermissionError, FileNotFoundError) as e:
275
- log.critical(f"Could not create folder {destination}\n{e}")
276
- exit(1)
277
- download_firmwares(destination, ports, boards, versions, force=force, clean=clean)
277
+ log.critical(f"Could not create folder {destination}")
278
+ raise MPFlashError(f"Could not create folder {destination}") from e
279
+
280
+ return download_firmwares(destination, ports, boards, versions, force=force, clean=clean)
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
mpflash/list.py CHANGED
@@ -1,14 +1,19 @@
1
1
  from typing import List
2
2
 
3
3
  from rich import print
4
- from rich.progress import track
5
- from rich.table import Table
4
+ from rich.progress import BarColumn, Progress, SpinnerColumn, TextColumn, TimeElapsedColumn, track
5
+ from rich.table import Column, Table
6
6
 
7
7
  from mpflash.mpremoteboard import MPRemoteBoard
8
+ from mpflash.vendor.versions import clean_version
8
9
 
9
10
  from .config import config
10
11
  from .logger import console
11
12
 
13
+ rp_spinner = SpinnerColumn(finished_text="✅")
14
+ rp_text = TextColumn("{task.description} {task.fields[device]}", table_column=Column())
15
+ rp_bar = BarColumn(bar_width=None, table_column=Column())
16
+
12
17
 
13
18
  def list_mcus(bluetooth: bool = False):
14
19
  """
@@ -21,12 +26,24 @@ def list_mcus(bluetooth: bool = False):
21
26
  """
22
27
  conn_mcus = [MPRemoteBoard(sp) for sp in MPRemoteBoard.connected_boards(bluetooth) if sp not in config.ignore_ports]
23
28
 
24
- for mcu in track(conn_mcus, description="Getting board info", transient=True, update_period=0.1):
29
+ # a lot of boilerplate to show a progress bar with the comport currenlty scanned
30
+ with Progress(rp_spinner, rp_text, rp_bar, TimeElapsedColumn()) as progress:
31
+ tsk_scan = progress.add_task("[green]Scanning", visible=False, total=None)
32
+ progress.tasks[tsk_scan].fields["device"] = "..."
33
+ progress.tasks[tsk_scan].visible = True
34
+ progress.start_task(tsk_scan)
25
35
  try:
26
- mcu.get_mcu_info()
27
- except ConnectionError as e:
28
- print(f"Error: {e}")
29
- continue
36
+ for mcu in conn_mcus:
37
+ progress.update(tsk_scan, device=mcu.serialport.replace("/dev/", ""))
38
+ try:
39
+ mcu.get_mcu_info()
40
+ except ConnectionError as e:
41
+ print(f"Error: {e}")
42
+ continue
43
+ finally:
44
+ # transient
45
+ progress.stop_task(tsk_scan)
46
+ progress.tasks[tsk_scan].visible = False
30
47
  return conn_mcus
31
48
 
32
49
 
@@ -38,11 +55,10 @@ def show_mcus(
38
55
  """Show the list of connected boards in a nice table"""
39
56
  table = Table(
40
57
  title=title,
41
- title_style="bold",
42
- header_style="bold blue",
58
+ title_style="magenta",
59
+ header_style="bold magenta",
43
60
  collapse_padding=True,
44
61
  width=110,
45
- row_styles=["blue", "yellow"],
46
62
  )
47
63
  table.add_column("Serial", overflow="fold")
48
64
  table.add_column("Family")
@@ -59,14 +75,15 @@ def show_mcus(
59
75
  mcu.get_mcu_info()
60
76
  except ConnectionError:
61
77
  continue
78
+ description = f"[italic bright_cyan]{mcu.description}" if mcu.description else ""
62
79
  table.add_row(
63
80
  mcu.serialport.replace("/dev/", ""),
64
81
  mcu.family,
65
82
  mcu.port,
66
- f"{mcu.board}\n{mcu.description}".strip(),
83
+ f"{mcu.board}\n{description}".strip(),
67
84
  # mcu.variant,
68
85
  mcu.cpu,
69
- mcu.version,
86
+ clean_version(mcu.version),
70
87
  mcu.build,
71
88
  )
72
89
  console.print(table)
@@ -65,8 +65,9 @@ class MPRemoteBoard:
65
65
 
66
66
  @staticmethod
67
67
  def connected_boards(bluetooth: bool = False) -> List[str]:
68
+ # TODO: rename to connected_comports
68
69
  """
69
- Get a list of connected boards.
70
+ Get a list of connected comports.
70
71
 
71
72
  Parameters:
72
73
  - bluetooth (bool): Whether to include Bluetooth ports. Default is False.
@@ -74,14 +75,14 @@ class MPRemoteBoard:
74
75
  Returns:
75
76
  - List[str]: A list of connected board ports.
76
77
  """
77
- ports = serial.tools.list_ports.comports()
78
+ comports = serial.tools.list_ports.comports()
78
79
 
79
80
  if not bluetooth:
80
81
  # filter out bluetooth ports
81
- ports = [p for p in ports if "bluetooth" not in p.description.lower()]
82
- ports = [p for p in ports if "BTHENUM" not in p.hwid]
82
+ comports = [p for p in comports if "bluetooth" not in p.description.lower()]
83
+ comports = [p for p in comports if "BTHENUM" not in p.hwid]
83
84
 
84
- return sorted([p.device for p in ports])
85
+ return sorted([p.device for p in comports])
85
86
 
86
87
  @retry(stop=stop_after_attempt(RETRIES), wait=wait_fixed(1), reraise=True) # type: ignore ## retry_error_cls=ConnectionError,
87
88
  def get_mcu_info(self, timeout: int = 2):
@@ -21,6 +21,17 @@ class LogTags:
21
21
  ignore_tags: LogTagList
22
22
 
23
23
 
24
+ DEFAULT_RESET_TAGS = [
25
+ # ESP32 reset causes
26
+ "rst cause:1, boot mode:", # 1 -> hardware watch dog reset
27
+ "rst cause:2, boot mode:", # 2 -> software watch dog reset (From an exception)
28
+ "rst cause:3, boot mode:", # 3 -> software watch dog reset system_restart (Possibly unfed watchdog got angry)
29
+ "rst cause:4, boot mode:", # 4 -> soft restart (Possibly with a restart command)
30
+ "boot.esp32: PRO CPU has been reset by WDT.",
31
+ "rst:0x10 (RTCWDT_RTC_RESET)",
32
+ ]
33
+
34
+
24
35
  def run(
25
36
  cmd: List[str],
26
37
  timeout: int = 60,
@@ -57,18 +68,7 @@ def run(
57
68
  The return code and the output as a list of strings
58
69
  """
59
70
  if not reset_tags:
60
- reset_tags = [
61
- "rst cause:1, boot mode:",
62
- "rst cause:2, boot mode:",
63
- "rst cause:3, boot mode:",
64
- "rst cause:4, boot mode:",
65
- ]
66
- # 0 -> normal startup by power on
67
- # 1 -> hardware watch dog reset
68
- # 2 -> software watch dog reset (From an exception)
69
- # 3 -> software watch dog reset system_restart (Possibly unfed watchdog got angry)
70
- # 4 -> soft restart (Possibly with a restart command)
71
- # 5 -> wake up from deep-sleep
71
+ reset_tags = DEFAULT_RESET_TAGS
72
72
  if not error_tags:
73
73
  error_tags = ["Traceback ", "Error: ", "Exception: ", "ERROR :", "CRIT :"]
74
74
  if not warning_tags:
mpflash/worklist.py CHANGED
@@ -24,7 +24,7 @@ def auto_update(
24
24
  *,
25
25
  selector: Optional[Dict[str, str]] = None,
26
26
  ) -> WorkList:
27
- """Builds a list of boards to update based on the connected boards and the firmware available
27
+ """Builds a list of boards to update based on the connected boards and the firmwares available locally in the firmware folder.
28
28
 
29
29
  Args:
30
30
  conn_boards (List[MPRemoteBoard]): List of connected boards
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mpflash
3
- Version: 0.6.0
3
+ Version: 0.7.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
@@ -32,23 +32,23 @@ Requires-Dist: pygithub (>=2.1.1,<3.0.0)
32
32
  Requires-Dist: pyusb (>=1.2.1,<2.0.0)
33
33
  Requires-Dist: requests (>=2.31.0,<3.0.0)
34
34
  Requires-Dist: rich-click (>=1.7.3,<2.0.0)
35
- Requires-Dist: strip-ansi (>=0.1.1,<0.2.0)
36
35
  Requires-Dist: tenacity (==8.2.3)
37
36
  Project-URL: Repository, https://github.com/Josverl/micropython-stubber
38
37
  Description-Content-Type: text/markdown
39
38
 
40
- # mpflash
41
- mpflash is a command-line tool for working with MicroPython firmware. It provides various features to help you develop, build, and manage your MicroPython projects.
39
+ # MPFLASH
42
40
 
43
- This tool was created to be used in a CI/CD pipeline to automate the process of downloading and flashing MicroPython firmware to multiple boards, but it can also be used for manual flashing and development.
41
+ `mpflash` is a command-line tool for working with MicroPython firmware. It provides features to help you flash and update Micropython on one or more .
44
42
 
45
- mpflash has been tested on Windows x64, Linux X64 and ARM64, but not (yet) macOS.
43
+ This tool was initially created to be used in a CI/CD pipeline to automate the process of downloading and flashing MicroPython firmware to multiple boards, but it has been extend with a TUI to me be used for manual downloadig, flashing and development.
44
+
45
+ `mpflash` has been tested on Windows x64, Linux X64, but not (yet) macOS.
46
+ Tested ports: `rp2`, `samd`, `esp32`, `esp32s3`, `esp32c3`, `esp8266` and `stm32`
46
47
 
47
48
  ## Features
48
49
  1. List the connected boards including their firmware details, in a tabular or json format
49
- 2. Download MicroPython firmware for specific boards and versions.
50
- 3. Flash one or all connected MicroPython boards with a specific firmware or version.
51
- Tested ports: rp2, samd, esp32, esp32s3, esp8266 and stm32
50
+ 2. Download MicroPython firmware for versions, and matching a specified board or matches your current attached board.
51
+ 3. Flash one or all connected MicroPython boards with a specific firmware or version.
52
52
 
53
53
  ## Installation
54
54
  To install mpflash, you can use pip: `pip install mpflash`
@@ -69,40 +69,40 @@ On Windows this will not be an issue, but on Linux you can use udev rules to gi
69
69
  [See the stm32_permissions documentation](./stm32_udev_rules.md) for more information.
70
70
 
71
71
 
72
- ## Advanced use
72
+ ## Detailed usage
73
73
  You can list the connected boards using the following command:
74
74
  ```bash
75
75
  $ mpflash list
76
76
  D:\MyPython\micropython-stubber> mpflash list
77
- Getting board info ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:02
78
- Connected boards
79
- ┏━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━┓
80
- ┃ Serial ┃ Family ┃ Port ┃ Board ┃ CPU ┃ Version ┃ build ┃
81
- ┡━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━┩
82
- COM11 micropython rp2 │ RPI_PICO_W │ RP2040 1.20.0
83
- COM12 micropython esp8266 ESP8266_GENERIC ESP8266 1.22.2
84
- COM18 micropython rp2 │ RPI_PICO_W │ RP2040 1.23.0-preview 155
85
- COM3 micropython samd SEEED_WIO_TERMINAL SAMD51P19A 1.23.0-preview 155
86
- COM5 micropython stm32 PYBV11 │ STM32F405RG 1.23.0-preview 166
87
- │ COM8 │ micropython │ esp32 │ ESP32_GENERIC_S3 │ ESP32S3 │ 1.23.0-preview │ 155 │
88
- └────────┴─────────────┴─────────┴────────────────────┴─────────────┴────────────────┴───────┘
77
+ Connected boards
78
+ ┏━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━┓
79
+ ┃ Serial ┃Family ┃Port ┃Board ┃CPU ┃Version ┃build ┃
80
+ ┡━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━┩
81
+ │ COM21 │micropython │rp2 │RPI_PICO │RP2040 │v1.23.0-preview │ 236 │
82
+ │ │Raspberry Pi Pico with RP2040
83
+ COM23 │micropython rp2 RPI_PICO_W RP2040 v1.23.0-preview 176
84
+ │ │Raspberry Pi Pico W with RP2040
85
+ COM9 │micropython rp2 ARDUINO_NANO_RP2040_CONNECT RP2040v1.23.0-preview 341
86
+ Arduino Nano RP2040 Connect with RP2040 │ │
87
+ └─────────┴─────────────┴──────┴───────────────────────────────────────────┴────────┴─────────────────┴──────┘
89
88
  ```
89
+ ## Download the firmware
90
90
 
91
- Suppose you want to download the MicroPython firmware for some boards, you can use the following command:
91
+ To download the MicroPython firmware for some boards, use the following command:
92
+ - `mpflash download` download the latest stable firmware for all connected boards
93
+ - `mpflash download --version preview` download the current preview for all connected boards
94
+ - `mpflash download --board ESP8266_GENERIC --board SEEED_WIO_TERMINAL` download these specific boards
95
+ - `mpflash download --version ? --board ?` prompt to select a specific version and board to download
92
96
 
93
- ```bash
94
- # download the firmware
95
- $ mpflash download --board ESP8266_GENERIC --board SEEED_WIO_TERMINAL
96
- ```
97
- This will download the latest stable version of the MicroPython firmware for the boards and save it in the `firmware` directory.
97
+ 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.
98
98
  The stable version (default) is determined based on the most recent published release,
99
- other optionse are `--version preview` and `--version x.y.z` to download the latest preview or version x.y.z respectively.
99
+ other versions are `--version preview` and `--version x.y.z` to download the latest preview or version x.y.z respectively.
100
100
 
101
- by default the firmware will be downloaded to Downloads in a `firmware` folder in your, but you can specify a different directory using the `--dir` option.
101
+ 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.
102
102
 
103
- ```bash
104
103
  The directory structure will be something like this:
105
- ```
104
+
105
+ ``` text
106
106
  Downloads/firmware
107
107
  | firmware.jsonl
108
108
  +---esp8266
@@ -113,9 +113,16 @@ Downloads/firmware
113
113
  \---samd
114
114
  SEEED_WIO_TERMINAL-v1.22.2.uf2
115
115
  ```
116
- You can then flash the firmware to the board using the following command: `mpflash flash`
116
+
117
+ ## Flashing the firmware
118
+ After you have downloaded a firmware you can flash the firmware to a board using the following command: `mpflash flash`
117
119
  This will (try to) autodetect the connected boards, and determine the correct firmware to flash to each board.
118
120
 
121
+ - `mpflash flash` will flash the latest stable firmware to all connected boards.
122
+ - `mpflash flash --serial ? --board ?` will prompt to select a specific serial port and board to flash. (the firmware must be dowloaded earlier)
123
+
124
+
125
+ ### Flashing all connected boards with the latest stable firmware
119
126
  ```bash
120
127
  > mpflash flash
121
128
  22:15:55 | ℹ️ - Using latest stable version: v1.22.2
@@ -1,13 +1,13 @@
1
1
  mpflash/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- mpflash/ask_input.py,sha256=NGjCcOx49gW8xuDZK1BQXNOMPy7fUQ5pQamasez1wHI,7793
3
- mpflash/cli_download.py,sha256=9Rxwo-j7h9_rwMeAgITmfkdiNVi-Wunr1vpx2VjjUNM,3090
4
- mpflash/cli_flash.py,sha256=bp2AXHYqusVQbIOt12gqkbC4OoVMVV2gsY1fI-Js63M,5482
5
- mpflash/cli_group.py,sha256=hdyFrxkA_ye5r5bAsOnPr99KV2pfzgDoNXGPjTvEpW0,1946
6
- mpflash/cli_list.py,sha256=uxTRPdjFWv5ev4E_pz1JYv8DSFLOtZvTKmVmCiRpEC4,1005
7
- mpflash/cli_main.py,sha256=VxIpmvk3-2Sr1uB1AMT5bRa0TlrbY28ZaYd6NGZnEe0,632
2
+ mpflash/ask_input.py,sha256=_LlatVyrWbY1Q4TDn8TWXJO5s22q_bGl3NXmdt13jxU,8442
3
+ mpflash/cli_download.py,sha256=RNEsk1eMqzKCf9_sUPZQkDnzw6w-8L0Jnl6gDQup2Tc,3266
4
+ mpflash/cli_flash.py,sha256=DTZ1mQSL31aEr3ROGIGWzzkiir4MRSqXdwq2p4ArDWE,5847
5
+ mpflash/cli_group.py,sha256=nL3H06PHm_XUDlMuRyjgmTYeLnkrLa9mKDdahYw-KRo,1967
6
+ mpflash/cli_list.py,sha256=KIlEeqcIIBf0g-emS43fzKspUy6fn9TUuFl0u00XaK8,1024
7
+ mpflash/cli_main.py,sha256=BgqkDeEV0LBdT_Xn_Ay3zQOVJ-73pWSA4ngRf9KxGpw,656
8
8
  mpflash/common.py,sha256=lucFGMLl03qz-5Ic2XVv4g5XVt6hloUU6N5v0tSaUYE,1049
9
9
  mpflash/config.py,sha256=G6TxliEGxoYXy1SHQYBKgywnKccz9QzD3mGq_Vv1frg,419
10
- mpflash/download.py,sha256=HhL97PFTts_QhI1121QcWS7Z2nbfqvJ7mof_KFARx6k,10765
10
+ mpflash/download.py,sha256=_yYENI7oew4tD51xEer1Ohv2B3LHrGg1lIF98LWDMCY,10991
11
11
  mpflash/downloaded.py,sha256=ADMJqZn7WVcU-Rm2X6RqA8ejtBNBYXcpwxVyT3v7r6s,3803
12
12
  mpflash/errors.py,sha256=Q5LR12Wo8iUCg5n_qq4GjdBdBflbvCOdKsRJ5InYRfI,96
13
13
  mpflash/flash.py,sha256=YGYXuNNbjro4QvZmpwpLCo86nFsh4UxWrOJHOowUYDY,2490
@@ -15,26 +15,26 @@ mpflash/flash_esp.py,sha256=TjBOk2y1eLrcE8T3iYGypsiskPX7BFNfxYmCuUo_3v4,2316
15
15
  mpflash/flash_stm32.py,sha256=d4BoQl3a9Tchnvn2ZTuq2MpYBB4MTaRukwtEncI95k0,823
16
16
  mpflash/flash_stm32_cube.py,sha256=w7aGWjReeWUKl0Q3ZjXH8BRqNO1Tk9AO7gtRNUg1c9Y,3970
17
17
  mpflash/flash_stm32_dfu.py,sha256=G70EZodWb-aRi507Jxbys-VEwbBGU1oZacow3_nq-d4,2972
18
- mpflash/flash_uf2.py,sha256=nTbp8MbSZeNVPWPPsQxN1ppTtBGESXMfwZ_qL4Bwkv0,2029
18
+ mpflash/flash_uf2.py,sha256=KvNPk1zDwQexJfPI5MlIoR7zTD0u-pQQwSHuFQjuMXg,2093
19
19
  mpflash/flash_uf2_boardid.py,sha256=WZKucGu_hJ8ymb236uuZbiR6pD6AA_l4LA-7LwtQhq8,414
20
20
  mpflash/flash_uf2_linux.py,sha256=LAGkzTImVq-wKo7LGUNlwkUHv1L4rGO7igR5dwxY07o,4298
21
21
  mpflash/flash_uf2_windows.py,sha256=dcmA-koavH7duOuNwI0n2aDDbhF1_5ZZ-mXFAXgj8z4,1072
22
- mpflash/list.py,sha256=7-yW_J-TDGMvRrRfz7clJseiMy4uEgcwyhOaiw5fj1w,2248
22
+ mpflash/list.py,sha256=R3upYux3mEltpqfrt467Ufs4hVatW1NE40jjhN7Ei1g,3252
23
23
  mpflash/logger.py,sha256=dI_H_a7EOdQJyvoeRHQuYeZuTKYVUS3DUPTLhE9rkdM,1098
24
24
  mpflash/mpboard_id/__init__.py,sha256=JYGe7VwpBV4ig2M9a6vJUQrMtgdNjZKHt_Z5N13Ycrs,3509
25
25
  mpflash/mpboard_id/board_id.py,sha256=NjKkIUv3sw6X60qy--mieQWrle3WNKw5NwAepMenTHI,2230
26
26
  mpflash/mpboard_id/board_info.csv,sha256=KPWDo-zHWfrPGQn9oInsDH-5IdCzhBCs6K_YAmqqSpQ,96983
27
27
  mpflash/mpboard_id/board_info.json,sha256=JtVyOMIO1O7vLKzJ0hyXQ4JSxXiQBJyay2hjdNLnZM0,674442
28
- mpflash/mpremoteboard/__init__.py,sha256=NSp71Qynz3hYqLLy0foVqdkURbNxfjUjiQBmaxKFF64,6951
28
+ mpflash/mpremoteboard/__init__.py,sha256=DxlO_7LiyWDz5hNRI77fzp3sI3fZQ9Sd23dnGLx4Zl0,7017
29
29
  mpflash/mpremoteboard/mpy_fw_info.py,sha256=6AQbN3jtQgllqWQYl4e-63KeEtV08EXk8_JnM6XBkvo,4554
30
- mpflash/mpremoteboard/runner.py,sha256=H3W_xGJvjz7TLtlkDQrCLibgegRWGfsaBOABNbAfP_U,4783
30
+ mpflash/mpremoteboard/runner.py,sha256=-PgzAeBGbyXaAUlwyiw4mcINsP2U1XRRjP1_QdBrxpg,4786
31
31
  mpflash/vendor/dfu.py,sha256=oK_MRSOyDJrUuS6D24IMIsfL7oLcrvUq0yp_h4WIY2U,5739
32
32
  mpflash/vendor/pydfu.py,sha256=_MdBRo1EeNeKDqFPSTB5tNL1jGSBJgsVeVjE5e7Pb8s,20542
33
33
  mpflash/vendor/readme.md,sha256=iIIZxuLUIGHQ0KODzYVtMezsztvyxCXcNJp_AzwTIPk,86
34
34
  mpflash/vendor/versions.py,sha256=ooRZjeeYepQHwp12hMu2m0p8nZXQ5s942w5mGkKmgeI,3629
35
- mpflash/worklist.py,sha256=TGVFugEyWn83WKr0wahBBimcfsHMWGo8_QTu4g3ao-0,5266
36
- mpflash-0.6.0.dist-info/entry_points.txt,sha256=Jk_visOhYOsZIcSP2Ms9hKqfKy1iorR-6dYltSoWCpY,52
37
- mpflash-0.6.0.dist-info/LICENSE,sha256=mWpNhsIxWzetYNnTpr4eb3HtgsxGIC8KcYWxXEcxQvE,1077
38
- mpflash-0.6.0.dist-info/METADATA,sha256=wlr-kNnhL5NmvIbM9LIquNRymrf_sPsLcv7MQYx0-Ic,13778
39
- mpflash-0.6.0.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
40
- mpflash-0.6.0.dist-info/RECORD,,
35
+ mpflash/worklist.py,sha256=qZsqF3Lf5Bl7QQ31ZLVHewP6WC8fmwQPMbyNgbG7LB4,5299
36
+ mpflash-0.7.1.dist-info/entry_points.txt,sha256=Jk_visOhYOsZIcSP2Ms9hKqfKy1iorR-6dYltSoWCpY,52
37
+ mpflash-0.7.1.dist-info/LICENSE,sha256=mWpNhsIxWzetYNnTpr4eb3HtgsxGIC8KcYWxXEcxQvE,1077
38
+ mpflash-0.7.1.dist-info/METADATA,sha256=aAxXPamGn_mE__rBwjcZwSQlj-lQo8KA8HzyhmUIc9U,14627
39
+ mpflash-0.7.1.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
40
+ mpflash-0.7.1.dist-info/RECORD,,