pyflashgui 0.1.0__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 (68) hide show
  1. pyflashgui/__init__.py +6 -0
  2. pyflashgui/__main__.py +334 -0
  3. pyflashgui/backends/__init__.py +40 -0
  4. pyflashgui/backends/base.py +272 -0
  5. pyflashgui/backends/jlink_backend.py +596 -0
  6. pyflashgui/backends/pyocd_backend.py +271 -0
  7. pyflashgui/backends/simulated.py +240 -0
  8. pyflashgui/core/__init__.py +2 -0
  9. pyflashgui/core/checkout.py +134 -0
  10. pyflashgui/core/compare.py +157 -0
  11. pyflashgui/core/context.py +37 -0
  12. pyflashgui/core/events.py +71 -0
  13. pyflashgui/core/excepthook.py +110 -0
  14. pyflashgui/core/flasher.py +419 -0
  15. pyflashgui/core/images.py +279 -0
  16. pyflashgui/core/installation.py +137 -0
  17. pyflashgui/core/layout.py +72 -0
  18. pyflashgui/core/memory_map.py +234 -0
  19. pyflashgui/core/packages.py +104 -0
  20. pyflashgui/core/paths.py +49 -0
  21. pyflashgui/core/settings.py +44 -0
  22. pyflashgui/core/shortcut.py +154 -0
  23. pyflashgui/core/slow_start.py +101 -0
  24. pyflashgui/core/timing.py +312 -0
  25. pyflashgui/core/updates.py +195 -0
  26. pyflashgui/core/worker.py +71 -0
  27. pyflashgui/core/workspaces.py +250 -0
  28. pyflashgui/help/__init__.py +129 -0
  29. pyflashgui/help/about.md +21 -0
  30. pyflashgui/help/changelog.md +46 -0
  31. pyflashgui/help/files.md +60 -0
  32. pyflashgui/help/main-window.png +0 -0
  33. pyflashgui/help/manual.md +44 -0
  34. pyflashgui/help/memory-map.md +28 -0
  35. pyflashgui/help/memory.md +59 -0
  36. pyflashgui/help/probe.md +71 -0
  37. pyflashgui/resources/__init__.py +10 -0
  38. pyflashgui/resources/pyflashgui.ico +0 -0
  39. pyflashgui/resources/pyflashgui.png +0 -0
  40. pyflashgui/resources/pyflashgui.svg +32 -0
  41. pyflashgui/resources/pyflashgui_small.svg +20 -0
  42. pyflashgui/ui/__init__.py +2 -0
  43. pyflashgui/ui/confirm.py +312 -0
  44. pyflashgui/ui/detached.py +101 -0
  45. pyflashgui/ui/erase_dialog.py +141 -0
  46. pyflashgui/ui/event_colours.py +66 -0
  47. pyflashgui/ui/files_view.py +716 -0
  48. pyflashgui/ui/folders.py +176 -0
  49. pyflashgui/ui/fonts.py +75 -0
  50. pyflashgui/ui/help_menu.py +587 -0
  51. pyflashgui/ui/main_window.py +754 -0
  52. pyflashgui/ui/map_view.py +215 -0
  53. pyflashgui/ui/memory_view.py +724 -0
  54. pyflashgui/ui/messages.py +78 -0
  55. pyflashgui/ui/pane_bar.py +92 -0
  56. pyflashgui/ui/panes.py +1068 -0
  57. pyflashgui/ui/persist.py +132 -0
  58. pyflashgui/ui/probe_bar.py +315 -0
  59. pyflashgui/ui/read_dialog.py +161 -0
  60. pyflashgui/ui/session.py +53 -0
  61. pyflashgui/ui/theme.py +85 -0
  62. pyflashgui-0.1.0.dist-info/METADATA +80 -0
  63. pyflashgui-0.1.0.dist-info/RECORD +68 -0
  64. pyflashgui-0.1.0.dist-info/WHEEL +5 -0
  65. pyflashgui-0.1.0.dist-info/entry_points.txt +2 -0
  66. pyflashgui-0.1.0.dist-info/licenses/LICENSE +202 -0
  67. pyflashgui-0.1.0.dist-info/licenses/NOTICE +30 -0
  68. pyflashgui-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,46 @@
1
+ [← Contents](manual.md)
2
+
3
+ # Changes
4
+
5
+ What each version of pyflashgui added, changed and fixed, newest first. The format is [Keep a
6
+ Changelog](https://keepachangelog.com/en/1.1.0/), and versions are numbered as [Semantic
7
+ Versioning](https://semver.org/spec/v2.0.0.html) describes. *Unreleased* is what has been done
8
+ since the last version, and comes out in the next one.
9
+
10
+ ## [Unreleased]
11
+
12
+ ## [0.1.0] - 2026-10-11
13
+
14
+ ### Added
15
+
16
+ - **Probe and target** in a bar across the top: the probe by its serial number, the
17
+ target by name, the debug clock, and Connect. A simulated probe and target for trying
18
+ pyflashgui with no hardware.
19
+ - **J-Link Commander** as a second way to a probe: a J-Link, through SEGGER's own
20
+ software, for the devices beyond Cortex-M that it supports. SEGGER's software is not
21
+ included.
22
+ - **Files**: a list of what is open -- ELF, Intel HEX, S-record and raw binary files, read
23
+ again at each use and whenever one changes on disc, and what has been read from a
24
+ target -- with a map underneath of where the ticked ones land, and Program, Verify,
25
+ Erase, Reset and Read. A read can be ticked and written like a file, and any two
26
+ entries can be compared.
27
+ - **Memory**: the bytes of each file and each read, as addresses, bytes and text, in a
28
+ pane of its own that can be docked and tabbed, with a search for
29
+ bytes or text and a way to an address. A read is saved from there as a raw binary,
30
+ Intel HEX or S-record file, and is asked about before it is let go of unsaved.
31
+ Through J-Link Commander, a read can leave out SEGGER's own setting up of the device, for
32
+ a part where that changes its RAM.
33
+ - **A notice at the start**, each time, saying what programming a device can do and
34
+ what to check first. The libraries load behind it.
35
+ - **Erase...**: all of a target's flash, some of its regions, or a range of addresses.
36
+ - **What the chosen target is**, at the foot of the window: its maker, its core where known,
37
+ and how much flash and RAM it has.
38
+ - **Memory Map**: where the ticked files land on the chosen target, how full each flash
39
+ region is, and what is wrong, worked out before anything is sent.
40
+ - The application's frame: the main window with dockable panes and the Event Log, workspaces,
41
+ light and dark themes, the manual, and the Help menu with diagnostics, licences and a check
42
+ for updates.
43
+ - Launchers for a source folder on Windows and Linux, and the build of the Windows installer.
44
+
45
+ [Unreleased]: https://github.com/davhodg/pyflashgui/compare/v0.1.0...HEAD
46
+ [0.1.0]: https://github.com/davhodg/pyflashgui/releases/tag/v0.1.0
@@ -0,0 +1,60 @@
1
+ [← Contents](manual.md)
2
+
3
+ # Files
4
+
5
+ The **Files** pane is the list of what is open, a map of where it lands, and the buttons that use it. What is open is firmware files and what has been read from a target, and the two are treated alike: each is bytes at addresses, to look at, to compare and to write.
6
+
7
+ ## The list
8
+
9
+ **Add...** puts a firmware file on the list, and **Read...** puts what it reads from the target there, as *Read 1*, *Read 2* and so on. Each row says what it is, where it came from, the addresses it runs from and to, and its size. **Remove** takes the selected ones off: a file itself is left alone, and a read that has not been saved is asked about first.
10
+
11
+ Each has a tick: only what is ticked is programmed, verified and shown in the [memory map](memory-map.md) underneath. A file is ticked when it is added. **A read is not**, since most are made to be looked at; tick one to write it to a target like a file, beside the files or instead of them. The files are kept in the workspace, so programming a product is choosing its workspace and pressing **Program**. What was read is in memory until it is saved, and is not kept.
12
+
13
+ **Show**, or a double click, shows the bytes of an entry in a [Memory](memory.md) pane. One opens by itself for each file and each read as it joins the list.
14
+
15
+ **Compare** compares the two entries that are selected -- two reads, two files, or one of each -- and marks where they differ in a Memory pane. Ctrl+click selects the second. See [Comparing](memory.md).
16
+
17
+ | Format | Addresses |
18
+ |---|---|
19
+ | ELF (`.elf`, `.axf`, `.out`) | In the file. Read at its load addresses, which is where initialised data is stored in flash. |
20
+ | Intel HEX (`.hex`) | In the file. |
21
+ | Motorola S-record (`.s19`, `.s28`, `.s37`, `.srec`) | In the file. |
22
+ | Raw binary (`.bin`) | None. Type where it starts into **Address**, in hexadecimal. |
23
+
24
+ The format is told from what is in the file, not from its name.
25
+
26
+ **A raw binary cannot be read until it has an address.** It is bytes and nothing else, and pyflashgui does not guess at zero. Double-click its **Address** and type one, such as `08000000`.
27
+
28
+ **A file is read again every time it is used**, and whenever it changes on disc, so the list, the memory map and the file's Memory pane follow each build and **Program** always sends what the file holds now. A file that cannot be read says *Cannot be read* in the list; hover over it for why.
29
+
30
+ ## Program, Verify, Erase, Reset, Read
31
+
32
+ These need a probe [connected](probe.md) to a target.
33
+
34
+ - **Program** writes what is ticked: files, reads, or both. Before it starts, they are checked against the target's memory and against each other, as the [memory map](memory-map.md) shows: if anything is an error there -- two of them writing the same addresses is one -- nothing is programmed and the [Event Log](manual.md) says why.
35
+ - **Verify** reads the flash back and compares it with what is ticked, changing nothing. If they differ, it says how many bytes do and where the first one is.
36
+ - **Erase...** erases the target's flash: all of it, some of its regions, or a range of addresses. See *Erasing* below.
37
+ - **Reset** restarts the target.
38
+ - **Read...** reads part of the target's memory back, changing nothing in the target. What is read joins the list and is shown in a [Memory](memory.md) pane of its own. It can be saved to a file from there.
39
+
40
+ Three ticks say what **Program** does besides writing:
41
+
42
+ - **Erase everything first** erases all of the flash before programming, so nothing of what was there is left. Without it, only the sectors the files write to are erased and the rest of the flash is kept.
43
+ - **Verify** reads the flash back afterwards and compares it.
44
+ - **Reset** restarts the target afterwards, so the new firmware runs. It is not reset if verifying failed.
45
+
46
+ **Program and Erase ask first**, once a session for each target, because what they replace cannot be got back. The question can be told not to ask again; *Tools > Reset > Re-enable all confirmations* brings it back. The simulated target is not asked about.
47
+
48
+ The bar beside the buttons says what is being done and how far along it is; where that cannot be told, it shows only that something is happening. **Cancel** stops a verify or a read. Programming is not stopped part way: that would leave the target holding neither the old firmware nor the new.
49
+
50
+ ## Erasing
51
+
52
+ **Erase...** asks how much, and opens on **All of the flash**.
53
+
54
+ - **These regions** lists the target's flash regions, each with a tick. It is for a device with more than one flash, where the bootloader or the data is to be kept.
55
+ - **This range** takes an address and a length, in hexadecimal.
56
+
57
+ Flash is erased a sector at a time, so every sector that any of a range falls in is erased whole: a range of sixteen bytes costs the sector they are in. Where the target's memory is not known there are no regions to tick, and the choice is all of it or a range.
58
+
59
+ Before anything is erased, pyflashgui says which addresses will go and asks, as it does before programming.
60
+
Binary file
@@ -0,0 +1,44 @@
1
+ # pyflashgui manual
2
+
3
+ pyflashgui is a graphical flash programming tool: for Arm Cortex-M targets with any debug probe pyOCD supports, and for the many other devices a J-Link reaches through SEGGER's J-Link Commander.
4
+
5
+ ![pyflashgui on its simulated probe: the Files pane with a firmware file and a read, the memory map under them, the bytes of the read beside them, and the Event Log below](main-window.png)
6
+
7
+ **It is a tool for the bench**: for development, debugging and hobby use. It is not meant for production programming.
8
+
9
+ ## Contents
10
+
11
+ - [Probe and target](probe.md): the bar across the top, connecting, and which probes need what
12
+ - [Files](files.md): what is open, files and reads alike, and Program, Verify, Erase, Reset, Read and Compare
13
+ - [Memory map](memory-map.md): where what is ticked lands, checked before anything is sent
14
+ - [Memory](memory.md): the bytes of a file or of what was read back, to look at, compare and save
15
+ - [About, licences and updates](about.md)
16
+ - [Changes](changelog.md)
17
+
18
+ ## In short
19
+
20
+ 1. Choose the **Probe** and the **Target** in the bar across the top.
21
+ 2. **Add...** the firmware files in the Files pane.
22
+ 3. Look at the memory map under the list: it says whether they fit the target.
23
+ 4. **Connect**, then **Program**.
24
+
25
+ With no hardware, choose *Simulated* under **Through** and the same steps work on a target that exists only in memory.
26
+
27
+ ## The window
28
+
29
+ Everything pyflashgui has to say arrives in the **Event Log**, with warnings and errors in their own colours. A warning or an error opens the pane if it has been closed; an ordinary note does not. Right-click in it to clear it.
30
+
31
+ Each pane can be dragged to another edge of the window, floated, or closed, and **View** brings one back. *View > Reset layout* puts every pane back where it starts and the window back to the size it opens at.
32
+
33
+ *Tools > Settings > Theme* chooses light, dark, or whichever the operating system is set to.
34
+
35
+ ## Where your files are
36
+
37
+ The probe, the target, the list of files, the arrangement of the panes and pyflashgui's settings are kept in a workspace, a folder under pyflashgui's own:
38
+
39
+ | | |
40
+ |---|---|
41
+ | Windows | `%APPDATA%\pyflashgui` |
42
+ | Linux | `~/.config/pyflashgui` |
43
+
44
+ *Tools > Open workspace folder* opens it.
@@ -0,0 +1,28 @@
1
+ [← Contents](manual.md)
2
+
3
+ # Memory Map
4
+
5
+ The **memory map** is the lower part of the [Files](files.md) pane. It shows what the ticked entries of the list above it -- files, and reads that have been ticked -- will write, and where, on the [target](probe.md) that is chosen. It is worked out before anything is sent, from the same bytes that will be sent, so a file linked for the wrong part is found here and not half way through programming a board. The bar between the list and the map can be dragged to give either more room.
6
+
7
+ From top to bottom:
8
+
9
+ - **What is wrong**, if anything is. Each line begins *Error* or *Warning*.
10
+ - **How full each flash region is**: the bytes the files write, out of the region's size, and how many sectors are erased to make room for them. A sector is erased whole, so one byte in a sector costs all of it.
11
+ - **Every piece of every file**: where it starts and ends, how big it is, and the region it lands in.
12
+
13
+ ## What it finds
14
+
15
+ | | |
16
+ |---|---|
17
+ | **Error:** outside the target's memory | The file has bytes at addresses this target does not have. It was probably built for another part, or a raw binary has the wrong address. |
18
+ | **Error:** in memory that cannot be written | The bytes land in ROM, or in a region that is another address for the flash and takes no writes. |
19
+ | **Error:** two write the same addresses | Two files, or a file and a read. Whichever was written second would win, and which is second is not something anybody chose. Untick one of them. |
20
+ | **Warning:** in RAM | The bytes are written, and lost at the next reset. Loading a program into RAM to run it is a real thing to do; it is not what a file meant for flash should be doing. |
21
+
22
+ With an error showing, **Program** refuses. A warning does not stop it.
23
+
24
+ With *J-Link Commander*, bytes outside the memory listed for the device are a **warning** and not an error. SEGGER's list says where a device's memory is and may not give every address it can be reached at -- flash that also appears at a second address is listed once -- so pyflashgui does not refuse what SEGGER's software may take. That list does not say how flash is divided into sectors either, so for these devices the map says how full a region is and not how much is erased.
25
+
26
+ ## When the memory is not known
27
+
28
+ A target that pyOCD has built in has its memory known as soon as it is chosen. One that comes from a CMSIS-Pack is known once it is connected to; until then the pieces are listed, files that overlap are still found, and the pane says that nothing has been checked against the target.
@@ -0,0 +1,59 @@
1
+ [← Contents](manual.md)
2
+
3
+ # Memory
4
+
5
+ A **Memory** pane shows the bytes of one entry of the [Files](files.md) list -- a firmware file, or what was read from a target: sixteen bytes to a row, with the address of the first, the bytes in hexadecimal, and the characters they spell. Each entry has a pane of its own, opened when it joins the list. Each is called what the list calls it: the file's name, or *Read 1*, *Read 2* and so on.
6
+
7
+ A file in several pieces, with nothing between them, is shown piece after piece: each starts a row of its own at its own address, and the gaps are not shown.
8
+
9
+ Memory panes open beside the Files pane, as tabs of one another. Each is a pane like any other: it can be docked at an edge, tabbed with another pane, or given a window of its own, and **View** lists it. A new one opens as a tab with the last that is docked in the window, so moving one moves where the rest arrive.
10
+
11
+ **Closing a Memory pane loses nothing.** What it showed is still on the Files list, and **Show** there, or a double click, opens it again. It is taking a read off that list, or closing pyflashgui, that would lose one that has not been saved, and both say so first and offer to save it, to discard it, or to keep it. The pane of a file follows the file: when a build writes it again, the pane shows what it holds now.
12
+
13
+ ## Reading
14
+
15
+ **Read...**, in the [Files](files.md) pane or in a Memory pane, asks what to read. It needs a probe [connected](probe.md) to a target, and changes nothing in the target.
16
+
17
+ - **Region** offers the target's own regions, the flash first, and fills in the address and the length. Both can be typed over, in hexadecimal: what is wanted is as often the first few kilobytes as the whole region.
18
+ - Where the target's memory is not known, as for a device whose name was typed and is not on the backend's list, there are no regions to choose and the range is typed.
19
+ - **Leave the device as it is (skip J-Link's own set-up)** is offered with J-Link Commander only. On connecting, SEGGER's software sets some devices up in ways that change them: on an S32K3 it fills the RAM, so a read made to see what a running program left there finds it gone. With this ticked, that set-up is left out for this read. It is not ticked to begin with, and wants leaving alone unless that is the trouble: on a part whose set-up is what lets it be read at all, a read without it fails. Programming and erasing always have the set-up.
20
+
21
+ What is read is kept in memory, joins the Files list and is shown in a new pane. The line above the bytes says which target it came from, the range and when. The bar in the Files pane shows how far along a read is, and **Cancel** there stops it.
22
+
23
+ A device that protects its flash from being read gives an error from the probe, or reads as something other than what it holds. pyflashgui does not try to get round that.
24
+
25
+ ## Finding your way about
26
+
27
+ Both of these work on what is shown, and read nothing more from the target.
28
+
29
+ - **Go to** takes an address in hexadecimal and, on Enter, goes to the row it is on. An address outside what was read is said, with the range that was.
30
+ - **Find** looks for **Bytes**, typed in hexadecimal, or for **Text**, as it is spelled. Bytes can be typed however is convenient: `DE AD BE EF`, `DEADBEEF` and `0xDE, 0xAD, 0xBE, 0xEF` are the same four. Text is matched exactly, capitals included. Enter or **Next** finds the next, **Previous** the one before, and the search goes round from the end to the start, saying so when it does.
31
+
32
+ The line under the boxes says the address of what was found. The row is selected as well, but a row is sixteen bytes and the address is the one that was meant.
33
+
34
+ | | |
35
+ |---|---|
36
+ | Ctrl+F | Find |
37
+ | F3, Shift+F3 | The next, and the one before |
38
+ | Ctrl+G | Go to an address |
39
+
40
+ The keys work in the Memory pane that is being used.
41
+
42
+ ## Comparing
43
+
44
+ **Compare**, in the [Files](files.md) pane, compares the two entries selected there: two reads, two files, or a read and a file. One of them is shown, marked where the other differs from it. Of a read and a file it is the read that is shown, the file being what the target is held against; of two of a kind, the one higher in the list. Nothing is read from the target. It is the question [Verify](files.md) asks, of any stretch of memory and at any time after it was read.
45
+
46
+ - **Only where the two overlap is compared.** Two of them rarely cover the same addresses. What the other has outside what is shown, and what is shown that the other says nothing about, are each counted and said, and neither is a difference.
47
+ - **A line says what was found**: how many bytes were compared, how many differ and where the first is. The same line goes to the Event Log.
48
+ - **A column appears, headed with the other's name**, with something in it on each row that differs: the other's own bytes where they differ, `..` for a byte that agrees and `--` for one the other does not mention. A row that agrees throughout is left blank.
49
+ - **Next difference** and **Previous difference** go from one stretch of differing bytes to the next, going round, and say where it is and what each side has.
50
+
51
+ To compare with a file that is not on the list, add it; untick it if it is not to be programmed. A raw binary has no addresses of its own, so it needs its address typed in the list before it can be compared. The comparison is that pane's, and showing something else in it, or the file changing, puts it away.
52
+
53
+ ## Saving
54
+
55
+ **Save...** writes what is shown to a file: a raw binary, Intel HEX or Motorola S-record, by the name it is given. Nothing is saved until this is pressed, so a read made only to look costs no file. Once it has been saved, the Files list no longer says *not saved*, and it is removed without asking. Save is for what is in one piece, as everything read from a target is.
56
+
57
+ - A raw binary is the bytes and nothing else, so it does not record where they came from. The other two do, and can be put on the [Files](files.md) list and programmed back as they are.
58
+ - An S-record file is given addresses wide enough for what it holds, whatever its name: flash at `08000000` saved as `.s19` has 32-bit addresses.
59
+ - **Leave off the erased bytes at the end** is for a read of more than is there. Erased flash reads as `FF`, so the whole of a 1 MiB flash holding 100 KiB of firmware saves as 1 MiB. With this ticked, the file ends at the last byte that holds something; an `FF` in the middle of what is there is kept. It is not ticked to begin with, so that what is saved is what was read.
@@ -0,0 +1,71 @@
1
+ [← Contents](manual.md)
2
+
3
+ # Probe and target
4
+
5
+ The bar across the top of the window says what pyflashgui is connected through and what to. Everything else in the window depends on it.
6
+
7
+ | | |
8
+ |---|---|
9
+ | **Through** | What reaches the probe. *pyOCD* works with many probes and Cortex-M devices. *J-Link Commander* works with a J-Link and every device SEGGER's software knows. *Simulated* is a probe and a target that exist only in memory, for trying pyflashgui with no hardware. |
10
+ | **Probe** | The debug probe, by its description and serial number. **Refresh** looks again for what is plugged in. |
11
+ | **Target** | The device on the end of the probe. Type any part of its name to find it. |
12
+ | **Speed** | How fast the probe clocks the debug port. *Probe's own* leaves it to the probe. |
13
+ | **Interface** | With J-Link Commander only: how the probe is wired to the device. |
14
+ | **Connect** | Attaches the probe to the target, and becomes **Disconnect**. |
15
+
16
+ The bar at the foot of the window says what is known of the target that is chosen: who makes it, its core where that is known, and how much flash and RAM it has.
17
+
18
+ What is chosen is kept in the [workspace](manual.md): the target and the speed belong to the product being worked on, and the probe is remembered by its serial number, so a bench with two probes on it connects through the same one each time.
19
+
20
+ ## Connecting
21
+
22
+ **The target is stopped while it is connected**, and runs again when it is disconnected or reset. Connecting to a device that is doing something is therefore not free: it stops doing it.
23
+
24
+ If connecting fails, the [Event Log](manual.md) says what the probe reported. The usual causes are the target not being powered, the wrong target chosen, or a cable too long for the speed: try a lower **Speed**.
25
+
26
+ ## Targets
27
+
28
+ The list is every target pyOCD has built in, and every device in the CMSIS-Packs installed on this computer. A target that is built in has its memory known before anything is connected, so the [Memory Map](memory-map.md) can check the files against it straight away. One from a pack is checked once it is connected to.
29
+
30
+ ## J-Link Commander
31
+
32
+ Choosing *J-Link Commander* under **Through** uses a J-Link by way of SEGGER's own command line program, which comes with SEGGER's J-Link software. It reaches every device that software knows, which is far more than Cortex-M: Cortex-A and Cortex-R, RISC-V and others. The price is that it works with a J-Link and nothing else, and needs SEGGER's software installed.
33
+
34
+ - **SEGGER's software is yours to install**, and its licence is between you and SEGGER. pyflashgui never carries it. It is for genuine SEGGER probes, and SEGGER describes J-Link Commander as a tool for development, not for production programming.
35
+ - **Target** is the device's name as SEGGER's software has it, such as `STM32F103ZE`. The list is read from that software, with each device's maker, core and memory; a name not on it can be typed.
36
+ - **Interface** appears for this choice only: SWD, JTAG, cJTAG or FINE, as the device is wired.
37
+ - **The Memory Map goes by SEGGER's list of the device's memory**, which says where its flash and RAM are and may not give every address they can be reached at. So a file outside what is listed is a warning and not a refusal, and SEGGER's software has the last word. The list does not say how the flash is divided into sectors, so the map does not say how much is erased.
38
+ - **The bar shows that something is happening, not how far along it is**, since J-Link Commander does not say.
39
+ - **A read can leave the device as it is.** SEGGER's software sets some devices up on connecting in ways that change them; the [Read](memory.md) dialog has a tick to leave that out.
40
+ - **Connect** checks that the probe and the device answer. Nothing is held open between one operation and the next; each attaches again by itself.
41
+
42
+ If pyflashgui does not find J-Link Commander, *Tools > Settings > J-Link Commander location...* says where it is.
43
+
44
+ **Tried on one board so far.** Listing the probe, connecting and reading were tried on an XMC4500 through its on-board J-Link, and what was read matched SEGGER's own tool. Programming, erasing and resetting this way have not yet been tried on a probe.
45
+
46
+ ## Probes with pyOCD
47
+
48
+ With *pyOCD* chosen, every probe is reached through pyOCD, which has a driver for each of the ways a probe talks over USB. Which probes work is therefore pyOCD's list:
49
+
50
+ | Probe | How pyOCD talks to it | What to install | Worth knowing |
51
+ |---|---|---|---|
52
+ | **CMSIS-DAP probes** | Arm's open CMSIS-DAP protocol | Windows: nothing. Linux: a udev rule. | The widest choice, and the one to pick when there is a choice. |
53
+ | **ST-Link** v2, v2-1 and v3 | ST's own protocol | Windows: ST's USB driver, where Windows has none for it. Linux: a udev rule. | Recent ST-Link firmware reaches only STM32 targets: for any other maker's device, use another probe. Firmware V2J24 or newer. |
54
+ | **J-Link** | SEGGER's own library, or CMSIS-DAP for a J-Link switched to that mode | SEGGER's J-Link software, on Windows and on Linux. | In its own mode it is not offered until that software is installed. Current J-Link BASE, PLUS, EDU, ULTRA+ and PRO models can be set to start as a CMSIS-DAP probe instead, with SEGGER's Configurator, and are then used like any other. |
55
+ | **Picoprobe** | The original Raspberry Pi Pico probe firmware | Linux: a udev rule. | The Pico's current debug probe firmware is CMSIS-DAP instead, and is the one to have. |
56
+
57
+ CMSIS-DAP is a protocol and not a product, so a great many probes speak it. Among those pyOCD's documentation names:
58
+
59
+ - Raspberry Pi Debug Probe, and a Pico running the debug probe firmware
60
+ - DAPLink, on its own and built into Arm Mbed and micro:bit boards
61
+ - NXP MCU-Link, MCU-Link Pro, LPC-Link2 and OpenSDA
62
+ - Microchip Atmel-ICE, and the EDBG on Microchip's boards
63
+ - Infineon (Cypress) KitProg3 and MiniProg4
64
+ - Keil ULINKplus
65
+ - TI XDS110, standalone and on TI LaunchPads. It is asked for one reply at a time, which some versions of its firmware need; pyflashgui sets that itself. pyOCD's udev rules do not include it, so on Linux it wants a rule of its own or the one TI's software installs.
66
+
67
+ **The target has to be an Arm Cortex-M, whichever probe it is.** The probe carries the debug port; what is on the far side of it is pyOCD's to understand, and Cortex-M is what it understands. A probe that can reach other kinds of processor with its maker's own software still reaches only Cortex-M here.
68
+
69
+ On Linux a probe is usable without root once a udev rule allows it; pyOCD publishes [a set of them](https://github.com/pyocd/pyOCD/tree/main/udev).
70
+
71
+ Vendor software is never bundled with pyflashgui: install the vendor's own, and pyflashgui finds the probe.
@@ -0,0 +1,10 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # SPDX-FileCopyrightText: 2026 davhodg
3
+ """Data files shipped with pyflashgui (icons ...)."""
4
+
5
+ from importlib import resources
6
+ from pathlib import Path
7
+
8
+
9
+ def path(name: str) -> Path:
10
+ return Path(str(resources.files(__name__) / name))
Binary file
Binary file
@@ -0,0 +1,32 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 256 256">
2
+ <!-- SPDX-License-Identifier: Apache-2.0 -->
3
+ <!-- SPDX-FileCopyrightText: 2026 davhodg -->
4
+ <!-- pyflashgui icon, 32 px and up: a chip with four pins a side and a flash
5
+ across it. Below 32 px four pins a side blur into a fringe, so
6
+ pyflashgui_small.svg draws two heavier ones. build/icon.py renders both
7
+ into pyflashgui.ico and pyflashgui.png. -->
8
+ <rect x="0" y="0" width="256" height="256" rx="40" fill="#151b1d"/>
9
+ <!-- pins, drawn first so the body's outline covers their inner ends -->
10
+ <g stroke="#2FD9C4" stroke-width="12" stroke-linecap="round">
11
+ <line x1="38" y1="89" x2="70" y2="89"/>
12
+ <line x1="38" y1="115" x2="70" y2="115"/>
13
+ <line x1="38" y1="141" x2="70" y2="141"/>
14
+ <line x1="38" y1="167" x2="70" y2="167"/>
15
+ <line x1="186" y1="89" x2="218" y2="89"/>
16
+ <line x1="186" y1="115" x2="218" y2="115"/>
17
+ <line x1="186" y1="141" x2="218" y2="141"/>
18
+ <line x1="186" y1="167" x2="218" y2="167"/>
19
+ <line x1="89" y1="38" x2="89" y2="70"/>
20
+ <line x1="115" y1="38" x2="115" y2="70"/>
21
+ <line x1="141" y1="38" x2="141" y2="70"/>
22
+ <line x1="167" y1="38" x2="167" y2="70"/>
23
+ <line x1="89" y1="186" x2="89" y2="218"/>
24
+ <line x1="115" y1="186" x2="115" y2="218"/>
25
+ <line x1="141" y1="186" x2="141" y2="218"/>
26
+ <line x1="167" y1="186" x2="167" y2="218"/>
27
+ </g>
28
+ <!-- the body: outlined rather than filled, so the flash has the dark behind it -->
29
+ <rect x="68" y="68" width="120" height="120" rx="14" fill="#151b1d" stroke="#EDEAE2" stroke-width="12"/>
30
+ <!-- the flash -->
31
+ <path d="M140,84 L100,134 H124 L114,172 L156,120 H131 Z" fill="#F2924B"/>
32
+ </svg>
@@ -0,0 +1,20 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 256 256">
2
+ <!-- SPDX-License-Identifier: Apache-2.0 -->
3
+ <!-- SPDX-FileCopyrightText: 2026 davhodg -->
4
+ <!-- pyflashgui icon, 24 px and below: pyflashgui.svg with two heavy pins a
5
+ side where the large drawing has four, a heavier outline and a larger
6
+ flash, which is what survives at this size. -->
7
+ <rect x="0" y="0" width="256" height="256" rx="40" fill="#151b1d"/>
8
+ <g stroke="#2FD9C4" stroke-width="22" stroke-linecap="round">
9
+ <line x1="30" y1="100" x2="62" y2="100"/>
10
+ <line x1="30" y1="156" x2="62" y2="156"/>
11
+ <line x1="194" y1="100" x2="226" y2="100"/>
12
+ <line x1="194" y1="156" x2="226" y2="156"/>
13
+ <line x1="100" y1="30" x2="100" y2="62"/>
14
+ <line x1="156" y1="30" x2="156" y2="62"/>
15
+ <line x1="100" y1="194" x2="100" y2="226"/>
16
+ <line x1="156" y1="194" x2="156" y2="226"/>
17
+ </g>
18
+ <rect x="60" y="60" width="136" height="136" rx="14" fill="#151b1d" stroke="#EDEAE2" stroke-width="18"/>
19
+ <path d="M146,78 L94,136 H124 L110,180 L164,118 H133 Z" fill="#F2924B"/>
20
+ </svg>
@@ -0,0 +1,2 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # SPDX-FileCopyrightText: 2026 davhodg