micropython-stubber 1.20.4__py3-none-any.whl → 1.20.6__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.
- {micropython_stubber-1.20.4.dist-info → micropython_stubber-1.20.6.dist-info}/LICENSE +30 -30
- {micropython_stubber-1.20.4.dist-info → micropython_stubber-1.20.6.dist-info}/METADATA +4 -4
- micropython_stubber-1.20.6.dist-info/RECORD +159 -0
- mpflash/README.md +184 -184
- mpflash/libusb_flash.ipynb +203 -203
- mpflash/mpflash/add_firmware.py +98 -98
- mpflash/mpflash/ask_input.py +236 -226
- mpflash/mpflash/bootloader/__init__.py +37 -0
- mpflash/mpflash/bootloader/manual.py +102 -0
- mpflash/mpflash/bootloader/micropython.py +10 -0
- mpflash/mpflash/bootloader/touch1200.py +45 -0
- mpflash/mpflash/cli_download.py +129 -128
- mpflash/mpflash/cli_flash.py +219 -212
- mpflash/mpflash/cli_group.py +98 -92
- mpflash/mpflash/cli_list.py +81 -77
- mpflash/mpflash/cli_main.py +41 -38
- mpflash/mpflash/common.py +164 -151
- mpflash/mpflash/config.py +47 -31
- mpflash/mpflash/connected.py +74 -74
- mpflash/mpflash/download.py +360 -361
- mpflash/mpflash/downloaded.py +129 -129
- mpflash/mpflash/errors.py +9 -5
- mpflash/mpflash/flash.py +52 -69
- mpflash/mpflash/flash_esp.py +59 -59
- mpflash/mpflash/flash_stm32.py +24 -24
- mpflash/mpflash/flash_stm32_cube.py +111 -111
- mpflash/mpflash/flash_stm32_dfu.py +101 -101
- mpflash/mpflash/flash_uf2.py +67 -67
- mpflash/mpflash/flash_uf2_boardid.py +15 -15
- mpflash/mpflash/flash_uf2_linux.py +123 -123
- mpflash/mpflash/flash_uf2_macos.py +34 -37
- mpflash/mpflash/flash_uf2_windows.py +34 -34
- mpflash/mpflash/list.py +89 -89
- mpflash/mpflash/logger.py +41 -41
- mpflash/mpflash/mpboard_id/__init__.py +93 -93
- mpflash/mpflash/mpboard_id/add_boards.py +255 -255
- mpflash/mpflash/mpboard_id/board.py +37 -37
- mpflash/mpflash/mpboard_id/board_id.py +86 -86
- mpflash/mpflash/mpboard_id/store.py +43 -43
- mpflash/mpflash/mpremoteboard/__init__.py +221 -221
- mpflash/mpflash/mpremoteboard/mpy_fw_info.py +141 -141
- mpflash/mpflash/mpremoteboard/runner.py +140 -140
- mpflash/mpflash/uf2disk.py +12 -12
- mpflash/mpflash/vendor/basicgit.py +288 -288
- mpflash/mpflash/vendor/click_aliases.py +91 -0
- mpflash/mpflash/vendor/dfu.py +165 -165
- mpflash/mpflash/vendor/pydfu.py +605 -605
- mpflash/mpflash/vendor/readme.md +2 -2
- mpflash/mpflash/vendor/versions.py +119 -117
- mpflash/mpflash/worklist.py +170 -170
- mpflash/poetry.lock +1588 -1623
- mpflash/pyproject.toml +60 -60
- mpflash/stm32_udev_rules.md +62 -62
- stubber/__init__.py +3 -3
- stubber/basicgit.py +294 -288
- stubber/board/board_info.csv +193 -193
- stubber/board/boot.py +34 -34
- stubber/board/createstubs.py +986 -987
- stubber/board/createstubs_db.py +825 -826
- stubber/board/createstubs_db_min.py +331 -331
- stubber/board/createstubs_db_mpy.mpy +0 -0
- stubber/board/createstubs_lvgl.py +741 -741
- stubber/board/createstubs_lvgl_min.py +741 -741
- stubber/board/createstubs_mem.py +766 -767
- stubber/board/createstubs_mem_min.py +306 -306
- stubber/board/createstubs_mem_mpy.mpy +0 -0
- stubber/board/createstubs_min.py +294 -294
- stubber/board/createstubs_mpy.mpy +0 -0
- stubber/board/fw_info.py +141 -141
- stubber/board/info.py +183 -183
- stubber/board/main.py +19 -19
- stubber/board/modulelist.txt +247 -247
- stubber/board/pyrightconfig.json +34 -34
- stubber/bulk/mcu_stubber.py +454 -455
- stubber/codemod/_partials/__init__.py +48 -50
- stubber/codemod/_partials/db_main.py +147 -147
- stubber/codemod/_partials/lvgl_main.py +77 -77
- stubber/codemod/_partials/modules_reader.py +80 -80
- stubber/codemod/add_comment.py +53 -53
- stubber/codemod/add_method.py +65 -65
- stubber/codemod/board.py +317 -317
- stubber/codemod/enrich.py +145 -145
- stubber/codemod/merge_docstub.py +284 -284
- stubber/codemod/modify_list.py +54 -54
- stubber/codemod/utils.py +57 -57
- stubber/commands/build_cmd.py +94 -94
- stubber/commands/cli.py +51 -51
- stubber/commands/clone_cmd.py +66 -66
- stubber/commands/config_cmd.py +29 -29
- stubber/commands/enrich_folder_cmd.py +70 -70
- stubber/commands/get_core_cmd.py +69 -69
- stubber/commands/get_docstubs_cmd.py +87 -87
- stubber/commands/get_frozen_cmd.py +112 -112
- stubber/commands/get_mcu_cmd.py +56 -56
- stubber/commands/merge_cmd.py +66 -66
- stubber/commands/publish_cmd.py +119 -119
- stubber/commands/stub_cmd.py +30 -30
- stubber/commands/switch_cmd.py +54 -54
- stubber/commands/variants_cmd.py +48 -48
- stubber/cst_transformer.py +178 -178
- stubber/data/board_info.csv +193 -193
- stubber/data/board_info.json +1729 -1729
- stubber/data/micropython_tags.csv +15 -15
- stubber/data/requirements-core-micropython.txt +38 -38
- stubber/data/requirements-core-pycopy.txt +39 -39
- stubber/downloader.py +36 -36
- stubber/freeze/common.py +68 -68
- stubber/freeze/freeze_folder.py +69 -69
- stubber/freeze/freeze_manifest_2.py +113 -113
- stubber/freeze/get_frozen.py +127 -127
- stubber/get_cpython.py +101 -101
- stubber/get_lobo.py +59 -59
- stubber/minify.py +418 -418
- stubber/publish/bump.py +86 -86
- stubber/publish/candidates.py +262 -283
- stubber/publish/database.py +18 -18
- stubber/publish/defaults.py +45 -45
- stubber/publish/enums.py +24 -30
- stubber/publish/helpers.py +29 -29
- stubber/publish/merge_docstubs.py +130 -130
- stubber/publish/missing_class_methods.py +49 -49
- stubber/publish/package.py +146 -177
- stubber/publish/pathnames.py +51 -51
- stubber/publish/publish.py +120 -121
- stubber/publish/pypi.py +38 -38
- stubber/publish/stubpackage.py +1029 -1029
- stubber/rst/__init__.py +9 -9
- stubber/rst/classsort.py +77 -77
- stubber/rst/lookup.py +530 -530
- stubber/rst/output_dict.py +401 -401
- stubber/rst/reader.py +822 -823
- stubber/rst/report_return.py +69 -69
- stubber/rst/rst_utils.py +540 -540
- stubber/stubber.py +38 -38
- stubber/stubs_from_docs.py +90 -90
- stubber/tools/manifestfile.py +610 -610
- stubber/tools/readme.md +5 -5
- stubber/update_fallback.py +117 -117
- stubber/update_module_list.py +123 -125
- stubber/utils/__init__.py +5 -5
- stubber/utils/config.py +127 -127
- stubber/utils/makeversionhdr.py +54 -54
- stubber/utils/manifest.py +92 -92
- stubber/utils/post.py +79 -79
- stubber/utils/repos.py +157 -154
- stubber/utils/stubmaker.py +139 -139
- stubber/utils/typed_config_toml.py +77 -77
- stubber/utils/versions.py +128 -120
- stubber/variants.py +106 -106
- micropython_stubber-1.20.4.dist-info/RECORD +0 -154
- {micropython_stubber-1.20.4.dist-info → micropython_stubber-1.20.6.dist-info}/WHEEL +0 -0
- {micropython_stubber-1.20.4.dist-info → micropython_stubber-1.20.6.dist-info}/entry_points.txt +0 -0
mpflash/mpflash/ask_input.py
CHANGED
@@ -1,226 +1,236 @@
|
|
1
|
-
"""
|
2
|
-
Interactive input for mpflash.
|
3
|
-
|
4
|
-
Note: The prompts can use "{version}" and "{action}" to insert the version and action in the prompt without needing an f-string.
|
5
|
-
The values are provided from the answers dictionary.
|
6
|
-
"""
|
7
|
-
|
8
|
-
from typing import List, Sequence, Tuple, Union
|
9
|
-
|
10
|
-
from loguru import logger as log
|
11
|
-
|
12
|
-
from .common import DownloadParams, FlashParams, ParamType
|
13
|
-
from .config import config
|
14
|
-
from .mpboard_id import get_known_boards_for_port, get_known_ports,
|
15
|
-
|
16
|
-
from .
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
params.
|
72
|
-
if "
|
73
|
-
params.
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
"""
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
)
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
1
|
+
"""
|
2
|
+
Interactive input for mpflash.
|
3
|
+
|
4
|
+
Note: The prompts can use "{version}" and "{action}" to insert the version and action in the prompt without needing an f-string.
|
5
|
+
The values are provided from the answers dictionary.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from typing import List, Sequence, Tuple, Union
|
9
|
+
|
10
|
+
from loguru import logger as log
|
11
|
+
|
12
|
+
from .common import DownloadParams, FlashParams, ParamType
|
13
|
+
from .config import config
|
14
|
+
from .mpboard_id import (get_known_boards_for_port, get_known_ports,
|
15
|
+
known_stored_boards)
|
16
|
+
from .mpremoteboard import MPRemoteBoard
|
17
|
+
from .vendor.versions import micropython_versions
|
18
|
+
|
19
|
+
|
20
|
+
def ask_missing_params(
|
21
|
+
params: ParamType,
|
22
|
+
) -> ParamType:
|
23
|
+
"""
|
24
|
+
Asks the user for parameters that have not been supplied on the commandline and returns the updated params.
|
25
|
+
|
26
|
+
Args:
|
27
|
+
params (ParamType): The parameters to be updated.
|
28
|
+
|
29
|
+
Returns:
|
30
|
+
ParamType: The updated parameters.
|
31
|
+
"""
|
32
|
+
if not config.interactive:
|
33
|
+
# no interactivity allowed
|
34
|
+
log.info("Interactive mode disabled. Skipping ask for user input.")
|
35
|
+
return params
|
36
|
+
|
37
|
+
import inquirer
|
38
|
+
|
39
|
+
log.trace(f"ask_missing_params: {params}")
|
40
|
+
|
41
|
+
# if action flash, single input
|
42
|
+
# if action download, multiple input
|
43
|
+
multi_select = isinstance(params, DownloadParams)
|
44
|
+
action = "download" if isinstance(params, DownloadParams) else "flash"
|
45
|
+
|
46
|
+
questions = []
|
47
|
+
answers: dict[str, Union[str, List]] = {"action": action}
|
48
|
+
if not multi_select:
|
49
|
+
if not params.serial or "?" in params.serial:
|
50
|
+
questions.append(ask_serialport(multi_select=False, bluetooth=False))
|
51
|
+
else:
|
52
|
+
answers["serial"] = params.serial
|
53
|
+
|
54
|
+
if params.versions == [] or "?" in params.versions:
|
55
|
+
questions.append(ask_mp_version(multi_select=multi_select, action=action))
|
56
|
+
else:
|
57
|
+
# versions is used to show only the boards for the selected versions
|
58
|
+
answers["versions"] = params.versions # type: ignore
|
59
|
+
|
60
|
+
if not params.boards or "?" in params.boards:
|
61
|
+
questions.extend(ask_port_board(multi_select=multi_select, action=action))
|
62
|
+
if questions:
|
63
|
+
answers = inquirer.prompt(questions, answers=answers) # type: ignore
|
64
|
+
if not answers:
|
65
|
+
# input cancelled by user
|
66
|
+
return [] # type: ignore
|
67
|
+
log.trace(f"answers: {answers}")
|
68
|
+
if isinstance(params, FlashParams) and "serial" in answers:
|
69
|
+
if isinstance(answers["serial"], str):
|
70
|
+
answers["serial"] = [answers["serial"]]
|
71
|
+
params.serial = [s.split()[0] for s in answers["serial"]] # split to remove the description
|
72
|
+
if "port" in answers:
|
73
|
+
# params.ports = [p for p in params.ports if p != "?"] # remove the "?" if present
|
74
|
+
if isinstance(answers["port"], str):
|
75
|
+
params.ports.append(answers["port"])
|
76
|
+
elif isinstance(answers["port"], list): # type: ignore
|
77
|
+
params.ports.extend(answers["port"])
|
78
|
+
else:
|
79
|
+
raise ValueError(f"Unexpected type for answers['port']: {type(answers['port'])}")
|
80
|
+
|
81
|
+
if "boards" in answers:
|
82
|
+
params.boards = [b for b in params.boards if b != "?"] # remove the "?" if present
|
83
|
+
params.boards.extend(answers["boards"] if isinstance(answers["boards"], list) else [answers["boards"]])
|
84
|
+
if "versions" in answers:
|
85
|
+
params.versions = [v for v in params.versions if v != "?"] # remove the "?" if present
|
86
|
+
# make sure it is a list
|
87
|
+
if isinstance(answers["versions"], (list, tuple)):
|
88
|
+
params.versions.extend(answers["versions"])
|
89
|
+
else:
|
90
|
+
params.versions.append(answers["versions"])
|
91
|
+
# remove duplicates
|
92
|
+
params.ports = list(set(params.ports))
|
93
|
+
params.boards = list(set(params.boards))
|
94
|
+
params.versions = list(set(params.versions))
|
95
|
+
log.trace(f"ask_missing_params returns: {params}")
|
96
|
+
|
97
|
+
return params
|
98
|
+
|
99
|
+
|
100
|
+
def filter_matching_boards(answers: dict) -> Sequence[Tuple[str, str]]:
|
101
|
+
"""
|
102
|
+
Filters the known boards based on the selected versions and returns the filtered boards.
|
103
|
+
|
104
|
+
Args:
|
105
|
+
answers (dict): The user's answers.
|
106
|
+
|
107
|
+
Returns:
|
108
|
+
Sequence[Tuple[str, str]]: The filtered boards.
|
109
|
+
"""
|
110
|
+
versions = None
|
111
|
+
# if version is not asked ; then need to get the version from the inputs
|
112
|
+
if "versions" in answers:
|
113
|
+
versions = list(answers["versions"])
|
114
|
+
if "stable" in versions:
|
115
|
+
versions.remove("stable")
|
116
|
+
versions.append(micropython_versions()[-2]) # latest stable
|
117
|
+
elif "preview" in versions:
|
118
|
+
versions.remove("preview")
|
119
|
+
versions.extend((micropython_versions()[-1], micropython_versions()[-2])) # latest preview and stable
|
120
|
+
|
121
|
+
some_boards = known_stored_boards(answers["port"], versions) # or known_mp_boards(answers["port"])
|
122
|
+
|
123
|
+
if some_boards:
|
124
|
+
# Create a dictionary where the keys are the second elements of the tuples
|
125
|
+
# This will automatically remove duplicates because dictionaries cannot have duplicate keys
|
126
|
+
unique_dict = {item[1]: item for item in some_boards}
|
127
|
+
# Get the values of the dictionary, which are the unique items from the original list
|
128
|
+
some_boards = list(unique_dict.values())
|
129
|
+
else:
|
130
|
+
some_boards = [(f"No {answers['port']} boards found for version(s) {versions}", "")]
|
131
|
+
return some_boards
|
132
|
+
|
133
|
+
|
134
|
+
def ask_port_board(*, multi_select: bool, action: str):
|
135
|
+
"""
|
136
|
+
Asks the user for the port and board selection.
|
137
|
+
|
138
|
+
Args:
|
139
|
+
questions (list): The list of questions to be asked.
|
140
|
+
action (str): The action to be performed.
|
141
|
+
|
142
|
+
Returns:
|
143
|
+
None
|
144
|
+
"""
|
145
|
+
# import only when needed to reduce load time
|
146
|
+
import inquirer
|
147
|
+
|
148
|
+
# if action flash, single input
|
149
|
+
# if action download, multiple input
|
150
|
+
inquirer_ux = inquirer.Checkbox if multi_select else inquirer.List
|
151
|
+
return [
|
152
|
+
inquirer.List(
|
153
|
+
"port",
|
154
|
+
message="Which port do you want to {action} " + "to {serial} ?" if action == "flash" else "?",
|
155
|
+
choices=get_known_ports(),
|
156
|
+
# autocomplete=True,
|
157
|
+
),
|
158
|
+
inquirer_ux(
|
159
|
+
"boards",
|
160
|
+
message=(
|
161
|
+
"Which {port} board firmware do you want to {action} " + "to {serial} ?" if action == "flash" else "?"
|
162
|
+
),
|
163
|
+
choices=filter_matching_boards,
|
164
|
+
validate=at_least_one_validation, # type: ignore
|
165
|
+
# validate=lambda _, x: True if x else "Please select at least one board", # type: ignore
|
166
|
+
),
|
167
|
+
]
|
168
|
+
|
169
|
+
def at_least_one_validation(answers, current) -> bool:
|
170
|
+
import inquirer.errors
|
171
|
+
if not current:
|
172
|
+
raise inquirer.errors.ValidationError("", reason="Please select at least one item.")
|
173
|
+
if isinstance(current, list) and not any(current):
|
174
|
+
raise inquirer.errors.ValidationError("", reason="Please select at least one item.")
|
175
|
+
return True
|
176
|
+
|
177
|
+
def ask_mp_version(multi_select: bool, action: str):
|
178
|
+
"""
|
179
|
+
Asks the user for the version selection.
|
180
|
+
|
181
|
+
Args:
|
182
|
+
questions (list): The list of questions to be asked.
|
183
|
+
action (str): The action to be performed.
|
184
|
+
|
185
|
+
Returns:
|
186
|
+
|
187
|
+
"""
|
188
|
+
# import only when needed to reduce load time
|
189
|
+
import inquirer
|
190
|
+
import inquirer.errors
|
191
|
+
|
192
|
+
input_ux = inquirer.Checkbox if multi_select else inquirer.List
|
193
|
+
|
194
|
+
mp_versions: List[str] = micropython_versions()
|
195
|
+
mp_versions.reverse() # newest first
|
196
|
+
|
197
|
+
# remove the versions for which there are no known boards in the board_info.json
|
198
|
+
# todo: this may be a little slow
|
199
|
+
mp_versions = [v for v in mp_versions if "preview" in v or get_known_boards_for_port("stm32", [v])]
|
200
|
+
|
201
|
+
message = "Which version(s) do you want to {action} " + ("to {serial} ?" if action == "flash" else "?")
|
202
|
+
q = input_ux(
|
203
|
+
# inquirer.List(
|
204
|
+
"versions",
|
205
|
+
message=message,
|
206
|
+
# Hints would be nice , but needs a hint for each and every option
|
207
|
+
# hints=["Use space to select multiple options"],
|
208
|
+
choices=mp_versions,
|
209
|
+
autocomplete=True,
|
210
|
+
validate=at_least_one_validation, # type: ignore
|
211
|
+
)
|
212
|
+
return q
|
213
|
+
|
214
|
+
|
215
|
+
def ask_serialport(*, multi_select: bool = False, bluetooth: bool = False):
|
216
|
+
"""
|
217
|
+
Asks the user for the serial port selection.
|
218
|
+
|
219
|
+
Args:
|
220
|
+
questions (list): The list of questions to be asked.
|
221
|
+
action (str): The action to be performed.
|
222
|
+
|
223
|
+
Returns:
|
224
|
+
None
|
225
|
+
"""
|
226
|
+
# import only when needed to reduce load time
|
227
|
+
import inquirer
|
228
|
+
|
229
|
+
comports = MPRemoteBoard.connected_boards(bluetooth=bluetooth, description=True)
|
230
|
+
return inquirer.List(
|
231
|
+
"serial",
|
232
|
+
message="Which serial port do you want to {action} ?",
|
233
|
+
choices=comports,
|
234
|
+
other=True,
|
235
|
+
validate=lambda _, x: True if x else "Please select or enter a serial port", # type: ignore
|
236
|
+
)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import time
|
2
|
+
|
3
|
+
from mpflash.common import BootloaderMethod
|
4
|
+
from mpflash.errors import MPFlashError
|
5
|
+
from mpflash.logger import log
|
6
|
+
from mpflash.mpremoteboard import MPRemoteBoard
|
7
|
+
|
8
|
+
from .manual import enter_bootloader_manual
|
9
|
+
from .micropython import enter_bootloader_mpy
|
10
|
+
from .touch1200 import enter_bootloader_cdc_1200bps
|
11
|
+
|
12
|
+
|
13
|
+
def enter_bootloader(
|
14
|
+
mcu: MPRemoteBoard,
|
15
|
+
method: BootloaderMethod = BootloaderMethod.MPY,
|
16
|
+
timeout: int = 10,
|
17
|
+
wait_after: int = 2,
|
18
|
+
):
|
19
|
+
"""Enter the bootloader mode for the board"""
|
20
|
+
if method == BootloaderMethod.NONE:
|
21
|
+
# NO bootloader requested, so must be OK to flash
|
22
|
+
return True
|
23
|
+
|
24
|
+
log.info(f"Entering bootloader on {mcu.board} on {mcu.serialport} using method: {method.value}")
|
25
|
+
if method == BootloaderMethod.MPY:
|
26
|
+
result = enter_bootloader_mpy(mcu, timeout=timeout)
|
27
|
+
elif method == BootloaderMethod.MANUAL:
|
28
|
+
result = enter_bootloader_manual(mcu, timeout=timeout)
|
29
|
+
elif method == BootloaderMethod.TOUCH_1200:
|
30
|
+
result = enter_bootloader_cdc_1200bps(mcu, timeout=timeout)
|
31
|
+
else:
|
32
|
+
raise MPFlashError(f"Unknown bootloader method {method}")
|
33
|
+
if result:
|
34
|
+
time.sleep(wait_after)
|
35
|
+
else:
|
36
|
+
log.error(f"Failed to enter bootloader on {mcu.serialport}")
|
37
|
+
return result
|
@@ -0,0 +1,102 @@
|
|
1
|
+
"""Manual bootloader mode entry for various MCUs."""
|
2
|
+
|
3
|
+
from click.exceptions import Abort
|
4
|
+
from rich.console import Console
|
5
|
+
from rich.highlighter import RegexHighlighter
|
6
|
+
from rich.panel import Panel
|
7
|
+
from rich.prompt import Confirm
|
8
|
+
from rich.theme import Theme
|
9
|
+
|
10
|
+
# from mpflash.logger import console, log
|
11
|
+
from mpflash.mpremoteboard import MPRemoteBoard
|
12
|
+
|
13
|
+
|
14
|
+
class MCUHighlighter(RegexHighlighter):
|
15
|
+
"""Apply style to anything that looks like an email."""
|
16
|
+
|
17
|
+
base_style = "mcu."
|
18
|
+
highlights = [
|
19
|
+
r"(?P<bold>Method[\s\d\:]*)",
|
20
|
+
r"(?P<bold> \d.)", # numbered items
|
21
|
+
r"(?P<bold> - )", # bullets
|
22
|
+
r"(?P<pad>GPIO[\d]*)",
|
23
|
+
r"(?P<pad>GPI[\d]*)",
|
24
|
+
r"(?P<pad>IO[\d]*)",
|
25
|
+
r"(?P<pad>RUN)",
|
26
|
+
r"(?P<pad>GND)",
|
27
|
+
r"(?P<pad>VCC)",
|
28
|
+
r"(?P<pad>3.3V)",
|
29
|
+
r"(?P<pad>5V)",
|
30
|
+
# buttons
|
31
|
+
r"(?P<button>BOOTSEL)",
|
32
|
+
r"(?P<button>RESET)",
|
33
|
+
r"(?P<button>reset)",
|
34
|
+
# other
|
35
|
+
r"(?P<cable>USB)",
|
36
|
+
# r"(?P<mcu>SAMD[\d]*)",
|
37
|
+
# r"(?P<mcu>ESP[\d]*)",
|
38
|
+
# r"(?P<mcu>rp2)",
|
39
|
+
# r"(?P<mcu>rp2040)",
|
40
|
+
]
|
41
|
+
|
42
|
+
|
43
|
+
# https://rich.readthedocs.io/en/stable/appendix/colors.html?highlight=colors#standard-colors
|
44
|
+
mcu_theme = Theme(
|
45
|
+
{
|
46
|
+
"mcu.bold": "orange3",
|
47
|
+
"mcu.mcu": "orange3",
|
48
|
+
"mcu.button": "bold green",
|
49
|
+
"mcu.pad": "dodger_blue2",
|
50
|
+
"mcu.cable": "dodger_blue2",
|
51
|
+
}
|
52
|
+
)
|
53
|
+
|
54
|
+
|
55
|
+
def enter_bootloader_manual(mcu: MPRemoteBoard, timeout: int = 10):
|
56
|
+
|
57
|
+
message: str
|
58
|
+
if mcu.port == "rp2":
|
59
|
+
message = f"""\
|
60
|
+
Please put your {" ".join([mcu.port,mcu.board])} device into bootloader mode by either:
|
61
|
+
Method 1:
|
62
|
+
1. Unplug the USB cable,
|
63
|
+
2. Press and hold the BOOTSEL button on the device,
|
64
|
+
3. Plug the USB cable back in.
|
65
|
+
4. Release the BOOTSEL button.
|
66
|
+
|
67
|
+
Method 2:
|
68
|
+
1. Press and hold the BOOTSEL button on the device,
|
69
|
+
2. Reset the device by either:
|
70
|
+
- pressing the RESET button on the device
|
71
|
+
- by power-cycling the device,
|
72
|
+
- by briefly connecting the RUN pin to GND
|
73
|
+
3. Release the BOOTSEL button.
|
74
|
+
"""
|
75
|
+
elif mcu.port == "samd":
|
76
|
+
message = f"""\
|
77
|
+
Please put your {mcu.port.upper()} device into bootloader mode by:
|
78
|
+
- Pressing or sliding the RESET button twice in fast succession
|
79
|
+
"""
|
80
|
+
else:
|
81
|
+
message = f"""\
|
82
|
+
Please put your {mcu.port.upper()} device into bootloader mode by:
|
83
|
+
- Pressing the RESET button on the device
|
84
|
+
"""
|
85
|
+
|
86
|
+
# todo: would be nice to re-use the console instance from logger
|
87
|
+
console = Console(highlighter=MCUHighlighter(), theme=mcu_theme)
|
88
|
+
message += "\nIf you are unsure how to enter bootloader mode, please refer to the device documentation."
|
89
|
+
console.print(
|
90
|
+
Panel(
|
91
|
+
message,
|
92
|
+
highlight=True,
|
93
|
+
title="Manual Bootloader",
|
94
|
+
title_align="left",
|
95
|
+
expand=False,
|
96
|
+
)
|
97
|
+
)
|
98
|
+
try:
|
99
|
+
answer = Confirm.ask("Press Enter to continue", default="y")
|
100
|
+
except Abort:
|
101
|
+
return False
|
102
|
+
return answer in ["y", "Y", True]
|
@@ -0,0 +1,10 @@
|
|
1
|
+
"""Module for handling the bootloader mode for micropython boards"""
|
2
|
+
|
3
|
+
from mpflash.mpremoteboard import MPRemoteBoard
|
4
|
+
|
5
|
+
|
6
|
+
def enter_bootloader_mpy(mcu: MPRemoteBoard, timeout: int = 10):
|
7
|
+
"""Enter the bootloader mode for the board using mpremote and micropython on the board"""
|
8
|
+
mcu.run_command("bootloader", timeout=timeout)
|
9
|
+
# todo: check if mpremote command was successful
|
10
|
+
return True
|