micropython-stubber 1.24.1__py3-none-any.whl → 1.24.4__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 (90) hide show
  1. {micropython_stubber-1.24.1.dist-info → micropython_stubber-1.24.4.dist-info}/METADATA +9 -29
  2. micropython_stubber-1.24.4.dist-info/RECORD +107 -0
  3. {micropython_stubber-1.24.1.dist-info → micropython_stubber-1.24.4.dist-info}/WHEEL +1 -1
  4. stubber/__init__.py +1 -1
  5. stubber/board/createstubs.py +44 -38
  6. stubber/board/createstubs_db.py +17 -12
  7. stubber/board/createstubs_db_min.py +63 -63
  8. stubber/board/createstubs_db_mpy.mpy +0 -0
  9. stubber/board/createstubs_mem.py +17 -12
  10. stubber/board/createstubs_mem_min.py +99 -99
  11. stubber/board/createstubs_mem_mpy.mpy +0 -0
  12. stubber/board/createstubs_min.py +111 -112
  13. stubber/board/createstubs_mpy.mpy +0 -0
  14. stubber/board/modulelist.txt +27 -27
  15. stubber/codemod/board.py +1 -1
  16. stubber/codemod/enrich.py +13 -13
  17. stubber/codemod/merge_docstub.py +83 -53
  18. stubber/codemod/visitors/type_helpers.py +143 -41
  19. stubber/commands/enrich_folder_cmd.py +17 -17
  20. stubber/commands/get_docstubs_cmd.py +27 -9
  21. stubber/commands/get_frozen_cmd.py +1 -0
  22. stubber/commands/merge_cmd.py +2 -4
  23. stubber/merge_config.py +5 -36
  24. stubber/minify.py +3 -3
  25. stubber/modcat.py +118 -0
  26. stubber/publish/merge_docstubs.py +22 -5
  27. stubber/publish/stubpackage.py +33 -28
  28. stubber/rst/lookup.py +6 -23
  29. stubber/rst/reader.py +8 -13
  30. stubber/stubs_from_docs.py +2 -1
  31. stubber/tools/manifestfile.py +2 -1
  32. stubber/{cst_transformer.py → typing_collector.py} +36 -4
  33. micropython_stubber-1.24.1.dist-info/RECORD +0 -161
  34. mpflash/README.md +0 -220
  35. mpflash/libusb_flash.ipynb +0 -203
  36. mpflash/mpflash/__init__.py +0 -0
  37. mpflash/mpflash/add_firmware.py +0 -98
  38. mpflash/mpflash/ask_input.py +0 -236
  39. mpflash/mpflash/basicgit.py +0 -324
  40. mpflash/mpflash/bootloader/__init__.py +0 -2
  41. mpflash/mpflash/bootloader/activate.py +0 -60
  42. mpflash/mpflash/bootloader/detect.py +0 -82
  43. mpflash/mpflash/bootloader/manual.py +0 -101
  44. mpflash/mpflash/bootloader/micropython.py +0 -12
  45. mpflash/mpflash/bootloader/touch1200.py +0 -36
  46. mpflash/mpflash/cli_download.py +0 -129
  47. mpflash/mpflash/cli_flash.py +0 -224
  48. mpflash/mpflash/cli_group.py +0 -111
  49. mpflash/mpflash/cli_list.py +0 -87
  50. mpflash/mpflash/cli_main.py +0 -39
  51. mpflash/mpflash/common.py +0 -217
  52. mpflash/mpflash/config.py +0 -44
  53. mpflash/mpflash/connected.py +0 -96
  54. mpflash/mpflash/download.py +0 -364
  55. mpflash/mpflash/downloaded.py +0 -138
  56. mpflash/mpflash/errors.py +0 -9
  57. mpflash/mpflash/flash/__init__.py +0 -55
  58. mpflash/mpflash/flash/esp.py +0 -59
  59. mpflash/mpflash/flash/stm32.py +0 -19
  60. mpflash/mpflash/flash/stm32_dfu.py +0 -104
  61. mpflash/mpflash/flash/uf2/__init__.py +0 -88
  62. mpflash/mpflash/flash/uf2/boardid.py +0 -15
  63. mpflash/mpflash/flash/uf2/linux.py +0 -136
  64. mpflash/mpflash/flash/uf2/macos.py +0 -42
  65. mpflash/mpflash/flash/uf2/uf2disk.py +0 -12
  66. mpflash/mpflash/flash/uf2/windows.py +0 -43
  67. mpflash/mpflash/flash/worklist.py +0 -170
  68. mpflash/mpflash/list.py +0 -106
  69. mpflash/mpflash/logger.py +0 -41
  70. mpflash/mpflash/mpboard_id/__init__.py +0 -98
  71. mpflash/mpflash/mpboard_id/add_boards.py +0 -262
  72. mpflash/mpflash/mpboard_id/board.py +0 -37
  73. mpflash/mpflash/mpboard_id/board_id.py +0 -90
  74. mpflash/mpflash/mpboard_id/board_info.zip +0 -0
  75. mpflash/mpflash/mpboard_id/store.py +0 -48
  76. mpflash/mpflash/mpremoteboard/__init__.py +0 -271
  77. mpflash/mpflash/mpremoteboard/mpy_fw_info.py +0 -152
  78. mpflash/mpflash/mpremoteboard/runner.py +0 -140
  79. mpflash/mpflash/vendor/board_database.py +0 -185
  80. mpflash/mpflash/vendor/click_aliases.py +0 -91
  81. mpflash/mpflash/vendor/dfu.py +0 -165
  82. mpflash/mpflash/vendor/pydfu.py +0 -605
  83. mpflash/mpflash/vendor/readme.md +0 -12
  84. mpflash/mpflash/versions.py +0 -123
  85. mpflash/poetry.lock +0 -2603
  86. mpflash/pyproject.toml +0 -66
  87. mpflash/stm32_udev_rules.md +0 -63
  88. stubber/codemod/test_enrich.py +0 -87
  89. {micropython_stubber-1.24.1.dist-info → micropython_stubber-1.24.4.dist-info}/LICENSE +0 -0
  90. {micropython_stubber-1.24.1.dist-info → micropython_stubber-1.24.4.dist-info}/entry_points.txt +0 -0
@@ -1,605 +0,0 @@
1
- #!/usr/bin/env python
2
- # This file is part of the OpenMV project.
3
- # Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
4
- # This work is licensed under the MIT license, see the file LICENSE for
5
- # details.
6
- # type: ignore
7
- """This module implements enough functionality to program the STM32F4xx over
8
- DFU, without requiring dfu-util.
9
-
10
- See app note AN3156 for a description of the DFU protocol.
11
- See document UM0391 for a description of the DFuse file.
12
- """
13
-
14
- from __future__ import print_function
15
-
16
- import argparse
17
- import collections
18
- import inspect
19
- import re
20
- import struct
21
- import sys
22
- import usb.core
23
- import usb.util
24
- import zlib
25
-
26
- # USB request __TIMEOUT
27
- __TIMEOUT = 4000
28
-
29
- # DFU commands
30
- __DFU_DETACH = 0
31
- __DFU_DNLOAD = 1
32
- __DFU_UPLOAD = 2
33
- __DFU_GETSTATUS = 3
34
- __DFU_CLRSTATUS = 4
35
- __DFU_GETSTATE = 5
36
- __DFU_ABORT = 6
37
-
38
- # DFU status
39
- __DFU_STATE_APP_IDLE = 0x00
40
- __DFU_STATE_APP_DETACH = 0x01
41
- __DFU_STATE_DFU_IDLE = 0x02
42
- __DFU_STATE_DFU_DOWNLOAD_SYNC = 0x03
43
- __DFU_STATE_DFU_DOWNLOAD_BUSY = 0x04
44
- __DFU_STATE_DFU_DOWNLOAD_IDLE = 0x05
45
- __DFU_STATE_DFU_MANIFEST_SYNC = 0x06
46
- __DFU_STATE_DFU_MANIFEST = 0x07
47
- __DFU_STATE_DFU_MANIFEST_WAIT_RESET = 0x08
48
- __DFU_STATE_DFU_UPLOAD_IDLE = 0x09
49
- __DFU_STATE_DFU_ERROR = 0x0A
50
-
51
- _DFU_DESCRIPTOR_TYPE = 0x21
52
-
53
- __DFU_STATUS_STR = {
54
- __DFU_STATE_APP_IDLE: "STATE_APP_IDLE",
55
- __DFU_STATE_APP_DETACH: "STATE_APP_DETACH",
56
- __DFU_STATE_DFU_IDLE: "STATE_DFU_IDLE",
57
- __DFU_STATE_DFU_DOWNLOAD_SYNC: "STATE_DFU_DOWNLOAD_SYNC",
58
- __DFU_STATE_DFU_DOWNLOAD_BUSY: "STATE_DFU_DOWNLOAD_BUSY",
59
- __DFU_STATE_DFU_DOWNLOAD_IDLE: "STATE_DFU_DOWNLOAD_IDLE",
60
- __DFU_STATE_DFU_MANIFEST_SYNC: "STATE_DFU_MANIFEST_SYNC",
61
- __DFU_STATE_DFU_MANIFEST: "STATE_DFU_MANIFEST",
62
- __DFU_STATE_DFU_MANIFEST_WAIT_RESET: "STATE_DFU_MANIFEST_WAIT_RESET",
63
- __DFU_STATE_DFU_UPLOAD_IDLE: "STATE_DFU_UPLOAD_IDLE",
64
- __DFU_STATE_DFU_ERROR: "STATE_DFU_ERROR",
65
- }
66
-
67
- # USB device handle
68
- __dev = None
69
-
70
- # Configuration descriptor of the device
71
- __cfg_descr = None
72
-
73
- __verbose = None
74
-
75
- # USB DFU interface
76
- __DFU_INTERFACE = 0
77
-
78
- # Python 3 deprecated getargspec in favour of getfullargspec, but
79
- # Python 2 doesn't have the latter, so detect which one to use
80
- getargspec = getattr(inspect, "getfullargspec", getattr(inspect, "getargspec", None))
81
-
82
- if "length" in getargspec(usb.util.get_string).args:
83
- # PyUSB 1.0.0.b1 has the length argument
84
- def get_string(dev, index):
85
- return usb.util.get_string(dev, 255, index)
86
-
87
- else:
88
- # PyUSB 1.0.0.b2 dropped the length argument
89
- def get_string(dev, index):
90
- return usb.util.get_string(dev, index)
91
-
92
-
93
- def find_dfu_cfg_descr(descr):
94
- if len(descr) == 9 and descr[0] == 9 and descr[1] == _DFU_DESCRIPTOR_TYPE:
95
- nt = collections.namedtuple(
96
- "CfgDescr",
97
- [
98
- "bLength",
99
- "bDescriptorType",
100
- "bmAttributes",
101
- "wDetachTimeOut",
102
- "wTransferSize",
103
- "bcdDFUVersion",
104
- ],
105
- )
106
- return nt(*struct.unpack("<BBBHHH", bytearray(descr)))
107
- return None
108
-
109
-
110
- def init(**kwargs):
111
- """Initializes the found DFU device so that we can program it."""
112
- global __dev, __cfg_descr
113
- devices = get_dfu_devices(**kwargs)
114
- if not devices:
115
- raise ValueError("No DFU device found")
116
- if len(devices) > 1:
117
- raise ValueError("Multiple DFU devices found")
118
- __dev = devices[0]
119
- __dev.set_configuration()
120
-
121
- # Claim DFU interface
122
- usb.util.claim_interface(__dev, __DFU_INTERFACE)
123
-
124
- # Find the DFU configuration descriptor, either in the device or interfaces
125
- __cfg_descr = None
126
- for cfg in __dev.configurations():
127
- __cfg_descr = find_dfu_cfg_descr(cfg.extra_descriptors)
128
- if __cfg_descr:
129
- break
130
- for itf in cfg.interfaces():
131
- __cfg_descr = find_dfu_cfg_descr(itf.extra_descriptors)
132
- if __cfg_descr:
133
- break
134
-
135
- # Get device into idle state
136
- for attempt in range(4):
137
- status = get_status()
138
- if status == __DFU_STATE_DFU_IDLE:
139
- break
140
- elif status == __DFU_STATE_DFU_DOWNLOAD_IDLE or status == __DFU_STATE_DFU_UPLOAD_IDLE:
141
- abort_request()
142
- else:
143
- clr_status()
144
-
145
-
146
- def abort_request():
147
- """Sends an abort request."""
148
- __dev.ctrl_transfer(0x21, __DFU_ABORT, 0, __DFU_INTERFACE, None, __TIMEOUT)
149
-
150
-
151
- def clr_status():
152
- """Clears any error status (perhaps left over from a previous session)."""
153
- __dev.ctrl_transfer(0x21, __DFU_CLRSTATUS, 0, __DFU_INTERFACE, None, __TIMEOUT)
154
-
155
-
156
- def get_status():
157
- """Get the status of the last operation."""
158
- stat = __dev.ctrl_transfer(0xA1, __DFU_GETSTATUS, 0, __DFU_INTERFACE, 6, 20000)
159
-
160
- # firmware can provide an optional string for any error
161
- if stat[5]:
162
- message = get_string(__dev, stat[5])
163
- if message:
164
- print(message)
165
-
166
- return stat[4]
167
-
168
-
169
- def check_status(stage, expected):
170
- status = get_status()
171
- if status != expected:
172
- raise SystemExit("DFU: %s failed (%s)" % (stage, __DFU_STATUS_STR.get(status, status)))
173
-
174
-
175
- def mass_erase():
176
- """Performs a MASS erase (i.e. erases the entire device)."""
177
- # Send DNLOAD with first byte=0x41
178
- __dev.ctrl_transfer(0x21, __DFU_DNLOAD, 0, __DFU_INTERFACE, "\x41", __TIMEOUT)
179
-
180
- # Execute last command
181
- check_status("erase", __DFU_STATE_DFU_DOWNLOAD_BUSY)
182
-
183
- # Check command state
184
- check_status("erase", __DFU_STATE_DFU_DOWNLOAD_IDLE)
185
-
186
-
187
- def page_erase(addr):
188
- """Erases a single page."""
189
- if __verbose:
190
- print("Erasing page: 0x%x..." % (addr))
191
-
192
- # Send DNLOAD with first byte=0x41 and page address
193
- buf = struct.pack("<BI", 0x41, addr)
194
- __dev.ctrl_transfer(0x21, __DFU_DNLOAD, 0, __DFU_INTERFACE, buf, __TIMEOUT)
195
-
196
- # Execute last command
197
- check_status("erase", __DFU_STATE_DFU_DOWNLOAD_BUSY)
198
-
199
- # Check command state
200
- check_status("erase", __DFU_STATE_DFU_DOWNLOAD_IDLE)
201
-
202
-
203
- def set_address(addr):
204
- """Sets the address for the next operation."""
205
- # Send DNLOAD with first byte=0x21 and page address
206
- buf = struct.pack("<BI", 0x21, addr)
207
- __dev.ctrl_transfer(0x21, __DFU_DNLOAD, 0, __DFU_INTERFACE, buf, __TIMEOUT)
208
-
209
- # Execute last command
210
- check_status("set address", __DFU_STATE_DFU_DOWNLOAD_BUSY)
211
-
212
- # Check command state
213
- check_status("set address", __DFU_STATE_DFU_DOWNLOAD_IDLE)
214
-
215
-
216
- def write_memory(addr, buf, progress=None, progress_addr=0, progress_size=0):
217
- """Writes a buffer into memory. This routine assumes that memory has
218
- already been erased.
219
- """
220
-
221
- xfer_count = 0
222
- xfer_bytes = 0
223
- xfer_total = len(buf)
224
- xfer_base = addr
225
-
226
- while xfer_bytes < xfer_total:
227
- if __verbose and xfer_count % 512 == 0:
228
- print("Addr 0x%x %dKBs/%dKBs..." % (xfer_base + xfer_bytes, xfer_bytes // 1024, xfer_total // 1024))
229
- if progress and xfer_count % 2 == 0:
230
- progress(progress_addr, xfer_base + xfer_bytes - progress_addr, progress_size)
231
-
232
- # Set mem write address
233
- set_address(xfer_base + xfer_bytes)
234
-
235
- # Send DNLOAD with fw data
236
- chunk = min(__cfg_descr.wTransferSize, xfer_total - xfer_bytes)
237
- __dev.ctrl_transfer(0x21, __DFU_DNLOAD, 2, __DFU_INTERFACE, buf[xfer_bytes : xfer_bytes + chunk], __TIMEOUT)
238
-
239
- # Execute last command
240
- check_status("write memory", __DFU_STATE_DFU_DOWNLOAD_BUSY)
241
-
242
- # Check command state
243
- check_status("write memory", __DFU_STATE_DFU_DOWNLOAD_IDLE)
244
-
245
- xfer_count += 1
246
- xfer_bytes += chunk
247
-
248
-
249
- def write_page(buf, xfer_offset):
250
- """Writes a single page. This routine assumes that memory has already
251
- been erased.
252
- """
253
-
254
- xfer_base = 0x08000000
255
-
256
- # Set mem write address
257
- set_address(xfer_base + xfer_offset)
258
-
259
- # Send DNLOAD with fw data
260
- __dev.ctrl_transfer(0x21, __DFU_DNLOAD, 2, __DFU_INTERFACE, buf, __TIMEOUT)
261
-
262
- # Execute last command
263
- check_status("write memory", __DFU_STATE_DFU_DOWNLOAD_BUSY)
264
-
265
- # Check command state
266
- check_status("write memory", __DFU_STATE_DFU_DOWNLOAD_IDLE)
267
-
268
- if __verbose:
269
- print("Write: 0x%x " % (xfer_base + xfer_offset))
270
-
271
-
272
- def exit_dfu():
273
- """Exit DFU mode, and start running the program."""
274
- # Set jump address
275
- set_address(0x08000000)
276
-
277
- # Send DNLOAD with 0 length to exit DFU
278
- __dev.ctrl_transfer(0x21, __DFU_DNLOAD, 0, __DFU_INTERFACE, None, __TIMEOUT)
279
-
280
- try:
281
- # Execute last command
282
- if get_status() != __DFU_STATE_DFU_MANIFEST:
283
- print("Failed to reset device")
284
-
285
- # Release device
286
- usb.util.dispose_resources(__dev)
287
- except:
288
- pass
289
-
290
-
291
- def named(values, names):
292
- """Creates a dict with `names` as fields, and `values` as values."""
293
- return dict(zip(names.split(), values))
294
-
295
-
296
- def consume(fmt, data, names):
297
- """Parses the struct defined by `fmt` from `data`, stores the parsed fields
298
- into a named tuple using `names`. Returns the named tuple, and the data
299
- with the struct stripped off."""
300
-
301
- size = struct.calcsize(fmt)
302
- return named(struct.unpack(fmt, data[:size]), names), data[size:]
303
-
304
-
305
- def cstring(string):
306
- """Extracts a null-terminated string from a byte array."""
307
- return string.decode("utf-8").split("\0", 1)[0]
308
-
309
-
310
- def compute_crc(data):
311
- """Computes the CRC32 value for the data passed in."""
312
- return 0xFFFFFFFF & -zlib.crc32(data) - 1
313
-
314
-
315
- def read_dfu_file(filename):
316
- """Reads a DFU file, and parses the individual elements from the file.
317
- Returns an array of elements. Each element is a dictionary with the
318
- following keys:
319
- num - The element index.
320
- address - The address that the element data should be written to.
321
- size - The size of the element data.
322
- data - The element data.
323
- If an error occurs while parsing the file, then None is returned.
324
- """
325
-
326
- print("File: {}".format(filename))
327
- with open(filename, "rb") as fin:
328
- data = fin.read()
329
- crc = compute_crc(data[:-4])
330
- elements = []
331
-
332
- # Decode the DFU Prefix
333
- #
334
- # <5sBIB
335
- # < little endian Endianness
336
- # 5s char[5] signature "DfuSe"
337
- # B uint8_t version 1
338
- # I uint32_t size Size of the DFU file (without suffix)
339
- # B uint8_t targets Number of targets
340
- dfu_prefix, data = consume("<5sBIB", data, "signature version size targets")
341
- print(" %(signature)s v%(version)d, image size: %(size)d, " "targets: %(targets)d" % dfu_prefix)
342
- for target_idx in range(dfu_prefix["targets"]):
343
- # Decode the Image Prefix
344
- #
345
- # <6sBI255s2I
346
- # < little endian Endianness
347
- # 6s char[6] signature "Target"
348
- # B uint8_t altsetting
349
- # I uint32_t named Bool indicating if a name was used
350
- # 255s char[255] name Name of the target
351
- # I uint32_t size Size of image (without prefix)
352
- # I uint32_t elements Number of elements in the image
353
- img_prefix, data = consume("<6sBI255s2I", data, "signature altsetting named name " "size elements")
354
- img_prefix["num"] = target_idx
355
- if img_prefix["named"]:
356
- img_prefix["name"] = cstring(img_prefix["name"])
357
- else:
358
- img_prefix["name"] = ""
359
- print(
360
- " %(signature)s %(num)d, alt setting: %(altsetting)s, "
361
- 'name: "%(name)s", size: %(size)d, elements: %(elements)d' % img_prefix
362
- )
363
-
364
- target_size = img_prefix["size"]
365
- target_data = data[:target_size]
366
- data = data[target_size:]
367
- for elem_idx in range(img_prefix["elements"]):
368
- # Decode target prefix
369
- #
370
- # <2I
371
- # < little endian Endianness
372
- # I uint32_t element Address
373
- # I uint32_t element Size
374
- elem_prefix, target_data = consume("<2I", target_data, "addr size")
375
- elem_prefix["num"] = elem_idx
376
- print(" %(num)d, address: 0x%(addr)08x, size: %(size)d" % elem_prefix)
377
- elem_size = elem_prefix["size"]
378
- elem_data = target_data[:elem_size]
379
- target_data = target_data[elem_size:]
380
- elem_prefix["data"] = elem_data
381
- elements.append(elem_prefix)
382
-
383
- if len(target_data):
384
- print("target %d PARSE ERROR" % target_idx)
385
-
386
- # Decode DFU Suffix
387
- #
388
- # <4H3sBI
389
- # < little endian Endianness
390
- # H uint16_t device Firmware version
391
- # H uint16_t product
392
- # H uint16_t vendor
393
- # H uint16_t dfu 0x11a (DFU file format version)
394
- # 3s char[3] ufd "UFD"
395
- # B uint8_t len 16
396
- # I uint32_t crc32 Checksum
397
- dfu_suffix = named(struct.unpack("<4H3sBI", data[:16]), "device product vendor dfu ufd len crc")
398
- print(
399
- " usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, "
400
- "dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x" % dfu_suffix
401
- )
402
- if crc != dfu_suffix["crc"]:
403
- print("CRC ERROR: computed crc32 is 0x%08x" % crc)
404
- return
405
- data = data[16:]
406
- if data:
407
- print("PARSE ERROR")
408
- return
409
-
410
- return elements
411
-
412
-
413
- class FilterDFU(object):
414
- """Class for filtering USB devices to identify devices which are in DFU
415
- mode.
416
- """
417
-
418
- def __call__(self, device):
419
- for cfg in device:
420
- for intf in cfg:
421
- return intf.bInterfaceClass == 0xFE and intf.bInterfaceSubClass == 1
422
-
423
-
424
- def get_dfu_devices(*args, **kwargs):
425
- """Returns a list of USB devices which are currently in DFU mode.
426
- Additional filters (like idProduct and idVendor) can be passed in
427
- to refine the search.
428
- """
429
-
430
- # Convert to list for compatibility with newer PyUSB
431
- return list(usb.core.find(*args, find_all=True, custom_match=FilterDFU(), **kwargs))
432
-
433
-
434
- def get_memory_layout(device):
435
- """Returns an array which identifies the memory layout. Each entry
436
- of the array will contain a dictionary with the following keys:
437
- addr - Address of this memory segment.
438
- last_addr - Last address contained within the memory segment.
439
- size - Size of the segment, in bytes.
440
- num_pages - Number of pages in the segment.
441
- page_size - Size of each page, in bytes.
442
- """
443
-
444
- cfg = device[0]
445
- intf = cfg[(0, 0)]
446
- mem_layout_str = get_string(device, intf.iInterface)
447
- mem_layout = mem_layout_str.split("/")
448
- result = []
449
- for mem_layout_index in range(1, len(mem_layout), 2):
450
- addr = int(mem_layout[mem_layout_index], 0)
451
- segments = mem_layout[mem_layout_index + 1].split(",")
452
- seg_re = re.compile(r"(\d+)\*(\d+)(.)(.)")
453
- for segment in segments:
454
- seg_match = seg_re.match(segment)
455
- num_pages = int(seg_match.groups()[0], 10)
456
- page_size = int(seg_match.groups()[1], 10)
457
- multiplier = seg_match.groups()[2]
458
- if multiplier == "K":
459
- page_size *= 1024
460
- if multiplier == "M":
461
- page_size *= 1024 * 1024
462
- size = num_pages * page_size
463
- last_addr = addr + size - 1
464
- result.append(
465
- named(
466
- (addr, last_addr, size, num_pages, page_size),
467
- "addr last_addr size num_pages page_size",
468
- )
469
- )
470
- addr += size
471
- return result
472
-
473
-
474
- def list_dfu_devices(*args, **kwargs):
475
- """Prints a list of devices detected in DFU mode."""
476
- devices = get_dfu_devices(*args, **kwargs)
477
- if not devices:
478
- raise SystemExit("No DFU capable devices found")
479
- for device in devices:
480
- print(
481
- "Bus {} Device {:03d}: ID {:04x}:{:04x}".format(
482
- device.bus, device.address, device.idVendor, device.idProduct
483
- )
484
- )
485
- layout = get_memory_layout(device)
486
- print("Memory Layout")
487
- for entry in layout:
488
- print(
489
- " 0x{:x} {:2d} pages of {:3d}K bytes".format(
490
- entry["addr"], entry["num_pages"], entry["page_size"] // 1024
491
- )
492
- )
493
-
494
-
495
- def write_elements(elements, mass_erase_used, progress=None):
496
- """Writes the indicated elements into the target memory,
497
- erasing as needed.
498
- """
499
-
500
- mem_layout = get_memory_layout(__dev)
501
- for elem in elements:
502
- addr = elem["addr"]
503
- size = elem["size"]
504
- data = elem["data"]
505
- elem_size = size
506
- elem_addr = addr
507
- if progress and elem_size:
508
- progress(elem_addr, 0, elem_size)
509
- while size > 0:
510
- write_size = size
511
- if not mass_erase_used:
512
- for segment in mem_layout:
513
- if addr >= segment["addr"] and addr <= segment["last_addr"]:
514
- # We found the page containing the address we want to
515
- # write, erase it
516
- page_size = segment["page_size"]
517
- page_addr = addr & ~(page_size - 1)
518
- if addr + write_size > page_addr + page_size:
519
- write_size = page_addr + page_size - addr
520
- page_erase(page_addr)
521
- break
522
- write_memory(addr, data[:write_size], progress, elem_addr, elem_size)
523
- data = data[write_size:]
524
- addr += write_size
525
- size -= write_size
526
- if progress:
527
- progress(elem_addr, addr - elem_addr, elem_size)
528
-
529
-
530
- def cli_progress(addr, offset, size):
531
- """Prints a progress report suitable for use on the command line."""
532
- width = 25
533
- done = offset * width // size
534
- print(
535
- "\r0x{:08x} {:7d} [{}{}] {:3d}% ".format(addr, size, "=" * done, " " * (width - done), offset * 100 // size),
536
- end="",
537
- )
538
- try:
539
- sys.stdout.flush()
540
- except OSError:
541
- pass # Ignore Windows CLI "WinError 87" on Python 3.6
542
- if offset == size:
543
- print("")
544
-
545
-
546
- def main():
547
- """Test program for verifying this files functionality."""
548
- global __verbose
549
- # Parse CMD args
550
- parser = argparse.ArgumentParser(description="DFU Python Util")
551
- parser.add_argument("-l", "--list", help="list available DFU devices", action="store_true", default=False)
552
- parser.add_argument("--vid", help="USB Vendor ID", type=lambda x: int(x, 0), default=None)
553
- parser.add_argument("--pid", help="USB Product ID", type=lambda x: int(x, 0), default=None)
554
- parser.add_argument("-m", "--mass-erase", help="mass erase device", action="store_true", default=False)
555
- parser.add_argument("-u", "--upload", help="read file from DFU device", dest="path", default=False)
556
- parser.add_argument("-x", "--exit", help="Exit DFU", action="store_true", default=False)
557
- parser.add_argument("-v", "--verbose", help="increase output verbosity", action="store_true", default=False)
558
- args = parser.parse_args()
559
-
560
- __verbose = args.verbose
561
-
562
- kwargs = {}
563
- if args.vid:
564
- kwargs["idVendor"] = args.vid
565
-
566
- if args.pid:
567
- kwargs["idProduct"] = args.pid
568
-
569
- if args.list:
570
- list_dfu_devices(**kwargs)
571
- return
572
-
573
- init(**kwargs)
574
-
575
- command_run = False
576
- if args.mass_erase:
577
- print("Mass erase...")
578
- mass_erase()
579
- command_run = True
580
-
581
- if args.path:
582
- elements = read_dfu_file(args.path)
583
- if not elements:
584
- print("No data in dfu file")
585
- return
586
- print("Writing memory...")
587
- write_elements(elements, args.mass_erase, progress=cli_progress)
588
-
589
- print("Exiting DFU...")
590
- exit_dfu()
591
- command_run = True
592
-
593
- if args.exit:
594
- print("Exiting DFU...")
595
- exit_dfu()
596
- command_run = True
597
-
598
- if command_run:
599
- print("Finished")
600
- else:
601
- print("No command specified")
602
-
603
-
604
- if __name__ == "__main__":
605
- main()
@@ -1,12 +0,0 @@
1
- These modules are vendored from the following repositories:
2
-
3
- - https://github.com/micropython/micropython (MIT)
4
- - dfu.py
5
- - pydfy.py
6
-
7
- - https://github.com/mattytrentini/mpbuild (MIT)
8
- - board_database.py
9
-
10
- - https://github.com/click-contrib/click-aliases (Public Domain)
11
- - click_aliases.py (Robbin Bonthond)
12
-