Repository: probe-rs/probe-rs
Pull request #2370 (2024-04-15 11:39:11)

Provide a bit more info in some low-level Xtensa errors


Patch:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index d02d1b2c..c0dbb7a0 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,4 +1,4 @@
-# Copyright 2022-2023, axodotdev
+# Copyright 2022-2024, axodotdev
 # SPDX-License-Identifier: MIT or Apache-2.0
 #
 # CI that:
@@ -6,9 +6,9 @@
 # * checks for a Git Tag that looks like a release
 # * builds artifacts with cargo-dist (archives, installers, hashes)
 # * uploads those artifacts to temporary workflow zip
-# * on success, uploads the artifacts to a Github Release
+# * on success, uploads the artifacts to a GitHub Release
 #
-# Note that the Github Release will be created with a generated
+# Note that the GitHub Release will be created with a generated
 # title/body based on your changelogs.
 
 name: Release
@@ -31,7 +31,7 @@ permissions:
 # packages versioned/released in lockstep).
 #
 # If you push multiple tags at once, separate instances of this workflow will
-# spin up, creating an independent announcement for each one. However Github
+# spin up, creating an independent announcement for each one. However, GitHub
 # will hard limit this to 3 tags per commit, as it will assume more tags is a
 # mistake.
 #
@@ -62,7 +62,7 @@ jobs:
         # we specify bash to get pipefail; it guards against the `curl` command
         # failing. otherwise `sh` won't catch that `curl` returned non-0
         shell: bash
-        run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.11.1/cargo-dist-installer.sh | sh"
+        run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.13.0/cargo-dist-installer.sh | sh"
       # sure would be cool if github gave us proper conditionals...
       # so here's a doubly-nested ternary-via-truthiness to try to provide the best possible
       # functionality based on whether this is a pull_request, and whether it's from a fork.
@@ -135,7 +135,7 @@ jobs:
         run: |
           # Parse out what we just built and upload it to scratch storage
           echo "paths<<EOF" >> "$GITHUB_OUTPUT"
-          jq --raw-output ".artifacts[]?.path | select( . != null )" dist-manifest.json >> "$GITHUB_OUTPUT"
+          jq --raw-output ".upload_files[]" dist-manifest.json >> "$GITHUB_OUTPUT"
           echo "EOF" >> "$GITHUB_OUTPUT"
 
           cp dist-manifest.json "$BUILD_MANIFEST_NAME"
@@ -162,7 +162,7 @@ jobs:
           submodules: recursive
       - name: Install cargo-dist
         shell: bash
-        run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.11.1/cargo-dist-installer.sh | sh"
+        run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.13.0/cargo-dist-installer.sh | sh"
       # Get all the local artifacts for the global tasks to use (for e.g. checksums)
       - name: Fetch local artifacts
         uses: actions/download-artifact@v4
@@ -178,7 +178,7 @@ jobs:
 
           # Parse out what we just built and upload it to scratch storage
           echo "paths<<EOF" >> "$GITHUB_OUTPUT"
-          jq --raw-output ".artifacts[]?.path | select( . != null )" dist-manifest.json >> "$GITHUB_OUTPUT"
+          jq --raw-output ".upload_files[]" dist-manifest.json >> "$GITHUB_OUTPUT"
           echo "EOF" >> "$GITHUB_OUTPUT"
 
           cp dist-manifest.json "$BUILD_MANIFEST_NAME"
@@ -207,7 +207,7 @@ jobs:
         with:
           submodules: recursive
       - name: Install cargo-dist
-        run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.11.1/cargo-dist-installer.sh | sh"
+        run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.13.0/cargo-dist-installer.sh | sh"
       # Fetch artifacts from scratch-storage
       - name: Fetch artifacts
         uses: actions/download-artifact@v4
@@ -215,7 +215,7 @@ jobs:
           pattern: artifacts-*
           path: target/distrib/
           merge-multiple: true
-      # This is a harmless no-op for Github Releases, hosting for that happens in "announce"
+      # This is a harmless no-op for GitHub Releases, hosting for that happens in "announce"
       - id: host
         shell: bash
         run: |
@@ -270,7 +270,7 @@ jobs:
           done
           git push
 
-  # Create a Github Release while uploading all files to it
+  # Create a GitHub Release while uploading all files to it
   announce:
     needs:
       - plan
@@ -287,7 +287,7 @@ jobs:
       - uses: actions/checkout@v4
         with:
           submodules: recursive
-      - name: "Download Github Artifacts"
+      - name: "Download GitHub Artifacts"
         uses: actions/download-artifact@v4
         with:
           pattern: artifacts-*
@@ -297,7 +297,7 @@ jobs:
         run: |
           # Remove the granular manifests
           rm -f artifacts/*-dist-manifest.json
-      - name: Create Github Release
+      - name: Create GitHub Release
         uses: ncipollo/release-action@v1
         with:
           tag: ${{ needs.plan.outputs.tag }}
diff --git a/Cargo.lock b/Cargo.lock
index 57d53546..92c14e4f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -17,12 +17,21 @@ name = "addr2line"
 version = "0.21.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
+dependencies = [
+ "gimli 0.28.1",
+]
+
+[[package]]
+name = "addr2line"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
 dependencies = [
  "cpp_demangle",
  "fallible-iterator",
- "gimli",
+ "gimli 0.29.0",
  "memmap2",
- "object 0.32.2",
+ "object 0.35.0",
  "rustc-demangle",
  "smallvec",
 ]
@@ -78,9 +87,9 @@ dependencies = [
 
 [[package]]
 name = "allocator-api2"
-version = "0.2.16"
+version = "0.2.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
+checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
 
 [[package]]
 name = "ansi-parser"
@@ -142,9 +151,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.81"
+version = "1.0.82"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247"
+checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
 
 [[package]]
 name = "arrayvec"
@@ -232,13 +241,13 @@ dependencies = [
 
 [[package]]
 name = "async-trait"
-version = "0.1.79"
+version = "0.1.80"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681"
+checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -258,9 +267,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
 
 [[package]]
 name = "autocfg"
-version = "1.1.0"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
 
 [[package]]
 name = "backtrace"
@@ -268,7 +277,7 @@ version = "0.3.71"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
 dependencies = [
- "addr2line",
+ "addr2line 0.21.0",
  "cc",
  "cfg-if",
  "libc",
@@ -306,9 +315,9 @@ dependencies = [
 
 [[package]]
 name = "bitfield"
-version = "0.14.0"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac"
+checksum = "c821a6e124197eb56d907ccc2188eab1038fb919c914f47976e64dd8dbc855d1"
 
 [[package]]
 name = "bitflags"
@@ -367,9 +376,9 @@ dependencies = [
 
 [[package]]
 name = "borsh"
-version = "1.3.1"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f58b559fd6448c6e2fd0adb5720cd98a2506594cafa4737ff98c396f3e82f667"
+checksum = "0901fc8eb0aca4c83be0106d6f2db17d86a08dfc2c25f0e84464bf381158add6"
 dependencies = [
  "borsh-derive",
  "cfg_aliases",
@@ -377,15 +386,15 @@ dependencies = [
 
 [[package]]
 name = "borsh-derive"
-version = "1.3.1"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7aadb5b6ccbd078890f6d7003694e33816e6b784358f18e15e7e6d9f065a57cd"
+checksum = "51670c3aa053938b0ee3bd67c3817e471e626151131b934038e83c5bf8de48f5"
 dependencies = [
  "once_cell",
  "proc-macro-crate 3.1.0",
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
  "syn_derive",
 ]
 
@@ -402,9 +411,9 @@ dependencies = [
 
 [[package]]
 name = "bumpalo"
-version = "3.15.4"
+version = "3.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa"
+checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
 
 [[package]]
 name = "byte-unit"
@@ -456,7 +465,7 @@ checksum = "4da9a32f3fed317401fa3c862968128267c3106685286e15d5aaa3d7389c2f60"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -529,9 +538,9 @@ dependencies = [
 
 [[package]]
 name = "cargo-config2"
-version = "0.1.23"
+version = "0.1.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42c11223b5229031d9b4ad2125ac8794386a2891a5c02acc4240bc46dd3af4f9"
+checksum = "88d9bdc858a15454c2d0a5138d8dcf4bcabc06fde679abdea8330393fbc0ef05"
 dependencies = [
  "home",
  "serde",
@@ -579,9 +588,9 @@ dependencies = [
 
 [[package]]
 name = "cc"
-version = "1.0.90"
+version = "1.0.94"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
+checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7"
 dependencies = [
  "jobserver",
  "libc",
@@ -601,9 +610,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
 
 [[package]]
 name = "chrono"
-version = "0.4.35"
+version = "0.4.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a"
+checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
 dependencies = [
  "num-traits",
 ]
@@ -620,9 +629,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.5.3"
+version = "4.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813"
+checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -637,19 +646,19 @@ dependencies = [
  "anstream",
  "anstyle",
  "clap_lex",
- "strsim 0.11.0",
+ "strsim 0.11.1",
 ]
 
 [[package]]
 name = "clap_derive"
-version = "4.5.3"
+version = "4.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f"
+checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
 dependencies = [
  "heck 0.5.0",
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -927,7 +936,7 @@ dependencies = [
  "defmt-json-schema",
  "defmt-parser",
  "dissimilar",
- "gimli",
+ "gimli 0.28.1",
  "log",
  "nom",
  "object 0.32.2",
@@ -1072,7 +1081,7 @@ checksum = "4673f83edb6dfabfbc26704bd89ee95f4b164cd5db5fe8c88efda48fb0fca8d7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -1083,9 +1092,9 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b"
 
 [[package]]
 name = "either"
-version = "1.10.0"
+version = "1.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
+checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
 
 [[package]]
 name = "encode_unicode"
@@ -1095,9 +1104,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
 
 [[package]]
 name = "encoding_rs"
-version = "0.8.33"
+version = "0.8.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
+checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59"
 dependencies = [
  "cfg-if",
 ]
@@ -1117,7 +1126,7 @@ dependencies = [
  "heck 0.4.1",
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -1128,7 +1137,7 @@ checksum = "ba7795da175654fe16979af73f81f26a8ea27638d8d9823d317016888a63dc4c"
 dependencies = [
  "num-traits",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -1243,9 +1252,9 @@ checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
 
 [[package]]
 name = "fastrand"
-version = "2.0.1"
+version = "2.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
+checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984"
 
 [[package]]
 name = "fd-lock"
@@ -1260,9 +1269,9 @@ dependencies = [
 
 [[package]]
 name = "figment"
-version = "0.10.15"
+version = "0.10.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7270677e7067213e04f323b55084586195f18308cd7546cfac9f873344ccceb6"
+checksum = "fdefe49ed1057d124dc81a0681c30dd07de56ad96e32adc7b64e8f28eaab31c4"
 dependencies = [
  "atomic",
  "pear",
@@ -1383,7 +1392,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -1460,9 +1469,9 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.12"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
+checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
 dependencies = [
  "cfg-if",
  "libc",
@@ -1479,6 +1488,16 @@ dependencies = [
  "stable_deref_trait",
 ]
 
+[[package]]
+name = "gimli"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
+dependencies = [
+ "fallible-iterator",
+ "stable_deref_trait",
+]
+
 [[package]]
 name = "git-version"
 version = "0.3.9"
@@ -1496,7 +1515,7 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -1509,7 +1528,7 @@ dependencies = [
  "bstr",
  "log",
  "regex-automata 0.4.6",
- "regex-syntax 0.8.2",
+ "regex-syntax 0.8.3",
 ]
 
 [[package]]
@@ -1830,9 +1849,9 @@ dependencies = [
 
 [[package]]
 name = "hyper"
-version = "1.2.0"
+version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a"
+checksum = "9f24ce812868d86d19daa79bf3bf9175bc44ea323391147a5e3abde2a283871b"
 dependencies = [
  "bytes",
  "futures-channel",
@@ -1869,9 +1888,9 @@ checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c"
 dependencies = [
  "futures-util",
  "http 1.1.0",
- "hyper 1.2.0",
+ "hyper 1.3.0",
  "hyper-util",
- "rustls 0.22.2",
+ "rustls 0.22.3",
  "rustls-pki-types",
  "tokio",
  "tokio-rustls 0.25.0",
@@ -1889,7 +1908,7 @@ dependencies = [
  "futures-util",
  "http 1.1.0",
  "http-body 1.0.0",
- "hyper 1.2.0",
+ "hyper 1.3.0",
  "pin-project-lite",
  "socket2",
  "tokio",
@@ -2100,9 +2119,9 @@ dependencies = [
 
 [[package]]
 name = "itoa"
-version = "1.0.10"
+version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
+checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
 
 [[package]]
 name = "jep106"
@@ -2115,9 +2134,9 @@ dependencies = [
 
 [[package]]
 name = "jobserver"
-version = "0.1.28"
+version = "0.1.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6"
+checksum = "685a7d121ee3f65ae4fddd72b25a04bb36b6af81bc0828f7d5434c0fe60fa3a2"
 dependencies = [
  "libc",
 ]
@@ -2145,20 +2164,19 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
 
 [[package]]
 name = "libredox"
-version = "0.0.1"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
+checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
 dependencies = [
  "bitflags 2.5.0",
  "libc",
- "redox_syscall",
 ]
 
 [[package]]
 name = "libtest-mimic"
-version = "0.7.0"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f0f4c6f44ecfd52e8b443f2ad18f2b996540135771561283c2352ce56a1c70b"
+checksum = "fefdf21230d6143476a28adbee3d930e2b68a3d56443c777cae3fe9340eebff9"
 dependencies = [
  "clap",
  "escape8259",
@@ -2199,7 +2217,7 @@ checksum = "adf157a4dc5a29b7b464aa8fe7edeff30076e07e13646a1c3874f58477dc99f8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -2293,15 +2311,15 @@ checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
 
 [[package]]
 name = "memchr"
-version = "2.7.1"
+version = "2.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
+checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
 
 [[package]]
 name = "memmap2"
-version = "0.5.10"
+version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327"
+checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322"
 dependencies = [
  "libc",
 ]
@@ -2326,7 +2344,7 @@ checksum = "dcf09caffaac8068c346b6df2a7fc27a177fd20b39421a39ce0a211bde679a6c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -2492,18 +2510,18 @@ version = "0.32.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
 dependencies = [
- "flate2",
  "memchr",
- "ruzstd",
 ]
 
 [[package]]
 name = "object"
-version = "0.34.0"
+version = "0.35.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7090bae93f8585aad99e595b7073c5de9ba89fbd6b4e9f0cdd7a10177273ac8"
+checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e"
 dependencies = [
+ "flate2",
  "memchr",
+ "ruzstd",
 ]
 
 [[package]]
@@ -2617,7 +2635,7 @@ dependencies = [
  "proc-macro2",
  "proc-macro2-diagnostics",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -2643,14 +2661,14 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
 name = "pin-project-lite"
-version = "0.2.13"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
+checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
 
 [[package]]
 name = "pin-utils"
@@ -2672,12 +2690,13 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
 
 [[package]]
 name = "polling"
-version = "3.5.0"
+version = "3.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24f040dee2588b4963afb4e420540439d126f73fdacf4a9c486a96d840bac3c9"
+checksum = "e0c976a60b2d7e99d6f229e414670a9b85d13ac305cc6d1e9c134de58c5aaaf6"
 dependencies = [
  "cfg-if",
  "concurrent-queue",
+ "hermit-abi",
  "pin-project-lite",
  "rustix",
  "tracing",
@@ -2756,7 +2775,7 @@ dependencies = [
 name = "probe-rs"
 version = "0.23.0"
 dependencies = [
- "addr2line",
+ "addr2line 0.22.0",
  "ansi-parser",
  "anyhow",
  "async-io",
@@ -2783,7 +2802,7 @@ dependencies = [
  "figment",
  "futures-lite",
  "gdbstub",
- "gimli",
+ "gimli 0.29.0",
  "git-version",
  "goblin",
  "hexdump",
@@ -2798,7 +2817,7 @@ dependencies = [
  "miniz_oxide",
  "num-traits",
  "nusb",
- "object 0.34.0",
+ "object 0.35.0",
  "once_cell",
  "parking_lot",
  "parse_int",
@@ -2885,9 +2904,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.79"
+version = "1.0.80"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
+checksum = "a56dea16b0a29e94408b9aa5e2940a4eedbd128a1ba20e8f7ae60fd3d465af0e"
 dependencies = [
  "unicode-ident",
 ]
@@ -2900,7 +2919,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
  "version_check",
  "yansi 1.0.1",
 ]
@@ -2942,9 +2961,9 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.35"
+version = "1.0.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
 dependencies = [
  "proc-macro2",
 ]
@@ -2997,9 +3016,9 @@ dependencies = [
 
 [[package]]
 name = "ratatui"
-version = "0.26.1"
+version = "0.26.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bcb12f8fbf6c62614b0d56eb352af54f6a22410c3b079eb53ee93c7b97dd31d8"
+checksum = "a564a852040e82671dc50a37d88f3aa83bbc690dfc6844cfe7a2591620206a80"
 dependencies = [
  "bitflags 2.5.0",
  "cassowary",
@@ -3026,9 +3045,9 @@ dependencies = [
 
 [[package]]
 name = "redox_users"
-version = "0.4.4"
+version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4"
+checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891"
 dependencies = [
  "getrandom",
  "libredox",
@@ -3044,7 +3063,7 @@ dependencies = [
  "aho-corasick",
  "memchr",
  "regex-automata 0.4.6",
- "regex-syntax 0.8.2",
+ "regex-syntax 0.8.3",
 ]
 
 [[package]]
@@ -3064,7 +3083,7 @@ checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
 dependencies = [
  "aho-corasick",
  "memchr",
- "regex-syntax 0.8.2",
+ "regex-syntax 0.8.3",
 ]
 
 [[package]]
@@ -3075,9 +3094,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
 
 [[package]]
 name = "regex-syntax"
-version = "0.8.2"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
+checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
 
 [[package]]
 name = "rend"
@@ -3145,7 +3164,7 @@ dependencies = [
  "http 1.1.0",
  "http-body 1.0.0",
  "http-body-util",
- "hyper 1.2.0",
+ "hyper 1.3.0",
  "hyper-rustls 0.26.0",
  "hyper-util",
  "ipnet",
@@ -3155,8 +3174,8 @@ dependencies = [
  "once_cell",
  "percent-encoding",
  "pin-project-lite",
- "rustls 0.22.2",
- "rustls-pemfile 2.1.1",
+ "rustls 0.22.3",
+ "rustls-pemfile 2.1.2",
  "rustls-pki-types",
  "serde",
  "serde_json",
@@ -3267,9 +3286,9 @@ dependencies = [
 
 [[package]]
 name = "rust_decimal"
-version = "1.34.3"
+version = "1.35.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b39449a79f45e8da28c57c341891b69a183044b29518bb8f86dbac9df60bb7df"
+checksum = "1790d1c4c0ca81211399e0e0af16333276f375209e71a37b67698a373db5b47a"
 dependencies = [
  "arrayvec 0.7.4",
  "borsh",
@@ -3314,9 +3333,9 @@ dependencies = [
 
 [[package]]
 name = "rustls"
-version = "0.22.2"
+version = "0.22.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41"
+checksum = "99008d7ad0bbbea527ec27bddbc0e432c5b87d8175178cee68d2eec9c4a1813c"
 dependencies = [
  "log",
  "ring",
@@ -3349,19 +3368,19 @@ dependencies = [
 
 [[package]]
 name = "rustls-pemfile"
-version = "2.1.1"
+version = "2.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f48172685e6ff52a556baa527774f61fcaa884f59daf3375c62a3f1cd2549dab"
+checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d"
 dependencies = [
- "base64 0.21.7",
+ "base64 0.22.0",
  "rustls-pki-types",
 ]
 
 [[package]]
 name = "rustls-pki-types"
-version = "1.4.0"
+version = "1.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "868e20fada228fefaf6b652e00cc73623d54f8171e7352c18bb281571f2d92da"
+checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247"
 
 [[package]]
 name = "rustls-webpki"
@@ -3386,9 +3405,9 @@ dependencies = [
 
 [[package]]
 name = "rustversion"
-version = "1.0.14"
+version = "1.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
+checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47"
 
 [[package]]
 name = "rustyline"
@@ -3414,9 +3433,9 @@ dependencies = [
 
 [[package]]
 name = "ruzstd"
-version = "0.5.0"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58c4eb8a81997cf040a091d1f7e1938aeab6749d3a0dfa73af43cdc32393483d"
+checksum = "5174a470eeb535a721ae9fdd6e291c2411a906b96592182d05217591d5c5cf7b"
 dependencies = [
  "byteorder",
  "derive_more",
@@ -3523,7 +3542,7 @@ checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -3544,9 +3563,9 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
 
 [[package]]
 name = "security-framework"
-version = "2.9.2"
+version = "2.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de"
+checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6"
 dependencies = [
  "bitflags 1.3.2",
  "core-foundation",
@@ -3557,9 +3576,9 @@ dependencies = [
 
 [[package]]
 name = "security-framework-sys"
-version = "2.9.1"
+version = "2.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a"
+checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef"
 dependencies = [
  "core-foundation-sys",
  "libc",
@@ -3591,7 +3610,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -3616,13 +3635,13 @@ dependencies = [
 
 [[package]]
 name = "serde_repr"
-version = "0.1.18"
+version = "0.1.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb"
+checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -3728,9 +3747,9 @@ checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a"
 
 [[package]]
 name = "similar"
-version = "2.4.0"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21"
+checksum = "fa42c91313f1d05da9b26f267f931cf178d4aba455b4c4622dd7355eb80c6640"
 
 [[package]]
 name = "slab"
@@ -3786,12 +3805,12 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
 
 [[package]]
 name = "stability"
-version = "0.1.1"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebd1b177894da2a2d9120208c3386066af06a488255caabc5de8ddca22dbc3ce"
+checksum = "2ff9eaf853dec4c8802325d8b6d3dffa86cc707fd7a1a4cdbf416e13b061787a"
 dependencies = [
  "quote",
- "syn 1.0.109",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -3814,9 +3833,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
 
 [[package]]
 name = "strsim"
-version = "0.11.0"
+version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
 
 [[package]]
 name = "strum"
@@ -3837,7 +3856,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "rustversion",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -3888,9 +3907,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.53"
+version = "2.0.59"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032"
+checksum = "4a6531ffc7b071655e4ce2e04bd464c4830bb585a61cabb96cf808f05172615a"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3906,7 +3925,7 @@ dependencies = [
  "proc-macro-error",
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -4013,7 +4032,7 @@ dependencies = [
  "cfg-if",
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -4024,7 +4043,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
  "test-case-core",
 ]
 
@@ -4056,7 +4075,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -4080,9 +4099,9 @@ dependencies = [
 
 [[package]]
 name = "time"
-version = "0.3.34"
+version = "0.3.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
+checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
 dependencies = [
  "deranged",
  "itoa",
@@ -4103,9 +4122,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
 
 [[package]]
 name = "time-macros"
-version = "0.2.17"
+version = "0.2.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774"
+checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
 dependencies = [
  "num-conv",
  "time-core",
@@ -4151,7 +4170,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -4170,7 +4189,7 @@ version = "0.25.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f"
 dependencies = [
- "rustls 0.22.2",
+ "rustls 0.22.3",
  "rustls-pki-types",
  "tokio",
 ]
@@ -4242,7 +4261,7 @@ dependencies = [
  "serde",
  "serde_spanned",
  "toml_datetime",
- "winnow 0.6.5",
+ "winnow 0.6.6",
 ]
 
 [[package]]
@@ -4305,7 +4324,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -4572,7 +4591,7 @@ dependencies = [
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
  "wasm-bindgen-shared",
 ]
 
@@ -4606,7 +4625,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -4651,9 +4670,9 @@ dependencies = [
 
 [[package]]
 name = "widestring"
-version = "1.0.2"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8"
+checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311"
 
 [[package]]
 name = "winapi"
@@ -4701,7 +4720,7 @@ version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
 dependencies = [
- "windows-targets 0.52.4",
+ "windows-targets 0.52.5",
 ]
 
 [[package]]
@@ -4721,17 +4740,18 @@ dependencies = [
 
 [[package]]
 name = "windows-targets"
-version = "0.52.4"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
+checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
 dependencies = [
- "windows_aarch64_gnullvm 0.52.4",
- "windows_aarch64_msvc 0.52.4",
- "windows_i686_gnu 0.52.4",
- "windows_i686_msvc 0.52.4",
- "windows_x86_64_gnu 0.52.4",
- "windows_x86_64_gnullvm 0.52.4",
- "windows_x86_64_msvc 0.52.4",
+ "windows_aarch64_gnullvm 0.52.5",
+ "windows_aarch64_msvc 0.52.5",
+ "windows_i686_gnu 0.52.5",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc 0.52.5",
+ "windows_x86_64_gnu 0.52.5",
+ "windows_x86_64_gnullvm 0.52.5",
+ "windows_x86_64_msvc 0.52.5",
 ]
 
 [[package]]
@@ -4742,9 +4762,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
 
 [[package]]
 name = "windows_aarch64_gnullvm"
-version = "0.52.4"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
+checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
 
 [[package]]
 name = "windows_aarch64_msvc"
@@ -4754,9 +4774,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.52.4"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
+checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
 
 [[package]]
 name = "windows_i686_gnu"
@@ -4766,9 +4786,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.52.4"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
+checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
 
 [[package]]
 name = "windows_i686_msvc"
@@ -4778,9 +4804,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.52.4"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
+checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
 
 [[package]]
 name = "windows_x86_64_gnu"
@@ -4790,9 +4816,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.52.4"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
+checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
@@ -4802,9 +4828,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.52.4"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
+checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
 
 [[package]]
 name = "windows_x86_64_msvc"
@@ -4814,9 +4840,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.52.4"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
+checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
 
 [[package]]
 name = "winnow"
@@ -4829,9 +4855,9 @@ dependencies = [
 
 [[package]]
 name = "winnow"
-version = "0.6.5"
+version = "0.6.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8"
+checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352"
 dependencies = [
  "memchr",
 ]
@@ -4876,18 +4902,18 @@ dependencies = [
 
 [[package]]
 name = "xshell"
-version = "0.2.5"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce2107fe03e558353b4c71ad7626d58ed82efaf56c54134228608893c77023ad"
+checksum = "6db0ab86eae739efd1b054a8d3d16041914030ac4e01cd1dca0cf252fd8b6437"
 dependencies = [
  "xshell-macros",
 ]
 
 [[package]]
 name = "xshell-macros"
-version = "0.2.5"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e2c411759b501fb9501aac2b1b2d287a6e93e5bdcf13c25306b23e1b716dd0e"
+checksum = "9d422e8e38ec76e2f06ee439ccc765e9c6a9638b9e7c9f2e8255e4d41e8bd852"
 
 [[package]]
 name = "xtask"
@@ -4937,7 +4963,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.53",
+ "syn 2.0.59",
 ]
 
 [[package]]
@@ -4987,9 +5013,9 @@ dependencies = [
 
 [[package]]
 name = "zstd-sys"
-version = "2.0.9+zstd.1.5.5"
+version = "2.0.10+zstd.1.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656"
+checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa"
 dependencies = [
  "cc",
  "pkg-config",
diff --git a/Cargo.toml b/Cargo.toml
index 6ca86b14..2c0f6e0c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -27,7 +27,7 @@ probe-rs-target = { path = "probe-rs-target", version = "0.23.0" }
 
 docsplay = "0.1.1"
 thiserror = "1.0.58"
-anyhow = "1.0.81"
+anyhow = "1.0.82"
 
 [workspace.metadata.release]
 shared-version = true
@@ -36,11 +36,11 @@ tag-name = "v{{version}}"
 # Config for 'cargo dist'
 [workspace.metadata.dist]
 # The preferred cargo-dist version to use in CI (Cargo.toml SemVer syntax)
-cargo-dist-version = "0.11.1"
+cargo-dist-version = "0.13.0"
 # CI backends to support
 ci = ["github"]
 # Target platforms to build apps for (Rust target-triple syntax)
-targets = ["aarch64-apple-darwin", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu", "x86_64-pc-windows-msvc"]
+targets = ["aarch64-apple-darwin", "aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu", "x86_64-pc-windows-msvc"]
 # Build only the required packages, and individually
 precise-builds = true
 # The archive format to use for non-windows builds (defaults .tar.xz)
@@ -53,6 +53,8 @@ pr-run-mode = "plan"
 tap = "probe-rs/homebrew-probe-rs"
 # Publish jobs to run in CI
 publish-jobs = ["homebrew"]
+# Whether to install an updater program
+install-updater = false
 # Select custom runner for ARM Linux
 [workspace.metadata.dist.github-custom-runners]
 aarch64-unknown-linux-gnu = "buildjet-2vcpu-ubuntu-2204-arm"
diff --git a/changelog/added-dap-server-ip-option.md b/changelog/added-dap-server-ip-option.md
new file mode 100644
index 00000000..90cbd2ab
--- /dev/null
+++ b/changelog/added-dap-server-ip-option.md
@@ -0,0 +1,1 @@
+Users can now specify IP address for dap-server to bind.
diff --git a/changelog/added-enable-kickstart-power-for-jlink.md b/changelog/added-enable-kickstart-power-for-jlink.md
new file mode 100644
index 00000000..63349185
--- /dev/null
+++ b/changelog/added-enable-kickstart-power-for-jlink.md
@@ -0,0 +1,1 @@
+added enable/disable kickstart power for J-Link
diff --git a/changelog/added-new stm32-targets.md b/changelog/added-new stm32-targets.md
new file mode 100644
index 00000000..d5c84bae
--- /dev/null
+++ b/changelog/added-new stm32-targets.md
@@ -0,0 +1,1 @@
+Update the `STM32WB_Series.yaml` targets with `target-gen arm --filter STM32WBxx_DFP`
diff --git a/changelog/added-u0.md b/changelog/added-u0.md
new file mode 100644
index 00000000..cde132bc
--- /dev/null
+++ b/changelog/added-u0.md
@@ -0,0 +1,1 @@
+Added support for STM32U0 devices
\ No newline at end of file
diff --git a/changelog/fixed-esp32-riscv-reset.md b/changelog/fixed-esp32-riscv-reset.md
new file mode 100644
index 00000000..89289176
--- /dev/null
+++ b/changelog/fixed-esp32-riscv-reset.md
@@ -0,0 +1,1 @@
+Probe-rs should now succeed more at flashing RISC-V ESP32 devices
\ No newline at end of file
diff --git a/probe-rs/Cargo.toml b/probe-rs/Cargo.toml
index 24bca3e4..1031efdd 100644
--- a/probe-rs/Cargo.toml
+++ b/probe-rs/Cargo.toml
@@ -82,11 +82,11 @@ test = []
 anyhow = { workspace = true }
 base64 = "0.22"
 bincode = "1.3"
-bitfield = "0.14"
+bitfield = "0.15"
 bitvec = "1"
 docsplay = { workspace = true }
 enum-primitive-derive = "0.3"
-gimli = { version = "0.28", default-features = false, features = [
+gimli = { version = "0.29", default-features = false, features = [
     "endian-reader",
     "read",
     "std",
@@ -99,7 +99,7 @@ jep106 = "0.2"
 once_cell = "1"
 miniz_oxide = "0.7"
 num-traits = "0.2"
-object = { version = "0.34", default-features = false, features = [
+object = { version = "0.35", default-features = false, features = [
     "elf",
     "read_core",
     "std",
@@ -133,7 +133,7 @@ gdbstub = { version = "0.7", optional = true }
 itertools = { version = "0.12", optional = true }
 
 # CLI-only
-addr2line = { version = "0.21", optional = true }
+addr2line = { version = "0.22", optional = true }
 byte-unit = { version = "5", optional = true }
 bytesize = { version = "1", optional = true }
 capstone = { version = "0.12", optional = true }
@@ -155,7 +155,7 @@ goblin = { version = "0.8", optional = true }
 indicatif = { version = "0.17", optional = true }
 insta = { version = "1.38", features = ["yaml", "filters"], optional = true }
 itm = { version = "0.9.0-rc.1", default-features = false, optional = true }
-libtest-mimic = { version = "0.7.0", optional = true }
+libtest-mimic = { version = "0.7.2", optional = true }
 rand = { version = "0.8", optional = true }
 rustyline = { version = "14", optional = true }
 sanitize-filename = { version = "0.5", optional = true }
@@ -177,12 +177,12 @@ tracing-subscriber = { version = "0.3", features = [
     "json",
 ], optional = true }
 tracing-appender = { version = "0.2", optional = true }
-ratatui = { version = "0.26.1", default-features = false, features = [
+ratatui = { version = "0.26.2", default-features = false, features = [
     "crossterm",
 ], optional = true }
 ansi-parser = { version = "0.9.0", optional = true }
 parking_lot = "0.12.1"
-cargo-config2 = { version = "0.1.23", optional = true }
+cargo-config2 = { version = "0.1.24", optional = true }
 
 [build-dependencies]
 bincode = "1"
diff --git a/probe-rs/src/architecture/riscv/communication_interface.rs b/probe-rs/src/architecture/riscv/communication_interface.rs
index f0e6431d..af017988 100644
--- a/probe-rs/src/architecture/riscv/communication_interface.rs
+++ b/probe-rs/src/architecture/riscv/communication_interface.rs
@@ -314,6 +314,9 @@ pub struct RiscvCommunicationInterface {
     state: RiscvCommunicationInterfaceState,
     enabled_harts: u32,
     last_selected_hart: u32,
+
+    /// Store the value of the `hasresethaltreq` bit of the `dmcstatus` register.
+    hasresethaltreq: Option<bool>,
 }
 
 impl RiscvCommunicationInterface {
@@ -326,6 +329,7 @@ impl RiscvCommunicationInterface {
             state,
             enabled_harts: 0,
             last_selected_hart: 0,
+            hasresethaltreq: None,
         };
 
         if let Err(err) = s.enter_debug_mode() {
@@ -421,8 +425,9 @@ impl RiscvCommunicationInterface {
         Ok(())
     }
 
-    fn enter_debug_mode(&mut self) -> Result<(), RiscvError> {
+    pub(crate) fn enter_debug_mode(&mut self) -> Result<(), RiscvError> {
         tracing::debug!("Building RISC-V interface");
+        self.dtm.init()?;
 
         // Reset error bits from previous connections
         self.dtm.clear_error_state()?;
@@ -430,6 +435,7 @@ impl RiscvCommunicationInterface {
         // read the  version of the debug module
         let status: Dmstatus = self.read_dm_register()?;
 
+        self.state.progbuf_cache.fill(0);
         self.state.debug_version = DebugModuleVersion::from(status.version() as u8);
 
         // Only version of 0.13 of the debug specification is currently supported.
@@ -680,7 +686,7 @@ impl RiscvCommunicationInterface {
     }
 
     /// Schedules a DM register read, flushes the queue and returns the result.
-    pub(super) fn read_dm_register<R: MemoryMappedRegister<u32>>(
+    pub(crate) fn read_dm_register<R: MemoryMappedRegister<u32>>(
         &mut self,
     ) -> Result<R, RiscvError> {
         tracing::debug!(
@@ -711,7 +717,7 @@ impl RiscvCommunicationInterface {
         Ok(register_value)
     }
 
-    pub(super) fn write_dm_register<R: MemoryMappedRegister<u32>>(
+    pub(crate) fn write_dm_register<R: MemoryMappedRegister<u32>>(
         &mut self,
         register: R,
     ) -> Result<(), RiscvError> {
@@ -1080,7 +1086,8 @@ impl RiscvCommunicationInterface {
             let error = AbstractCommandErrorKind::parse(status.cmderr() as u8);
 
             tracing::error!(
-                "Executing the abstract command for perform_memory_write failed: {:?} ({:x?})",
+                "Executing the abstract command for write_{} failed: {:?} ({:x?})",
+                V::WIDTH.byte_width() * 8,
                 error,
                 status,
             );
@@ -1142,7 +1149,8 @@ impl RiscvCommunicationInterface {
             let error = AbstractCommandErrorKind::parse(status.cmderr() as u8);
 
             tracing::error!(
-                "Executing the abstract command for write_32 failed: {:?} ({:x?})",
+                "Executing the abstract command for write_multiple_{} failed: {:?} ({:x?})",
+                V::WIDTH.byte_width() * 8,
                 error,
                 status,
             );
@@ -1526,6 +1534,127 @@ impl RiscvCommunicationInterface {
     {
         V::schedule_write_to_register::<R>(self, value)
     }
+
+    /// Check if the connected device supports halt after reset.
+    ///
+    /// Returns a cached value if available, otherwise queries the
+    /// `hasresethaltreq` bit in the `dmstatus` register.
+    pub(crate) fn supports_reset_halt_req(&mut self) -> Result<bool, RiscvError> {
+        if let Some(has_reset_halt_req) = self.hasresethaltreq {
+            Ok(has_reset_halt_req)
+        } else {
+            let dmstatus: Dmstatus = self.read_dm_register()?;
+
+            self.hasresethaltreq = Some(dmstatus.hasresethaltreq());
+
+            Ok(dmstatus.hasresethaltreq())
+        }
+    }
+
+    // Resume the core.
+    pub(crate) fn resume_core(&mut self) -> Result<(), RiscvError> {
+        // set resume request.
+        let mut dmcontrol: Dmcontrol = self.read_dm_register()?;
+        dmcontrol.set_dmactive(true);
+        dmcontrol.set_resumereq(true);
+        self.write_dm_register(dmcontrol)?;
+
+        // check if request has been acknowleged.
+        let status: Dmstatus = self.read_dm_register()?;
+        if !status.allresumeack() {
+            return Err(RiscvError::RequestNotAcknowledged);
+        }
+
+        // clear resume request.
+        dmcontrol.set_resumereq(false);
+        self.write_dm_register(dmcontrol)?;
+
+        Ok(())
+    }
+
+    pub(crate) fn reset_hart_and_halt(&mut self, timeout: Duration) -> Result<(), RiscvError> {
+        tracing::debug!("Resetting core, setting hartreset bit");
+
+        let mut dmcontrol: Dmcontrol = self.read_dm_register()?;
+        dmcontrol.set_dmactive(true);
+        dmcontrol.set_hartreset(true);
+        dmcontrol.set_haltreq(true);
+
+        self.write_dm_register(dmcontrol)?;
+
+        // Read back register to verify reset is supported
+        let readback: Dmcontrol = self.read_dm_register()?;
+
+        if readback.hartreset() {
+            tracing::debug!("Clearing hartreset bit");
+            // Reset is performed by setting the bit high, and then low again
+            let mut dmcontrol = readback;
+            dmcontrol.set_dmactive(true);
+            dmcontrol.set_hartreset(false);
+
+            self.write_dm_register(dmcontrol)?;
+        } else {
+            // Hartreset is not supported, whole core needs to be reset
+            //
+            // TODO: Cache this
+            tracing::debug!("Hartreset bit not supported, using ndmreset");
+            dmcontrol.set_hartreset(false);
+            dmcontrol.set_ndmreset(true);
+            dmcontrol.set_haltreq(true);
+
+            self.write_dm_register(dmcontrol)?;
+
+            tracing::debug!("Clearing ndmreset bit");
+            dmcontrol.set_ndmreset(false);
+            dmcontrol.set_haltreq(true);
+
+            self.write_dm_register(dmcontrol)?;
+        }
+
+        let start = Instant::now();
+
+        loop {
+            // check that cores have reset
+            let readback: Dmstatus = self.read_dm_register()?;
+
+            if readback.allhavereset() && readback.allhalted() {
+                break;
+            }
+
+            if start.elapsed() > timeout {
+                return Err(RiscvError::RequestNotAcknowledged);
+            }
+        }
+
+        // clear the reset request
+        dmcontrol.set_haltreq(false);
+        dmcontrol.set_ackhavereset(true);
+        dmcontrol.set_hartreset(false);
+        dmcontrol.set_ndmreset(false);
+
+        self.write_dm_register(dmcontrol)?;
+
+        // Reenable halt on breakpoint because this gets disabled if we reset the core
+        self.debug_on_sw_breakpoint(true)?; // TODO: only restore if enabled before?
+
+        Ok(())
+    }
+
+    pub(crate) fn debug_on_sw_breakpoint(&mut self, enabled: bool) -> Result<(), RiscvError> {
+        let mut dcsr = Dcsr(self.read_csr(0x7b0)?);
+
+        dcsr.set_ebreakm(enabled);
+        dcsr.set_ebreaks(enabled);
+        dcsr.set_ebreaku(enabled);
+
+        match self.abstract_cmd_register_write(0x7b0, dcsr.0) {
+            Err(RiscvError::AbstractCommand(AbstractCommandErrorKind::NotSupported)) => {
+                tracing::debug!("Could not write core register {:#x} with abstract command, falling back to program buffer", 0x7b0);
+                self.write_csr_progbuf(0x7b0, dcsr.0)
+            }
+            other => other,
+        }
+    }
 }
 
 pub(crate) trait LargeRegister {
@@ -2097,17 +2226,17 @@ impl From<u32> for AccessMemoryCommand {
     }
 }
 
-memory_mapped_bitfield_register! { struct Sbaddress0(u32); 0x39, "sbaddress0", impl From; }
-memory_mapped_bitfield_register! { struct Sbaddress1(u32); 0x3a, "sbaddress1", impl From; }
-memory_mapped_bitfield_register! { struct Sbaddress2(u32); 0x3b, "sbaddress2", impl From; }
-memory_mapped_bitfield_register! { struct Sbaddress3(u32); 0x37, "sbaddress3", impl From; }
+memory_mapped_bitfield_register! { pub struct Sbaddress0(u32); 0x39, "sbaddress0", impl From; }
+memory_mapped_bitfield_register! { pub struct Sbaddress1(u32); 0x3a, "sbaddress1", impl From; }
+memory_mapped_bitfield_register! { pub struct Sbaddress2(u32); 0x3b, "sbaddress2", impl From; }
+memory_mapped_bitfield_register! { pub struct Sbaddress3(u32); 0x37, "sbaddress3", impl From; }
 
-memory_mapped_bitfield_register! { struct Sbdata0(u32); 0x3c, "sbdata0", impl From; }
-memory_mapped_bitfield_register! { struct Sbdata1(u32); 0x3d, "sbdata1", impl From; }
-memory_mapped_bitfield_register! { struct Sbdata2(u32); 0x3e, "sbdata2", impl From; }
-memory_mapped_bitfield_register! { struct Sbdata3(u32); 0x3f, "sbdata3", impl From; }
+memory_mapped_bitfield_register! { pub struct Sbdata0(u32); 0x3c, "sbdata0", impl From; }
+memory_mapped_bitfield_register! { pub struct Sbdata1(u32); 0x3d, "sbdata1", impl From; }
+memory_mapped_bitfield_register! { pub struct Sbdata2(u32); 0x3e, "sbdata2", impl From; }
+memory_mapped_bitfield_register! { pub struct Sbdata3(u32); 0x3f, "sbdata3", impl From; }
 
-memory_mapped_bitfield_register! { struct Confstrptr0(u32); 0x19, "confstrptr0", impl From; }
-memory_mapped_bitfield_register! { struct Confstrptr1(u32); 0x1a, "confstrptr1", impl From; }
-memory_mapped_bitfield_register! { struct Confstrptr2(u32); 0x1b, "confstrptr2", impl From; }
-memory_mapped_bitfield_register! { struct Confstrptr3(u32); 0x1c, "confstrptr3", impl From; }
+memory_mapped_bitfield_register! { pub struct Confstrptr0(u32); 0x19, "confstrptr0", impl From; }
+memory_mapped_bitfield_register! { pub struct Confstrptr1(u32); 0x1a, "confstrptr1", impl From; }
+memory_mapped_bitfield_register! { pub struct Confstrptr2(u32); 0x1b, "confstrptr2", impl From; }
+memory_mapped_bitfield_register! { pub struct Confstrptr3(u32); 0x1c, "confstrptr3", impl From; }
diff --git a/probe-rs/src/architecture/riscv/dtm/dtm_access.rs b/probe-rs/src/architecture/riscv/dtm/dtm_access.rs
index 6014f206..0e011fb5 100644
--- a/probe-rs/src/architecture/riscv/dtm/dtm_access.rs
+++ b/probe-rs/src/architecture/riscv/dtm/dtm_access.rs
@@ -4,6 +4,11 @@ use std::fmt;
 use std::time::Duration;
 
 pub trait DtmAccess: Send + fmt::Debug {
+    /// Perform interface-specific initialisation upon attaching.
+    fn init(&mut self) -> Result<(), DebugProbeError> {
+        Ok(())
+    }
+
     /// Asserts a reset of the physical pins
     fn target_reset_assert(&mut self) -> Result<(), DebugProbeError>;
 
diff --git a/probe-rs/src/architecture/riscv/dtm/jtag_dtm.rs b/probe-rs/src/architecture/riscv/dtm/jtag_dtm.rs
index 5a8c740f..90edc5ed 100644
--- a/probe-rs/src/architecture/riscv/dtm/jtag_dtm.rs
+++ b/probe-rs/src/architecture/riscv/dtm/jtag_dtm.rs
@@ -41,7 +41,7 @@ impl JtagDtm {
 
         let dtmcs = Dtmcs(raw_dtmcs);
 
-        tracing::debug!("Dtmcs: {:?}", dtmcs);
+        tracing::debug!("{:?}", dtmcs);
 
         let abits = dtmcs.abits();
         let idle_cycles = dtmcs.idle();
@@ -109,7 +109,7 @@ impl JtagDtm {
         Ok(self.queued_commands.schedule(JtagWriteCommand {
             address: DMI_ADDRESS,
             data: bytes.to_vec(),
-            transform: |result| {
+            transform: |_, result| {
                 Self::transform_dmi_result(result)
                     .map(CommandResult::U32)
                     .map_err(|e| crate::Error::Riscv(e.map_as_err().unwrap_err()))
@@ -147,6 +147,11 @@ impl JtagDtm {
 }
 
 impl DtmAccess for JtagDtm {
+    fn init(&mut self) -> Result<(), DebugProbeError> {
+        self.probe.tap_reset()?;
+        Ok(())
+    }
+
     fn target_reset_assert(&mut self) -> Result<(), DebugProbeError> {
         self.probe.target_reset_assert()
     }
diff --git a/probe-rs/src/architecture/riscv/mod.rs b/probe-rs/src/architecture/riscv/mod.rs
index aa8fccbe..c6ea20ae 100644
--- a/probe-rs/src/architecture/riscv/mod.rs
+++ b/probe-rs/src/architecture/riscv/mod.rs
@@ -3,6 +3,7 @@
 #![allow(clippy::inconsistent_digit_grouping)]
 
 use crate::{
+    architecture::riscv::sequences::RiscvDebugSequence,
     core::{
         Architecture, BreakpointCause, CoreInformation, CoreRegisters, RegisterId, RegisterValue,
     },
@@ -17,7 +18,10 @@ use anyhow::{anyhow, Result};
 use bitfield::bitfield;
 use communication_interface::{AbstractCommandErrorKind, RiscvCommunicationInterface, RiscvError};
 use registers::{FP, RA, RISCV_CORE_REGSISTERS, SP};
-use std::time::{Duration, Instant};
+use std::{
+    sync::Arc,
+    time::{Duration, Instant},
+};
 
 #[macro_use]
 pub(crate) mod registers;
@@ -27,39 +31,39 @@ pub mod communication_interface;
 pub(crate) mod dtm;
 pub mod sequences;
 
-/// An interface to operate RISC-V cores.
+/// An interface to operate a RISC-V core.
 pub struct Riscv32<'probe> {
-    hart: u32,
     interface: &'probe mut RiscvCommunicationInterface,
     state: &'probe mut RiscVState,
+    sequence: Arc<dyn RiscvDebugSequence>,
 }
 
 impl<'probe> Riscv32<'probe> {
-    /// Create a new RISC-V interface.
+    /// Create a new RISC-V interface for a particular hart.
     pub fn new(
         hart: u32,
         interface: &'probe mut RiscvCommunicationInterface,
         state: &'probe mut RiscVState,
+        sequence: Arc<dyn RiscvDebugSequence>,
     ) -> Result<Self, RiscvError> {
         if !interface.hart_enabled(hart) {
             return Err(RiscvError::HartUnavailable);
         }
 
+        interface.select_hart(hart)?;
+
         Ok(Self {
-            hart,
             interface,
             state,
+            sequence,
         })
     }
 
     fn read_csr(&mut self, address: u16) -> Result<u32, RiscvError> {
-        self.interface.select_hart(self.hart)?;
         self.interface.read_csr(address)
     }
 
     fn write_csr(&mut self, address: u16, value: u32) -> Result<(), RiscvError> {
-        self.interface.select_hart(self.hart)?;
-
         tracing::debug!("Writing CSR {:#x}", address);
 
         match self.interface.abstract_cmd_register_write(address, value) {
@@ -71,48 +75,14 @@ impl<'probe> Riscv32<'probe> {
         }
     }
 
-    // Resume the core.
+    /// Resume the core.
     fn resume_core(&mut self) -> Result<(), crate::Error> {
-        self.interface.select_hart(self.hart)?;
         self.state.semihosting_command = None;
-
-        // set resume request.
-        let mut dmcontrol: Dmcontrol = self.interface.read_dm_register()?;
-        dmcontrol.set_dmactive(true);
-        dmcontrol.set_resumereq(true);
-        self.interface.write_dm_register(dmcontrol)?;
-
-        // check if request has been acknowleged.
-        let status: Dmstatus = self.interface.read_dm_register()?;
-        if !status.allresumeack() {
-            return Err(RiscvError::RequestNotAcknowledged.into());
-        };
-
-        // clear resume request.
-        dmcontrol.set_resumereq(false);
-        self.interface.write_dm_register(dmcontrol)?;
+        self.interface.resume_core()?;
 
         Ok(())
     }
 
-    /// Check if the connected device supports halt after reset.
-    ///
-    /// Returns a cached value if available, otherwise queries the
-    /// `hasresethaltreq` bit in the `dmstatus` register.
-    fn supports_reset_halt_req(&mut self) -> Result<bool, crate::Error> {
-        self.interface.select_hart(self.hart)?;
-
-        if let Some(has_reset_halt_req) = self.state.hasresethaltreq {
-            Ok(has_reset_halt_req)
-        } else {
-            let dmstatus: Dmstatus = self.interface.read_dm_register()?;
-
-            self.state.hasresethaltreq = Some(dmstatus.hasresethaltreq());
-
-            Ok(dmstatus.hasresethaltreq())
-        }
-    }
-
     /// Check if the current breakpoint is a semihosting call
     fn check_for_semihosting(&mut self) -> Result<Option<SemihostingCommand>, Error> {
         let pc: u32 = self.read_core_reg(self.program_counter().id)?.try_into()?;
@@ -166,21 +136,16 @@ impl<'probe> Riscv32<'probe> {
 
 impl<'probe> CoreInterface for Riscv32<'probe> {
     fn wait_for_core_halted(&mut self, timeout: Duration) -> Result<(), crate::Error> {
-        self.interface.select_hart(self.hart)?;
         Ok(self.interface.wait_for_core_halted(timeout)?)
     }
 
     fn core_halted(&mut self) -> Result<bool, crate::Error> {
-        self.interface.select_hart(self.hart)?;
-
         let dmstatus: Dmstatus = self.interface.read_dm_register()?;
 
         Ok(dmstatus.allhalted())
     }
 
     fn status(&mut self) -> Result<crate::core::CoreStatus, crate::Error> {
-        self.interface.select_hart(self.hart)?;
-
         // TODO: We should use hartsum to determine if any hart is halted
         //       quickly
 
@@ -223,14 +188,11 @@ impl<'probe> CoreInterface for Riscv32<'probe> {
         }
     }
 
-    fn halt(&mut self, timeout: Duration) -> Result<CoreInformation, crate::Error> {
-        self.interface.select_hart(self.hart)?;
+    fn halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
         Ok(self.interface.halt(timeout)?)
     }
 
-    fn run(&mut self) -> Result<(), crate::Error> {
-        self.interface.select_hart(self.hart)?;
-
+    fn run(&mut self) -> Result<(), Error> {
         // Before we run, we always perform a single instruction step, to account for possible breakpoints that might get us stuck on the current instruction.
         self.step()?;
 
@@ -240,98 +202,23 @@ impl<'probe> CoreInterface for Riscv32<'probe> {
         Ok(())
     }
 
-    fn reset(&mut self) -> Result<(), crate::Error> {
-        self.interface.select_hart(self.hart)?;
+    fn reset(&mut self) -> Result<(), Error> {
+        self.reset_and_halt(Duration::from_secs(1))?;
+        self.resume_core()?;
 
-        match self.reset_and_halt(Duration::from_millis(500)) {
-            Ok(_) => self.resume_core()?,
-            Err(error) => {
-                return Err(RiscvError::DebugProbe(DebugProbeError::Other(
-                    anyhow::anyhow!("Error during reset").context(error),
-                ))
-                .into());
-            }
-        }
         Ok(())
     }
 
-    fn reset_and_halt(
-        &mut self,
-        timeout: Duration,
-    ) -> Result<crate::core::CoreInformation, crate::Error> {
-        self.interface.select_hart(self.hart)?;
-
-        tracing::debug!("Resetting core, setting hartreset bit");
-
-        let mut dmcontrol: Dmcontrol = self.interface.read_dm_register()?;
-        dmcontrol.set_dmactive(true);
-        dmcontrol.set_hartreset(true);
-        dmcontrol.set_haltreq(true);
-
-        self.interface.write_dm_register(dmcontrol)?;
-
-        // Read back register to verify reset is supported
-        let readback: Dmcontrol = self.interface.read_dm_register()?;
-
-        if readback.hartreset() {
-            tracing::debug!("Clearing hartreset bit");
-            // Reset is performed by setting the bit high, and then low again
-            let mut dmcontrol = readback;
-            dmcontrol.set_dmactive(true);
-            dmcontrol.set_hartreset(false);
-
-            self.interface.write_dm_register(dmcontrol)?;
-        } else {
-            // Hartreset is not supported, whole core needs to be reset
-            //
-            // TODO: Cache this
-            tracing::debug!("Hartreset bit not supported, using ndmreset");
-            dmcontrol.set_hartreset(false);
-            dmcontrol.set_ndmreset(true);
-            dmcontrol.set_haltreq(true);
-
-            self.interface.write_dm_register(dmcontrol)?;
-
-            tracing::debug!("Clearing ndmreset bit");
-            dmcontrol.set_ndmreset(false);
-            dmcontrol.set_haltreq(true);
-
-            self.interface.write_dm_register(dmcontrol)?;
-        }
-
-        let start = Instant::now();
-
-        loop {
-            // check that cores have reset
-            let readback: Dmstatus = self.interface.read_dm_register()?;
-
-            if readback.allhavereset() && readback.allhalted() {
-                break;
-            }
-
-            if start.elapsed() > timeout {
-                return Err(RiscvError::RequestNotAcknowledged.into());
-            }
-        }
-
-        // acknowledge the reset, clear the halt request
-        dmcontrol.set_hartreset(false);
-        dmcontrol.set_ndmreset(false);
-        dmcontrol.set_ackhavereset(true);
-
-        self.interface.write_dm_register(dmcontrol)?;
-
-        // Reenable halt on breakpoint because this gets disabled if we reset the core
-        self.debug_on_sw_breakpoint(true)?; // TODO: only restore if enabled before?
+    fn reset_and_halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
+        self.sequence
+            .reset_system_and_halt(self.interface, timeout)?;
 
         let pc = self.read_core_reg(RegisterId(0x7b1))?;
 
         Ok(CoreInformation { pc: pc.try_into()? })
     }
 
-    fn step(&mut self) -> Result<crate::core::CoreInformation, crate::Error> {
-        self.interface.select_hart(self.hart)?;
-
+    fn step(&mut self) -> Result<CoreInformation, crate::Error> {
         let halt_reason = self.status()?;
         let flashing_done = self.state.hw_breakpoints_enabled;
         if matches!(
@@ -397,8 +284,6 @@ impl<'probe> CoreInterface for Riscv32<'probe> {
     }
 
     fn read_core_reg(&mut self, address: RegisterId) -> Result<RegisterValue, crate::Error> {
-        self.interface.select_hart(self.hart)?;
-
         self.read_csr(address.0)
             .map(|v| v.into())
             .map_err(|e| e.into())
@@ -409,15 +294,11 @@ impl<'probe> CoreInterface for Riscv32<'probe> {
         address: RegisterId,
         value: RegisterValue,
     ) -> Result<(), crate::Error> {
-        self.interface.select_hart(self.hart)?;
-
         let value: u32 = value.try_into()?;
         self.write_csr(address.0, value).map_err(|e| e.into())
     }
 
     fn available_breakpoint_units(&mut self) -> Result<u32, crate::Error> {
-        self.interface.select_hart(self.hart)?;
-
         // TODO: This should probably only be done once, when initialising
 
         tracing::debug!("Determining number of HW breakpoints supported");
@@ -492,7 +373,6 @@ impl<'probe> CoreInterface for Riscv32<'probe> {
     /// NOTE: For riscv, this assumes that only execution breakpoints are used.
     fn hw_breakpoints(&mut self) -> Result<Vec<Option<u64>>, Error> {
         // this can be called w/o halting the core via Session::new - temporarily halt if not halted
-        self.interface.select_hart(self.hart)?;
 
         let was_running = !self.core_halted()?;
         if was_running {
@@ -542,8 +422,6 @@ impl<'probe> CoreInterface for Riscv32<'probe> {
     }
 
     fn enable_breakpoints(&mut self, state: bool) -> Result<(), crate::Error> {
-        self.interface.select_hart(self.hart)?;
-
         // Loop through all triggers, and enable/disable them.
         let tselect = 0x7a0;
         let tdata1 = 0x7a1;
@@ -579,8 +457,6 @@ impl<'probe> CoreInterface for Riscv32<'probe> {
     }
 
     fn set_hw_breakpoint(&mut self, bp_unit_index: usize, addr: u64) -> Result<(), crate::Error> {
-        self.interface.select_hart(self.hart)?;
-
         let addr = valid_32bit_address(addr)?;
 
         if !self.hw_breakpoints_enabled() {
@@ -636,7 +512,6 @@ impl<'probe> CoreInterface for Riscv32<'probe> {
 
     fn clear_hw_breakpoint(&mut self, unit_index: usize) -> Result<(), crate::Error> {
         // this can be called w/o halting the core via Session::new - temporarily halt if not halted
-        self.interface.select_hart(self.hart)?;
 
         let was_running = !self.core_halted()?;
         if was_running {
@@ -682,16 +557,9 @@ impl<'probe> CoreInterface for Riscv32<'probe> {
         self.state.hw_breakpoints_enabled
     }
 
-    fn debug_on_sw_breakpoint(&mut self, enabled: bool) -> Result<(), crate::error::Error> {
-        self.interface.select_hart(self.hart)?;
-
-        let mut dcsr = Dcsr(self.read_core_reg(RegisterId(0x7b0))?.try_into()?);
-
-        dcsr.set_ebreakm(enabled);
-        dcsr.set_ebreaks(enabled);
-        dcsr.set_ebreaku(enabled);
-
-        self.write_csr(0x7b0, dcsr.0).map_err(|e| e.into())
+    fn debug_on_sw_breakpoint(&mut self, enabled: bool) -> Result<(), Error> {
+        self.interface.debug_on_sw_breakpoint(enabled)?;
+        Ok(())
     }
 
     fn architecture(&self) -> Architecture {
@@ -723,8 +591,6 @@ impl<'probe> CoreInterface for Riscv32<'probe> {
     }
 
     fn fpu_support(&mut self) -> Result<bool, crate::error::Error> {
-        self.interface.select_hart(self.hart)?;
-
         // Read the extensions from the Machine ISA regiseter.
         let isa_extensions =
             Misa::from(self.read_csr(Misa::get_mmio_address() as u16)?).extensions();
@@ -734,42 +600,16 @@ impl<'probe> CoreInterface for Riscv32<'probe> {
     }
 
     fn reset_catch_set(&mut self) -> Result<(), Error> {
-        self.interface.select_hart(self.hart)?;
-
-        if !self.supports_reset_halt_req()? {
-            return Err(Error::Riscv(RiscvError::ResetHaltRequestNotSupported));
-        }
-
-        let mut dmcontrol: Dmcontrol = self.interface.read_dm_register()?;
-
-        dmcontrol.set_dmactive(true);
-        dmcontrol.set_resethaltreq(true);
-
-        self.interface.write_dm_register(dmcontrol)?;
-
+        self.sequence.reset_catch_set(self.interface)?;
         Ok(())
     }
 
     fn reset_catch_clear(&mut self) -> Result<(), Error> {
-        self.interface.select_hart(self.hart)?;
-
-        if !self.supports_reset_halt_req()? {
-            return Err(Error::Riscv(RiscvError::ResetHaltRequestNotSupported));
-        }
-
-        let mut dmcontrol: Dmcontrol = self.interface.read_dm_register()?;
-
-        dmcontrol.set_dmactive(true);
-        dmcontrol.set_clrresethaltreq(true);
-
-        self.interface.write_dm_register(dmcontrol)?;
-
+        self.sequence.reset_catch_clear(self.interface)?;
         Ok(())
     }
 
     fn debug_core_stop(&mut self) -> Result<(), Error> {
-        self.interface.select_hart(self.hart)?;
-
         self.debug_on_sw_breakpoint(false)?;
         Ok(())
     }
@@ -781,87 +621,70 @@ impl<'probe> MemoryInterface for Riscv32<'probe> {
     }
 
     fn read_word_64(&mut self, address: u64) -> Result<u64, crate::error::Error> {
-        self.interface.select_hart(self.hart)?;
         self.interface.read_word_64(address)
     }
 
     fn read_word_32(&mut self, address: u64) -> Result<u32, Error> {
-        self.interface.select_hart(self.hart)?;
         self.interface.read_word_32(address)
     }
 
     fn read_word_16(&mut self, address: u64) -> Result<u16, Error> {
-        self.interface.select_hart(self.hart)?;
         self.interface.read_word_16(address)
     }
 
     fn read_word_8(&mut self, address: u64) -> Result<u8, Error> {
-        self.interface.select_hart(self.hart)?;
         self.interface.read_word_8(address)
     }
 
     fn read_64(&mut self, address: u64, data: &mut [u64]) -> Result<(), Error> {
-        self.interface.select_hart(self.hart)?;
         self.interface.read_64(address, data)
     }
 
     fn read_32(&mut self, address: u64, data: &mut [u32]) -> Result<(), Error> {
-        self.interface.select_hart(self.hart)?;
         self.interface.read_32(address, data)
     }
 
     fn read_16(&mut self, address: u64, data: &mut [u16]) -> Result<(), Error> {
-        self.interface.select_hart(self.hart)?;
         self.interface.read_16(address, data)
     }
 
     fn read_8(&mut self, address: u64, data: &mut [u8]) -> Result<(), Error> {
-        self.interface.select_hart(self.hart)?;
         self.interface.read_8(address, data)
     }
 
     fn write_word_64(&mut self, address: u64, data: u64) -> Result<(), Error> {
-        self.interface.select_hart(self.hart)?;
         self.interface.write_word_64(address, data)
     }
 
     fn write_word_32(&mut self, address: u64, data: u32) -> Result<(), Error> {
-        self.interface.select_hart(self.hart)?;
         self.interface.write_word_32(address, data)
     }
 
     fn write_word_16(&mut self, address: u64, data: u16) -> Result<(), Error> {
-        self.interface.select_hart(self.hart)?;
         self.interface.write_word_16(address, data)
     }
 
     fn write_word_8(&mut self, address: u64, data: u8) -> Result<(), Error> {
-        self.interface.select_hart(self.hart)?;
         self.interface.write_word_8(address, data)
     }
 
     fn write_64(&mut self, address: u64, data: &[u64]) -> Result<(), Error> {
-        self.interface.select_hart(self.hart)?;
         self.interface.write_64(address, data)
     }
 
     fn write_32(&mut self, address: u64, data: &[u32]) -> Result<(), Error> {
-        self.interface.select_hart(self.hart)?;
         self.interface.write_32(address, data)
     }
 
     fn write_16(&mut self, address: u64, data: &[u16]) -> Result<(), Error> {
-        self.interface.select_hart(self.hart)?;
         self.interface.write_16(address, data)
     }
 
     fn write_8(&mut self, address: u64, data: &[u8]) -> Result<(), Error> {
-        self.interface.select_hart(self.hart)?;
         self.interface.write_8(address, data)
     }
 
     fn write(&mut self, address: u64, data: &[u8]) -> Result<(), Error> {
-        self.interface.select_hart(self.hart)?;
         self.interface.write(address, data)
     }
 
@@ -870,7 +693,6 @@ impl<'probe> MemoryInterface for Riscv32<'probe> {
     }
 
     fn flush(&mut self) -> Result<(), Error> {
-        self.interface.select_hart(self.hart)?;
         self.interface.flush()
     }
 }
@@ -881,9 +703,6 @@ pub struct RiscVState {
     /// A flag to remember whether we want to use hw_breakpoints during stepping of the core.
     hw_breakpoints_enabled: bool,
 
-    /// Store the value of the `hasresethaltreq` bit of the `dmcstatus` register.
-    hasresethaltreq: Option<bool>,
-
     /// The semihosting command that was decoded at the current program counter
     semihosting_command: Option<SemihostingCommand>,
 }
@@ -892,36 +711,56 @@ impl RiscVState {
     pub(crate) fn new() -> Self {
         Self {
             hw_breakpoints_enabled: false,
-            hasresethaltreq: None,
             semihosting_command: None,
         }
     }
 }
 
 memory_mapped_bitfield_register! {
-    /// `dmcontrol` register, located at
-    /// address 0x10
+    /// `dmcontrol` register, located at address 0x10
     pub struct Dmcontrol(u32);
     0x10, "dmcontrol",
     impl From;
-    _, set_haltreq: 31;
-    _, set_resumereq: 30;
-    hartreset, set_hartreset: 29;
-    _, set_ackhavereset: 28;
-    hasel, set_hasel: 26;
-    hartsello, set_hartsello: 25, 16;
-    hartselhi, set_hartselhi: 15, 6;
-    _, set_resethaltreq: 3;
-    _, set_clrresethaltreq: 2;
-    ndmreset, set_ndmreset: 1;
-    dmactive, set_dmactive: 0;
+
+    /// Requests the currently selected harts to halt.
+    pub _, set_haltreq: 31;
+
+    /// Requests the currently selected harts to resume.
+    pub _, set_resumereq: 30;
+
+    /// Requests the currently selected harts to reset. Optional.
+    pub hartreset, set_hartreset: 29;
+
+    /// Writing 1 clears the `havereset` flag of selected harts.
+    pub _, set_ackhavereset: 28;
+
+    /// Selects the definition of currently selected harts. If 1, multiple harts may be selected.
+    pub hasel, set_hasel: 26;
+
+    /// The lower 10 bits of the currently selected harts.
+    pub hartsello, set_hartsello: 25, 16;
+
+    /// The upper 10 bits of the currently selected harts.
+    pub hartselhi, set_hartselhi: 15, 6;
+
+    /// Writes the halt-on-reset request bit for all currently selected hart. Optional.
+    pub _, set_resethaltreq: 3;
+
+    /// Clears the halt-on-reset request bit for all currently selected harts. Optional.
+    pub _, set_clrresethaltreq: 2;
+
+    /// This bit controls the reset signal from the DM to the rest of the system.
+    pub ndmreset, set_ndmreset: 1;
+
+    /// Reset signal for the debug module.
+    pub dmactive, set_dmactive: 0;
 }
 
 impl Dmcontrol {
     /// Currently selected harts
     ///
     /// Combination of the `hartselhi` and `hartsello` registers.
-    fn hartsel(&self) -> u32 {
+    pub fn hartsel(&self) -> u32 {
         self.hartselhi() << 10 | self.hartsello()
     }
 
@@ -929,7 +768,7 @@ impl Dmcontrol {
     ///
     /// This sets the `hartselhi` and `hartsello` registers.
     /// This is a 20 bit register, larger values will be truncated.
-    fn set_hartsel(&mut self, value: u32) {
+    pub fn set_hartsel(&mut self, value: u32) {
         self.set_hartsello(value & 0x3ff);
         self.set_hartselhi((value >> 10) & 0x3ff);
     }
@@ -963,21 +802,21 @@ memory_mapped_bitfield_register! {
 }
 
 bitfield! {
-        struct Dcsr(u32);
-        impl Debug;
-
-        xdebugver, _: 31, 28;
-        ebreakm, set_ebreakm: 15;
-        ebreaks, set_ebreaks: 13;
-        ebreaku, set_ebreaku: 12;
-        stepie, set_stepie: 11;
-        stopcount, set_stopcount: 10;
-        stoptime, set_stoptime: 9;
-        cause, set_cause: 8, 6;
-        mprven, set_mprven: 4;
-        nmip, _: 3;
-        step, set_step: 2;
-        prv, set_prv: 1,0;
+    struct Dcsr(u32);
+    impl Debug;
+
+    xdebugver, _: 31, 28;
+    ebreakm, set_ebreakm: 15;
+    ebreaks, set_ebreaks: 13;
+    ebreaku, set_ebreaku: 12;
+    stepie, set_stepie: 11;
+    stopcount, set_stopcount: 10;
+    stoptime, set_stoptime: 9;
+    cause, set_cause: 8, 6;
+    mprven, set_mprven: 4;
+    nmip, _: 3;
+    step, set_step: 2;
+    prv, set_prv: 1,0;
 }
 
 memory_mapped_bitfield_register! {
diff --git a/probe-rs/src/architecture/riscv/sequences.rs b/probe-rs/src/architecture/riscv/sequences.rs
index 088c2d4b..1c8a3179 100644
--- a/probe-rs/src/architecture/riscv/sequences.rs
+++ b/probe-rs/src/architecture/riscv/sequences.rs
@@ -1,8 +1,12 @@
 //! Debug sequences to operate special requirements RISC-V targets.
 
+use crate::architecture::riscv::communication_interface::RiscvError;
+use crate::architecture::riscv::Dmcontrol;
+
 use super::communication_interface::RiscvCommunicationInterface;
 use std::fmt::Debug;
 use std::sync::Arc;
+use std::time::Duration;
 
 /// A interface to operate debug sequences for RISC-V targets.
 ///
@@ -20,6 +24,55 @@ pub trait RiscvDebugSequence: Send + Sync + Debug {
     ) -> Result<Option<usize>, crate::Error> {
         Ok(None)
     }
+
+    /// Configure the target to stop code execution after a reset. After this, the core will halt when it comes
+    /// out of reset.
+    fn reset_catch_set(
+        &self,
+        interface: &mut RiscvCommunicationInterface,
+    ) -> Result<(), RiscvError> {
+        if !interface.supports_reset_halt_req()? {
+            return Err(RiscvError::ResetHaltRequestNotSupported);
+        }
+
+        let mut dmcontrol: Dmcontrol = interface.read_dm_register()?;
+
+        dmcontrol.set_dmactive(true);
+        dmcontrol.set_resethaltreq(true);
+
+        interface.write_dm_register(dmcontrol)?;
+
+        Ok(())
+    }
+
+    /// Free hardware resources allocated by ResetCatchSet.
+    fn reset_catch_clear(
+        &self,
+        interface: &mut RiscvCommunicationInterface,
+    ) -> Result<(), RiscvError> {
+        if !interface.supports_reset_halt_req()? {
+            return Err(RiscvError::ResetHaltRequestNotSupported);
+        }
+
+        let mut dmcontrol: Dmcontrol = interface.read_dm_register()?;
+
+        dmcontrol.set_dmactive(true);
+        dmcontrol.set_clrresethaltreq(true);
+
+        interface.write_dm_register(dmcontrol)?;
+
+        Ok(())
+    }
+
+    /// Executes a system-wide reset without debug domain (or warm-reset that preserves debug connection) via software mechanisms.
+    fn reset_system_and_halt(
+        &self,
+        interface: &mut RiscvCommunicationInterface,
+        timeout: Duration,
+    ) -> Result<(), crate::Error> {
+        interface.reset_hart_and_halt(timeout)?;
+        Ok(())
+    }
 }
 
 /// The default sequences that is used for RISC-V chips that do not specify a specific sequence.
diff --git a/probe-rs/src/architecture/xtensa/communication_interface.rs b/probe-rs/src/architecture/xtensa/communication_interface.rs
index 98c00ac1..993f1d5e 100644
--- a/probe-rs/src/architecture/xtensa/communication_interface.rs
+++ b/probe-rs/src/architecture/xtensa/communication_interface.rs
@@ -16,26 +16,25 @@ use crate::{
 use super::xdm::{Error as XdmError, Xdm};
 
 /// Possible Xtensa errors
-#[derive(thiserror::Error, Debug)]
+#[derive(thiserror::Error, Debug, docsplay::Display)]
 pub enum XtensaError {
-    /// An error originating from the DebugProbe
-    #[error("Debug Probe Error")]
+    /// An error originating from the DebugProbe occurred
     DebugProbe(#[from] DebugProbeError),
+
     /// Xtensa debug module error
-    #[error("Xtensa debug module error")]
     XdmError(#[from] XdmError),
-    /// A timeout occurred
+
+    /// The operation has timed out
     // TODO: maybe we could be a bit more specific
-    #[error("The operation has timed out")]
     Timeout,
+
     /// The connected target is not an Xtensa device.
-    #[error("Connected target is not an Xtensa device.")]
     NoXtensaTarget,
+
     /// The requested register is not available.
-    #[error("The requested register is not available.")]
     RegisterNotAvailable,
+
     /// The result index of a batched command is not available.
-    #[error("The requested data is not available due to a previous error.")]
     BatchedResultNotAvailable,
 }
 
@@ -175,41 +174,6 @@ impl XtensaCommunicationInterface {
         Ok(())
     }
 
-    /// Resets the processor core.
-    pub fn reset(&mut self) -> Result<(), XtensaError> {
-        match self.reset_and_halt(Duration::from_millis(500)) {
-            Ok(_) => {
-                self.resume()?;
-
-                Ok(())
-            }
-            Err(error) => Err(XtensaError::DebugProbe(DebugProbeError::Other(
-                anyhow::anyhow!("Error during reset").context(error),
-            ))),
-        }
-    }
-
-    /// Resets the processor core and halts it immediately.
-    pub fn reset_and_halt(&mut self, timeout: Duration) -> Result<(), XtensaError> {
-        self.xdm.target_reset_assert()?;
-        self.xdm.halt_on_reset(true);
-        self.xdm.target_reset_deassert()?;
-        self.wait_for_core_halted(timeout)?;
-        self.xdm.halt_on_reset(false);
-
-        // TODO: this is only necessary to run code, so this might not be the best place
-        // Make sure the CPU is in a known state and is able to run code we download.
-        self.write_register({
-            let mut ps = ProgramStatus(0);
-            ps.set_intlevel(1);
-            ps.set_user_mode(true);
-            ps.set_woe(true);
-            ps
-        })?;
-
-        Ok(())
-    }
-
     /// Halts the core.
     pub fn halt(&mut self) -> Result<(), XtensaError> {
         tracing::debug!("Halting core");
@@ -662,7 +626,7 @@ impl XtensaCommunicationInterface {
         self.xdm.execute()
     }
 
-    fn write_memory(&mut self, address: u64, data: &[u8]) -> Result<(), XtensaError> {
+    pub(crate) fn write_memory(&mut self, address: u64, data: &[u8]) -> Result<(), XtensaError> {
         tracing::debug!("Writing {} bytes to address {:08x}", data.len(), address);
         if data.is_empty() {
             return Ok(());
@@ -728,6 +692,12 @@ impl XtensaCommunicationInterface {
 
         Ok(())
     }
+
+    pub(crate) fn reset_and_halt(&mut self) -> Result<(), XtensaError> {
+        self.xdm.reset_and_halt()?;
+
+        Ok(())
+    }
 }
 
 /// DataType
diff --git a/probe-rs/src/architecture/xtensa/mod.rs b/probe-rs/src/architecture/xtensa/mod.rs
index 9b73e42c..fd97250a 100644
--- a/probe-rs/src/architecture/xtensa/mod.rs
+++ b/probe-rs/src/architecture/xtensa/mod.rs
@@ -1,6 +1,6 @@
 //! All the interface bits for Xtensa.
 
-use std::time::Duration;
+use std::{sync::Arc, time::Duration};
 
 use probe_rs_target::{Architecture, CoreType, InstructionSet};
 
@@ -9,6 +9,7 @@ use crate::{
         arch::{instruction::Instruction, Register, SpecialRegister},
         communication_interface::{DebugCause, IBreakEn},
         registers::{FP, PC, RA, SP, XTENSA_CORE_REGSISTERS},
+        sequences::XtensaDebugSequence,
     },
     core::{
         registers::{CoreRegisters, RegisterId, RegisterValue},
@@ -62,22 +63,28 @@ impl XtensaState {
     }
 }
 
-/// An interface to operate Xtensa cores.
+/// An interface to operate an Xtensa core.
 pub struct Xtensa<'probe> {
     interface: &'probe mut XtensaCommunicationInterface,
     state: &'probe mut XtensaState,
+    sequence: Arc<dyn XtensaDebugSequence>,
 }
 
 impl<'probe> Xtensa<'probe> {
     const IBREAKA_REGS: [SpecialRegister; 2] =
         [SpecialRegister::IBreakA0, SpecialRegister::IBreakA1];
 
-    /// Create a new Xtensa interface.
+    /// Create a new Xtensa interface for a particular core.
     pub fn new(
         interface: &'probe mut XtensaCommunicationInterface,
         state: &'probe mut XtensaState,
+        sequence: Arc<dyn XtensaDebugSequence>,
     ) -> Self {
-        Self { interface, state }
+        Self {
+            interface,
+            state,
+            sequence,
+        }
     }
 
     fn core_info(&mut self) -> Result<CoreInformation, Error> {
@@ -293,12 +300,14 @@ impl<'probe> CoreInterface for Xtensa<'probe> {
 
     fn reset(&mut self) -> Result<(), Error> {
         self.state.semihosting_command = None;
-        Ok(self.interface.reset()?)
+        self.sequence.reset_system_and_halt(self.interface)?;
+
+        self.run()
     }
 
-    fn reset_and_halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
+    fn reset_and_halt(&mut self, _timeout: Duration) -> Result<CoreInformation, Error> {
         self.state.semihosting_command = None;
-        self.interface.reset_and_halt(timeout)?;
+        self.sequence.reset_system_and_halt(self.interface)?;
 
         self.core_info()
     }
@@ -443,13 +452,11 @@ impl<'probe> CoreInterface for Xtensa<'probe> {
     }
 
     fn reset_catch_set(&mut self) -> Result<(), Error> {
-        self.interface.xdm.halt_on_reset(true);
-        Ok(())
+        Err(Error::NotImplemented("reset_catch_set"))
     }
 
     fn reset_catch_clear(&mut self) -> Result<(), Error> {
-        self.interface.xdm.halt_on_reset(false);
-        Ok(())
+        Err(Error::NotImplemented("reset_catch_clear"))
     }
 
     fn debug_core_stop(&mut self) -> Result<(), Error> {
diff --git a/probe-rs/src/architecture/xtensa/sequences.rs b/probe-rs/src/architecture/xtensa/sequences.rs
index 225210e2..fbb55258 100644
--- a/probe-rs/src/architecture/xtensa/sequences.rs
+++ b/probe-rs/src/architecture/xtensa/sequences.rs
@@ -1,6 +1,8 @@
 use std::{fmt::Debug, sync::Arc};
 
-use crate::architecture::xtensa::communication_interface::XtensaCommunicationInterface;
+use crate::architecture::xtensa::communication_interface::{
+    ProgramStatus, XtensaCommunicationInterface, XtensaError,
+};
 
 /// A interface to operate debug sequences for Xtensa targets.
 ///
@@ -21,6 +23,26 @@ pub trait XtensaDebugSequence: Send + Sync + Debug {
     ) -> Result<Option<usize>, crate::Error> {
         Ok(None)
     }
+
+    /// Executes a system-wide reset without debug domain (or warm-reset that preserves debug connection) via software mechanisms.
+    fn reset_system_and_halt(
+        &self,
+        interface: &mut XtensaCommunicationInterface,
+    ) -> Result<(), XtensaError> {
+        interface.reset_and_halt()?;
+
+        // TODO: this is only necessary to run code, so this might not be the best place
+        // Make sure the CPU is in a known state and is able to run code we download.
+        interface.write_register({
+            let mut ps = ProgramStatus(0);
+            ps.set_intlevel(1);
+            ps.set_user_mode(true);
+            ps.set_woe(true);
+            ps
+        })?;
+
+        Ok(())
+    }
 }
 
 /// The default sequences that is used for Xtensa chips that do not specify a specific sequence.
diff --git a/probe-rs/src/architecture/xtensa/xdm.rs b/probe-rs/src/architecture/xtensa/xdm.rs
index 70b1821b..ca7f1919 100644
--- a/probe-rs/src/architecture/xtensa/xdm.rs
+++ b/probe-rs/src/architecture/xtensa/xdm.rs
@@ -85,22 +85,26 @@ impl From<PowerDevice> for TapInstruction {
     }
 }
 
-#[derive(thiserror::Error, Debug, Copy, Clone)]
+#[derive(thiserror::Error, Debug, Copy, Clone, docsplay::Display)]
 pub enum DebugRegisterError {
-    #[error("Register is busy")]
+    /// Register is busy
     Busy,
 
-    #[error("Register-specific error")]
+    /// Register-specific error
     Error,
 
-    #[error("Unexpected value")]
-    Unexpected,
+    /// Unexpected value {0}
+    Unexpected(u8),
 }
 
 #[derive(thiserror::Error, Debug, Clone, Copy)]
 pub enum Error {
-    #[error("Error while accessing register")]
-    Xdm(#[from] DebugRegisterError),
+    #[error("Error {access} register {narsel:#04X}")]
+    Xdm {
+        narsel: u8,
+        access: &'static str,
+        source: DebugRegisterError,
+    },
 
     #[error("ExecExeception")]
     ExecExeception,
@@ -126,8 +130,6 @@ pub struct Xdm {
 
     last_instruction: Option<Instruction>,
 
-    halt_on_reset: bool,
-
     queue: JtagCommandQueue,
     jtag_results: DeferredResultSet,
 
@@ -143,8 +145,6 @@ impl Xdm {
             device_id: 0,
             last_instruction: None,
 
-            halt_on_reset: false,
-
             queue: JtagCommandQueue::new(),
             jtag_results: DeferredResultSet::new(),
 
@@ -160,6 +160,8 @@ impl Xdm {
 
     #[tracing::instrument(skip(self))]
     fn init(&mut self) -> Result<(), XtensaError> {
+        self.probe.tap_reset()?;
+
         let mut pwr_control = PowerControl(0);
 
         pwr_control.set_debug_wakeup(true);
@@ -240,6 +242,8 @@ impl Xdm {
     pub(super) fn execute(&mut self) -> Result<(), XtensaError> {
         let mut queue = std::mem::take(&mut self.queue);
 
+        tracing::debug!("Executing {} commands", queue.len());
+
         // Drop the status readers when we're done.
         // We take now to avoid a possibly recursive call to clear before it's time.
         let _idxs = std::mem::take(&mut self.status_idxs);
@@ -252,9 +256,10 @@ impl Xdm {
                 }
                 Err(e) => {
                     match e.error {
-                        ProbeRsError::Xtensa(XtensaError::XdmError(Error::Xdm(
-                            DebugRegisterError::Busy,
-                        ))) => {
+                        ProbeRsError::Xtensa(XtensaError::XdmError(Error::Xdm {
+                            source: DebugRegisterError::Busy,
+                            ..
+                        })) => {
                             // The specific nexus register may need some longer delay. For now we just
                             // retry, but we should probably add some no-ops later.
                         }
@@ -301,19 +306,22 @@ impl Xdm {
             address: TapInstruction::Nar.code(),
             data: nar.to_le_bytes().to_vec(),
             len: TapInstruction::Nar.bits(),
-            transform: |capture| {
-                let nar = TapInstruction::Nar.capture_to_u8(&capture);
-                let error = match nar & 0b00000011 {
-                    0 => return Ok(CommandResult::None),
-                    1 => DebugRegisterError::Error,
-                    2 => DebugRegisterError::Busy,
-                    _ => DebugRegisterError::Unexpected,
-                };
+            transform: |write, capture| {
+                let capture = TapInstruction::Nar.capture_to_u8(&capture);
+                let nar = write.data[0] >> 1;
+                let write = write.data[0] & 1 == 1;
 
                 // eww...?
-                Err(ProbeRsError::Xtensa(XtensaError::XdmError(Error::Xdm(
-                    error,
-                ))))
+                Err(ProbeRsError::Xtensa(XtensaError::XdmError(Error::Xdm {
+                    narsel: nar,
+                    access: if write { "writing" } else { "reading" },
+                    source: match capture & 0b00000011 {
+                        0 => return Ok(CommandResult::None),
+                        1 => DebugRegisterError::Error,
+                        2 => DebugRegisterError::Busy,
+                        _ => DebugRegisterError::Unexpected(capture),
+                    },
+                })))
             },
         });
 
@@ -567,7 +575,7 @@ impl Xdm {
         }
     }
 
-    pub fn target_reset_assert(&mut self) -> Result<(), XtensaError> {
+    pub fn reset_and_halt(&mut self) -> Result<(), XtensaError> {
         self.pwr_write(PowerDevice::PowerControl, {
             let mut pwr_control = PowerControl(0);
 
@@ -579,14 +587,7 @@ impl Xdm {
 
             pwr_control.0
         })?;
-
-        Ok(())
-    }
-
-    pub fn target_reset_deassert(&mut self) -> Result<(), XtensaError> {
-        if self.halt_on_reset {
-            self.halt()?;
-        }
+        self.halt()?;
 
         self.pwr_write(PowerDevice::PowerControl, {
             let mut pwr_control = PowerControl(0);
@@ -602,28 +603,33 @@ impl Xdm {
         Ok(())
     }
 
-    pub(crate) fn halt_on_reset(&mut self, en: bool) {
-        self.halt_on_reset = en;
-    }
-
     pub(super) fn free(self) -> Box<dyn JTAGAccess> {
         self.probe
     }
 }
 
-type TransformFn = fn(Vec<u8>) -> Result<CommandResult, ProbeRsError>;
+type TransformFn = fn(&JtagWriteCommand, Vec<u8>) -> Result<CommandResult, ProbeRsError>;
 
-fn transform_u32(capture: Vec<u8>) -> Result<CommandResult, ProbeRsError> {
+fn transform_u32(
+    _command: &JtagWriteCommand,
+    capture: Vec<u8>,
+) -> Result<CommandResult, ProbeRsError> {
     Ok(CommandResult::U32(
         TapInstruction::Ndr.capture_to_u32(&capture),
     ))
 }
 
-fn transform_noop(_capture: Vec<u8>) -> Result<CommandResult, ProbeRsError> {
+fn transform_noop(
+    _command: &JtagWriteCommand,
+    _capture: Vec<u8>,
+) -> Result<CommandResult, ProbeRsError> {
     Ok(CommandResult::None)
 }
 
-fn transform_instruction_status(capture: Vec<u8>) -> Result<CommandResult, ProbeRsError> {
+fn transform_instruction_status(
+    _command: &JtagWriteCommand,
+    capture: Vec<u8>,
+) -> Result<CommandResult, ProbeRsError> {
     let status = DebugStatus(TapInstruction::Ndr.capture_to_u32(&capture));
 
     if status.exec_overrun() {
@@ -645,14 +651,6 @@ fn transform_instruction_status(capture: Vec<u8>) -> Result<CommandResult, Probe
     Ok(CommandResult::None)
 }
 
-// TODO: I don't think these should be transformed into XtensaError directly. We might want to
-// attach register-specific messages via an in-between type.
-impl From<DebugRegisterError> for XtensaError {
-    fn from(e: DebugRegisterError) -> Self {
-        XtensaError::XdmError(e.into())
-    }
-}
-
 bitfield::bitfield! {
     #[derive(Copy, Clone)]
     pub struct PowerControl(u8);
diff --git a/probe-rs/src/bin/probe-rs/cmd/dap_server/mod.rs b/probe-rs/src/bin/probe-rs/cmd/dap_server/mod.rs
index e62a9f45..8f811998 100644
--- a/probe-rs/src/bin/probe-rs/cmd/dap_server/mod.rs
+++ b/probe-rs/src/bin/probe-rs/cmd/dap_server/mod.rs
@@ -14,7 +14,12 @@ use probe_rs::{
     probe::DebugProbeError, CoreDumpError, Error,
 };
 use server::startup::debug;
-use std::{fs::File, io::stderr, path::Path};
+use std::{
+    fs::File,
+    io::stderr,
+    net::{IpAddr, Ipv4Addr, SocketAddr},
+    path::Path,
+};
 use time::UtcOffset;
 use tracing::metadata::LevelFilter;
 use tracing_subscriber::{
@@ -75,6 +80,10 @@ pub struct Cmd {
     #[clap(long)]
     port: u16,
 
+    /// IP address to listen for incoming DAP connections, e.g. "127.0.0.1"
+    #[clap(long, default_value_t = Ipv4Addr::LOCALHOST.into())]
+    ip: IpAddr,
+
     /// Some editors and IDEs expect the debug adapter processes to exit at the end of every debug
     /// session (on receiving a `Disconnect` or `Terminate` request).
     ///
@@ -92,10 +101,11 @@ pub fn run(
     log_file: Option<&Path>,
 ) -> Result<()> {
     let log_info_message = setup_logging(log_file)?;
+    let addr = SocketAddr::new(cmd.ip, cmd.port);
 
     debug(
         lister,
-        cmd.port,
+        addr,
         cmd.single_session,
         &log_info_message,
         time_offset,
diff --git a/probe-rs/src/bin/probe-rs/cmd/dap_server/server/startup.rs b/probe-rs/src/bin/probe-rs/cmd/dap_server/server/startup.rs
index 0befb351..670eed29 100644
--- a/probe-rs/src/bin/probe-rs/cmd/dap_server/server/startup.rs
+++ b/probe-rs/src/bin/probe-rs/cmd/dap_server/server/startup.rs
@@ -5,7 +5,7 @@ use probe_rs::probe::list::Lister;
 use serde::Deserialize;
 use std::{
     fs,
-    net::{Ipv4Addr, TcpListener},
+    net::TcpListener,
     path::Path,
     time::{Duration, UNIX_EPOCH},
 };
@@ -33,7 +33,7 @@ impl std::str::FromStr for TargetSessionType {
 
 pub fn debug(
     lister: &Lister,
-    port: u16,
+    addr: std::net::SocketAddr,
     single_session: bool,
     log_info_message: &str,
     timestamp_offset: UtcOffset,
@@ -42,8 +42,6 @@ pub fn debug(
 
     log_to_console_and_tracing("Starting as a DAP Protocol server");
 
-    let addr = std::net::SocketAddr::new(std::net::IpAddr::V4(Ipv4Addr::LOCALHOST), port);
-
     // Tell the user if (and where) RUST_LOG messages are written.
     log_to_console_and_tracing(log_info_message);
 
diff --git a/probe-rs/src/bin/probe-rs/cmd/run/mod.rs b/probe-rs/src/bin/probe-rs/cmd/run/mod.rs
index 39498fa7..87d41773 100644
--- a/probe-rs/src/bin/probe-rs/cmd/run/mod.rs
+++ b/probe-rs/src/bin/probe-rs/cmd/run/mod.rs
@@ -239,7 +239,9 @@ impl RunLoop {
         F: FnMut(HaltReason, &mut Core) -> Result<Option<R>>,
     {
         if catch_hardfault || catch_reset {
-            core.halt(Duration::from_millis(100))?;
+            if !core.core_halted()? {
+                core.halt(Duration::from_millis(100))?;
+            }
 
             if catch_hardfault {
                 match core.enable_vector_catch(VectorCatchCondition::HardFault) {
diff --git a/probe-rs/src/config/registry.rs b/probe-rs/src/config/registry.rs
index 017fbc83..1cf7ac0c 100644
--- a/probe-rs/src/config/registry.rs
+++ b/probe-rs/src/config/registry.rs
@@ -145,112 +145,110 @@ impl Registry {
     }
 
     fn get_target_by_name(&self, name: impl AsRef<str>) -> Result<Target, RegistryError> {
-        let (target, _) = self.get_target_and_family_by_name(name)?;
+        let (target, _) = self.get_target_and_family_by_name(name.as_ref())?;
         Ok(target)
     }
 
     fn get_target_and_family_by_name(
         &self,
-        name: impl AsRef<str>,
+        name: &str,
     ) -> Result<(Target, ChipFamily), RegistryError> {
-        let name = name.as_ref();
-
         tracing::debug!("Searching registry for chip with name {}", name);
 
-        let (family, chip) = {
-            // Try get the corresponding chip.
-            let mut selected_family_and_chip = None;
-            let mut exact_matches = 0;
-            let mut partial_matches = Vec::new();
-            for family in &self.families {
-                for variant in family.variants.iter() {
-                    if match_name_prefix(&variant.name, name) {
-                        if variant.name.len() == name.len() {
-                            tracing::debug!("Exact match for chip name: {}", variant.name);
-                            exact_matches += 1;
-                        } else {
-                            tracing::debug!("Partial match for chip name: {}", &variant.name);
-                            partial_matches.push(variant.name.clone());
-                            if exact_matches > 0 {
-                                continue;
-                            }
+        // Try get the corresponding chip.
+        let mut selected_family_and_chip = None;
+        let mut exact_matches = 0;
+        let mut partial_matches = Vec::new();
+        for family in self.families.iter() {
+            for variant in family.variants.iter() {
+                if match_name_prefix(&variant.name, name) {
+                    if variant.name.len() == name.len() {
+                        tracing::debug!("Exact match for chip name: {}", variant.name);
+                        exact_matches += 1;
+                    } else {
+                        tracing::debug!("Partial match for chip name: {}", variant.name);
+                        partial_matches.push(variant.name.as_str());
+                        // Only select partial match if we don't have an exact match yet
+                        if exact_matches > 0 {
+                            continue;
                         }
-                        selected_family_and_chip = Some((family, variant));
                     }
+                    selected_family_and_chip = Some((family, variant));
                 }
             }
-            if exact_matches == 0 && partial_matches.len() > 1 {
-                tracing::warn!(
-                    "Ignoring ambiguous matches for specified chip name {}",
-                    name,
-                );
-                let mut suggestions;
-                if partial_matches.len() <= 100 {
-                    suggestions = partial_matches.join(", ");
-                } else {
-                    // prevent too much text being printed if too many matches
-                    suggestions = partial_matches[0..100].join(", ");
-                    suggestions.push_str(&format!(" and {} more", partial_matches.len() - 100))
+        }
+
+        let Some((family, chip)) = selected_family_and_chip else {
+            return Err(RegistryError::ChipNotFound(name.to_string()));
+        };
+
+        if exact_matches == 0 {
+            match partial_matches.len() {
+                0 => {}
+                1 => {
+                    tracing::warn!(
+                        "Found chip {} which matches given partial name {}. Consider specifying its full name.",
+                        chip.name,
+                        name,
+                    );
+                }
+                matches => {
+                    const MAX_PRINTED_MATCHES: usize = 100;
+                    tracing::warn!(
+                        "Ignoring {matches} ambiguous matches for specified chip name {name}"
+                    );
+
+                    let (print, overflow) =
+                        partial_matches.split_at(MAX_PRINTED_MATCHES.min(matches));
+
+                    let mut suggestions = print.join(", ");
+
+                    // Avoid "and 1 more" by printing the last item.
+                    match overflow.len() {
+                        0 => {}
+                        1 => suggestions.push_str(&format!(", {}", overflow[0])),
+                        _ => suggestions.push_str(&format!("and {} more", overflow.len())),
+                    }
+
+                    return Err(RegistryError::ChipNotUnique(name.to_string(), suggestions));
                 }
-                return Err(RegistryError::ChipNotUnique(name.to_owned(), suggestions));
-            }
-            let (family, chip) = selected_family_and_chip
-                .ok_or_else(|| RegistryError::ChipNotFound(name.to_owned()))?;
-            if exact_matches == 0 && partial_matches.len() == 1 {
-                tracing::warn!(
-                    "Found chip {} which matches given partial name {}. Consider specifying its full name.",
-                    chip.name,
-                    name,
-                );
-            }
-            if chip.name.to_ascii_lowercase() != name.to_ascii_lowercase() {
-                tracing::warn!(
-                    "Matching {} based on wildcard. Consider specifying the chip as {} instead.",
-                    name,
-                    chip.name,
-                );
             }
+        }
+
+        if !chip.name.eq_ignore_ascii_case(name) {
+            tracing::warn!(
+                "Matching {} based on wildcard. Consider specifying the chip as {} instead.",
+                name,
+                chip.name,
+            );
+        }
 
-            // Try get the correspnding flash algorithm.
-            (family, chip)
-        };
         let targ = self.get_target(family, chip)?;
         Ok((targ, family.clone()))
     }
 
-    fn get_targets_by_family_name(
-        &self,
-        family_name: impl AsRef<str>,
-    ) -> Result<Vec<String>, RegistryError> {
-        let name: &str = family_name.as_ref();
-
-        let family = {
-            let mut finded_family = None;
-            let mut exact_matches = 0;
-            for family in &self.families {
-                if match_name_prefix(&family.name, name) {
-                    if family.name.len() == name.len() {
-                        tracing::debug!("Exact match for family name: {}", family.name);
-                        exact_matches += 1;
-                    } else {
-                        tracing::debug!("Partial match for family name: {}", family.name);
-                        if exact_matches > 0 {
-                            continue;
-                        }
+    fn get_targets_by_family_name(&self, name: &str) -> Result<Vec<String>, RegistryError> {
+        let mut found_family = None;
+        let mut exact_matches = 0;
+        for family in self.families.iter() {
+            if match_name_prefix(&family.name, name) {
+                if family.name.len() == name.len() {
+                    tracing::debug!("Exact match for family name: {}", family.name);
+                    exact_matches += 1;
+                } else {
+                    tracing::debug!("Partial match for family name: {}", family.name);
+                    if exact_matches > 0 {
+                        continue;
                     }
-                    finded_family = Some(family);
                 }
+                found_family = Some(family);
             }
-            finded_family.ok_or_else(|| RegistryError::ChipNotFound(name.to_owned()))?
-        };
-
-        let mut all_family_targets = Vec::new();
-
-        for target in &family.variants {
-            all_family_targets.push(target.name.clone());
         }
+        let Some(family) = found_family else {
+            return Err(RegistryError::ChipNotFound(name.to_string()));
+        };
 
-        Ok(all_family_targets)
+        Ok(family.variants.iter().map(|v| v.name.to_string()).collect())
     }
 
     fn search_chips(&self, name: &str) -> Vec<String> {
@@ -260,12 +258,8 @@ impl Registry {
 
         for family in &self.families {
             for variant in family.variants.iter() {
-                if variant
-                    .name
-                    .to_ascii_lowercase()
-                    .starts_with(&name.to_ascii_lowercase())
-                {
-                    targets.push(variant.name.to_string())
+                if match_name_prefix(name, &variant.name) {
+                    targets.push(variant.name.to_string());
                 }
             }
         }
@@ -328,13 +322,9 @@ impl Registry {
             .validate()
             .map_err(|e| RegistryError::InvalidChipFamilyDefinition(Box::new(family.clone()), e))?;
 
-        let index = self
-            .families
-            .iter()
-            .position(|old_family| old_family.name == family.name);
-        if let Some(index) = index {
-            self.families.remove(index);
-        }
+        self.families
+            .retain(|old_family| !old_family.name.eq_ignore_ascii_case(&family.name));
+
         self.families.push(family);
 
         Ok(())
@@ -350,7 +340,10 @@ pub fn get_target_by_name(name: impl AsRef<str>) -> Result<Target, RegistryError
 pub fn get_target_and_family_by_name(
     name: impl AsRef<str>,
 ) -> Result<(Target, ChipFamily), RegistryError> {
-    REGISTRY.lock().unwrap().get_target_and_family_by_name(name)
+    REGISTRY
+        .lock()
+        .unwrap()
+        .get_target_and_family_by_name(name.as_ref())
 }
 
 /// Get all target from the internal registry based on its family name.
@@ -360,10 +353,10 @@ pub fn get_targets_by_family_name(
     REGISTRY
         .lock()
         .unwrap()
-        .get_targets_by_family_name(family_name)
+        .get_targets_by_family_name(family_name.as_ref())
 }
 
-/// Get a target from the internal registry based on its name.
+/// Returns targets from the internal registry that match the given name.
 pub fn search_chips(name: impl AsRef<str>) -> Result<Vec<String>, RegistryError> {
     Ok(REGISTRY.lock().unwrap().search_chips(name.as_ref()))
 }
@@ -416,8 +409,8 @@ pub fn families() -> Result<Vec<ChipFamily>, RegistryError> {
 fn match_name_prefix(pattern: &str, name: &str) -> bool {
     // If `name` is shorter than `pattern` but all characters in `name` match,
     // the iterator will end early and the function returns true.
-    for (n, p) in name.to_ascii_lowercase().chars().zip(pattern.chars()) {
-        if p.to_ascii_lowercase() != n && p != 'x' {
+    for (n, p) in name.chars().zip(pattern.chars()) {
+        if !n.eq_ignore_ascii_case(&p) && p != 'x' {
             return false;
         }
     }
diff --git a/probe-rs/src/config/sequences/esp.rs b/probe-rs/src/config/sequences/esp.rs
index 733cec59..f4740568 100644
--- a/probe-rs/src/config/sequences/esp.rs
+++ b/probe-rs/src/config/sequences/esp.rs
@@ -8,6 +8,7 @@ use crate::{
         xtensa::{
             arch::{instruction::Instruction, CpuRegister, Register},
             communication_interface::XtensaCommunicationInterface,
+            sequences::XtensaDebugSequence,
         },
     },
     MemoryInterface,
@@ -40,6 +41,7 @@ impl EspFlashSizeDetector {
     pub fn detect_flash_size_esp32(
         &self,
         interface: &mut XtensaCommunicationInterface,
+        sequence: &impl XtensaDebugSequence,
     ) -> Result<Option<usize>, crate::Error> {
         tracing::info!("Detecting flash size");
         attach_flash_xtensa(
@@ -47,6 +49,7 @@ impl EspFlashSizeDetector {
             self.stack_pointer,
             self.load_address,
             self.attach_fn,
+            sequence,
         )?;
         detect_flash_size_esp32(interface, self.spiflash_peripheral)
     }
@@ -54,6 +57,7 @@ impl EspFlashSizeDetector {
     pub fn detect_flash_size_xtensa(
         &self,
         interface: &mut XtensaCommunicationInterface,
+        sequence: &impl XtensaDebugSequence,
     ) -> Result<Option<usize>, crate::Error> {
         tracing::info!("Detecting flash size");
         attach_flash_xtensa(
@@ -61,6 +65,7 @@ impl EspFlashSizeDetector {
             self.stack_pointer,
             self.load_address,
             self.attach_fn,
+            sequence,
         )?;
         tracing::info!("Flash attached");
         detect_flash_size(interface, self.spiflash_peripheral)
@@ -120,9 +125,11 @@ fn attach_flash_xtensa(
     stack_pointer: u32,
     load_addr: u32,
     attach_fn: u32,
+    sequence: &impl XtensaDebugSequence,
 ) -> Result<(), crate::Error> {
     // We're very intrusive here but the flashing process should reset the MCU again anyway
-    interface.reset_and_halt(Duration::from_millis(500))?;
+    sequence.reset_system_and_halt(interface)?;
+    interface.resume()?;
 
     let mut instructions = vec![];
     Instruction::CallX8(CpuRegister::A4).encode_into_vec(&mut instructions);
diff --git a/probe-rs/src/config/sequences/esp32.rs b/probe-rs/src/config/sequences/esp32.rs
index becee5f8..1d785b54 100644
--- a/probe-rs/src/config/sequences/esp32.rs
+++ b/probe-rs/src/config/sequences/esp32.rs
@@ -69,6 +69,6 @@ impl XtensaDebugSequence for ESP32 {
         &self,
         interface: &mut XtensaCommunicationInterface,
     ) -> Result<Option<usize>, crate::Error> {
-        self.inner.detect_flash_size_esp32(interface)
+        self.inner.detect_flash_size_esp32(interface, self)
     }
 }
diff --git a/probe-rs/src/config/sequences/esp32c2.rs b/probe-rs/src/config/sequences/esp32c2.rs
index 75484de9..ce026dc1 100644
--- a/probe-rs/src/config/sequences/esp32c2.rs
+++ b/probe-rs/src/config/sequences/esp32c2.rs
@@ -1,12 +1,13 @@
 //! Sequence for the ESP32C2.
 
-use std::sync::Arc;
+use std::{sync::Arc, time::Duration};
 
 use probe_rs_target::Chip;
 
 use crate::{
     architecture::riscv::{
         communication_interface::RiscvCommunicationInterface, sequences::RiscvDebugSequence,
+        Dmcontrol,
     },
     config::sequences::esp::EspFlashSizeDetector,
     MemoryInterface,
@@ -60,4 +61,36 @@ impl RiscvDebugSequence for ESP32C2 {
     ) -> Result<Option<usize>, crate::Error> {
         self.inner.detect_flash_size_riscv(interface)
     }
+
+    fn reset_system_and_halt(
+        &self,
+        interface: &mut RiscvCommunicationInterface,
+        timeout: Duration,
+    ) -> Result<(), crate::Error> {
+        interface.halt(timeout)?;
+
+        // Reset all peripherals except for the RTC block.
+
+        // At this point the core is reset and halted, ready for us to issue a system reset
+        // Trigger reset via RTC_CNTL_SW_SYS_RST
+        interface.write_word_32(0x6000_8000, 0x9C00_A000)?;
+
+        // Workaround for stuck in cpu start during calibration.
+        interface.write_word_32(0x6001_F068, 0)?;
+
+        // Wait for the reset to take effect.
+        std::thread::sleep(Duration::from_millis(10));
+
+        let mut dmcontrol = Dmcontrol(0);
+        dmcontrol.set_dmactive(true);
+        dmcontrol.set_ackhavereset(true);
+        interface.write_dm_register(dmcontrol)?;
+
+        interface.enter_debug_mode()?;
+        self.on_connect(interface)?;
+
+        interface.reset_hart_and_halt(timeout)?;
+
+        Ok(())
+    }
 }
diff --git a/probe-rs/src/config/sequences/esp32c3.rs b/probe-rs/src/config/sequences/esp32c3.rs
index 412e1458..b839c365 100644
--- a/probe-rs/src/config/sequences/esp32c3.rs
+++ b/probe-rs/src/config/sequences/esp32c3.rs
@@ -1,12 +1,13 @@
 //! Sequence for the ESP32C3.
 
-use std::sync::Arc;
+use std::{sync::Arc, time::Duration};
 
 use probe_rs_target::Chip;
 
 use crate::{
     architecture::riscv::{
         communication_interface::RiscvCommunicationInterface, sequences::RiscvDebugSequence,
+        Dmcontrol,
     },
     config::sequences::esp::EspFlashSizeDetector,
     MemoryInterface,
@@ -65,4 +66,36 @@ impl RiscvDebugSequence for ESP32C3 {
     ) -> Result<Option<usize>, crate::Error> {
         self.inner.detect_flash_size_riscv(interface)
     }
+
+    fn reset_system_and_halt(
+        &self,
+        interface: &mut RiscvCommunicationInterface,
+        timeout: Duration,
+    ) -> Result<(), crate::Error> {
+        interface.reset_hart_and_halt(timeout)?;
+
+        // Reset all peripherals except for the RTC block.
+
+        // At this point the core is reset and halted, ready for us to issue a system reset
+        // Trigger reset via RTC_CNTL_SW_SYS_RST
+        interface.write_word_32(0x6000_8000, 0x9C00_A000)?;
+
+        // Workaround for stuck in cpu start during calibration.
+        interface.write_word_32(0x6001_F068, 0)?;
+
+        // Wait for the reset to take effect.
+        std::thread::sleep(Duration::from_millis(10));
+
+        let mut dmcontrol = Dmcontrol(0);
+        dmcontrol.set_dmactive(true);
+        dmcontrol.set_ackhavereset(true);
+        interface.write_dm_register(dmcontrol)?;
+
+        interface.enter_debug_mode()?;
+        self.on_connect(interface)?;
+
+        interface.reset_hart_and_halt(timeout)?;
+
+        Ok(())
+    }
 }
diff --git a/probe-rs/src/config/sequences/esp32c6.rs b/probe-rs/src/config/sequences/esp32c6.rs
index 937ba42c..f9e50950 100644
--- a/probe-rs/src/config/sequences/esp32c6.rs
+++ b/probe-rs/src/config/sequences/esp32c6.rs
@@ -1,12 +1,14 @@
 //! Sequences for the ESP32C6.
 
-use std::sync::Arc;
+use std::{sync::Arc, time::Duration};
 
 use probe_rs_target::Chip;
 
 use crate::{
     architecture::riscv::{
-        communication_interface::RiscvCommunicationInterface, sequences::RiscvDebugSequence,
+        communication_interface::{RiscvCommunicationInterface, Sbaddress0, Sbcs, Sbdata0},
+        sequences::RiscvDebugSequence,
+        Dmcontrol,
     },
     config::sequences::esp::EspFlashSizeDetector,
     MemoryInterface,
@@ -65,4 +67,46 @@ impl RiscvDebugSequence for ESP32C6 {
     ) -> Result<Option<usize>, crate::Error> {
         self.inner.detect_flash_size_riscv(interface)
     }
+
+    fn reset_system_and_halt(
+        &self,
+        interface: &mut RiscvCommunicationInterface,
+        timeout: Duration,
+    ) -> Result<(), crate::Error> {
+        interface.halt(timeout)?;
+
+        // System reset, ported from OpenOCD.
+        interface.write_dm_register(Sbcs(0x48000))?;
+        interface.write_dm_register(Sbaddress0(0x600b1034))?;
+        interface.write_dm_register(Sbdata0(0x80000000_u32))?;
+
+        // clear dmactive to clear sbbusy otherwise debug module gets stuck
+        interface.write_dm_register(Dmcontrol(0))?;
+
+        interface.write_dm_register(Sbcs(0x48000))?;
+        interface.write_dm_register(Sbaddress0(0x600b1038))?;
+        interface.write_dm_register(Sbdata0(0x10000000_u32))?;
+
+        // clear dmactive to clear sbbusy otherwise debug module gets stuck
+        interface.write_dm_register(Dmcontrol(0))?;
+
+        let mut dmcontrol = Dmcontrol(0);
+        dmcontrol.set_dmactive(true);
+        dmcontrol.set_resumereq(true);
+        interface.write_dm_register(dmcontrol)?;
+
+        std::thread::sleep(Duration::from_millis(10));
+
+        let mut dmcontrol = Dmcontrol(0);
+        dmcontrol.set_dmactive(true);
+        dmcontrol.set_ackhavereset(true);
+        interface.write_dm_register(dmcontrol)?;
+
+        interface.enter_debug_mode()?;
+        self.on_connect(interface)?;
+
+        interface.reset_hart_and_halt(timeout)?;
+
+        Ok(())
+    }
 }
diff --git a/probe-rs/src/config/sequences/esp32h2.rs b/probe-rs/src/config/sequences/esp32h2.rs
index 232c9780..66c3fcf5 100644
--- a/probe-rs/src/config/sequences/esp32h2.rs
+++ b/probe-rs/src/config/sequences/esp32h2.rs
@@ -1,12 +1,14 @@
 //! Sequences for the ESP32H2.
 
-use std::sync::Arc;
+use std::{sync::Arc, time::Duration};
 
 use probe_rs_target::Chip;
 
 use crate::{
     architecture::riscv::{
-        communication_interface::RiscvCommunicationInterface, sequences::RiscvDebugSequence,
+        communication_interface::{RiscvCommunicationInterface, Sbaddress0, Sbcs, Sbdata0},
+        sequences::RiscvDebugSequence,
+        Dmcontrol,
     },
     config::sequences::esp::EspFlashSizeDetector,
     MemoryInterface,
@@ -65,4 +67,46 @@ impl RiscvDebugSequence for ESP32H2 {
     ) -> Result<Option<usize>, crate::Error> {
         self.inner.detect_flash_size_riscv(interface)
     }
+
+    fn reset_system_and_halt(
+        &self,
+        interface: &mut RiscvCommunicationInterface,
+        timeout: Duration,
+    ) -> Result<(), crate::Error> {
+        interface.halt(timeout)?;
+
+        // System reset, ported from OpenOCD.
+        interface.write_dm_register(Sbcs(0x48000))?;
+        interface.write_dm_register(Sbaddress0(0x600b1034))?;
+        interface.write_dm_register(Sbdata0(0x80000000_u32))?;
+
+        // clear dmactive to clear sbbusy otherwise debug module gets stuck
+        interface.write_dm_register(Dmcontrol(0))?;
+
+        interface.write_dm_register(Sbcs(0x48000))?;
+        interface.write_dm_register(Sbaddress0(0x600b1038))?;
+        interface.write_dm_register(Sbdata0(0x10000000_u32))?;
+
+        // clear dmactive to clear sbbusy otherwise debug module gets stuck
+        interface.write_dm_register(Dmcontrol(0))?;
+
+        let mut dmcontrol = Dmcontrol(0);
+        dmcontrol.set_dmactive(true);
+        dmcontrol.set_resumereq(true);
+        interface.write_dm_register(dmcontrol)?;
+
+        std::thread::sleep(Duration::from_millis(10));
+
+        let mut dmcontrol = Dmcontrol(0);
+        dmcontrol.set_dmactive(true);
+        dmcontrol.set_ackhavereset(true);
+        interface.write_dm_register(dmcontrol)?;
+
+        interface.enter_debug_mode()?;
+        self.on_connect(interface)?;
+
+        interface.reset_hart_and_halt(timeout)?;
+
+        Ok(())
+    }
 }
diff --git a/probe-rs/src/config/sequences/esp32s2.rs b/probe-rs/src/config/sequences/esp32s2.rs
index 043e0a77..a8e6b40c 100644
--- a/probe-rs/src/config/sequences/esp32s2.rs
+++ b/probe-rs/src/config/sequences/esp32s2.rs
@@ -67,6 +67,6 @@ impl XtensaDebugSequence for ESP32S2 {
         &self,
         interface: &mut XtensaCommunicationInterface,
     ) -> Result<Option<usize>, crate::Error> {
-        self.inner.detect_flash_size_xtensa(interface)
+        self.inner.detect_flash_size_xtensa(interface, self)
     }
 }
diff --git a/probe-rs/src/config/sequences/esp32s3.rs b/probe-rs/src/config/sequences/esp32s3.rs
index 9c18791b..61b01ed0 100644
--- a/probe-rs/src/config/sequences/esp32s3.rs
+++ b/probe-rs/src/config/sequences/esp32s3.rs
@@ -67,6 +67,6 @@ impl XtensaDebugSequence for ESP32S3 {
         &self,
         interface: &mut XtensaCommunicationInterface,
     ) -> Result<Option<usize>, crate::Error> {
-        self.inner.detect_flash_size_xtensa(interface)
+        self.inner.detect_flash_size_xtensa(interface, self)
     }
 }
diff --git a/probe-rs/src/core.rs b/probe-rs/src/core.rs
index cb67bbc3..4910d0f9 100644
--- a/probe-rs/src/core.rs
+++ b/probe-rs/src/core.rs
@@ -1,6 +1,12 @@
 use crate::{
-    architecture::arm::sequences::ArmDebugSequence, config::DebugSequence, debug::DebugRegisters,
-    error::Error, CoreType, InstructionSet, MemoryInterface, Target,
+    architecture::{
+        arm::sequences::ArmDebugSequence, riscv::sequences::RiscvDebugSequence,
+        xtensa::sequences::XtensaDebugSequence,
+    },
+    config::DebugSequence,
+    debug::DebugRegisters,
+    error::Error,
+    CoreType, InstructionSet, MemoryInterface, Target,
 };
 use anyhow::anyhow;
 pub use probe_rs_target::{Architecture, CoreAccessOptions};
@@ -415,7 +421,13 @@ impl<'probe> Core<'probe> {
                 }
             }
             CoreAccessOptions::Riscv(options) => {
-                let core_state = CoreState::new(ResolvedCoreOptions::Riscv { options });
+                let DebugSequence::Riscv(sequence) = target.debug_sequence.clone() else {
+                    panic!(
+                        "Mismatch between sequence and core kind. This is a bug, please report it."
+                    );
+                };
+
+                let core_state = CoreState::new(ResolvedCoreOptions::Riscv { sequence, options });
                 CombinedCoreState {
                     id,
                     core_state,
@@ -423,7 +435,13 @@ impl<'probe> Core<'probe> {
                 }
             }
             CoreAccessOptions::Xtensa(options) => {
-                let core_state = CoreState::new(ResolvedCoreOptions::Xtensa { options });
+                let DebugSequence::Xtensa(sequence) = target.debug_sequence.clone() else {
+                    panic!(
+                        "Mismatch between sequence and core kind. This is a bug, please report it."
+                    );
+                };
+
+                let core_state = CoreState::new(ResolvedCoreOptions::Xtensa { sequence, options });
                 CombinedCoreState {
                     id,
                     core_state,
@@ -706,6 +724,10 @@ impl<'probe> Core<'probe> {
         self.inner.floating_point_register_count()
     }
 
+    pub(crate) fn reset_catch_set(&mut self) -> Result<(), Error> {
+        self.inner.reset_catch_set()
+    }
+
     pub(crate) fn reset_catch_clear(&mut self) -> Result<(), Error> {
         self.inner.reset_catch_clear()
     }
@@ -874,7 +896,7 @@ impl<'probe> CoreInterface for Core<'probe> {
     }
 
     fn reset_catch_set(&mut self) -> Result<(), Error> {
-        todo!()
+        self.reset_catch_set()
     }
 
     fn reset_catch_clear(&mut self) -> Result<(), Error> {
@@ -892,9 +914,11 @@ pub enum ResolvedCoreOptions {
         options: ArmCoreAccessOptions,
     },
     Riscv {
+        sequence: Arc<dyn RiscvDebugSequence>,
         options: RiscvCoreAccessOptions,
     },
     Xtensa {
+        sequence: Arc<dyn XtensaDebugSequence>,
         options: XtensaCoreAccessOptions,
     },
 }
@@ -907,8 +931,16 @@ impl std::fmt::Debug for ResolvedCoreOptions {
                 .field("sequence", &"<ArmDebugSequence>")
                 .field("options", options)
                 .finish(),
-            Self::Riscv { options } => f.debug_struct("Riscv").field("options", options).finish(),
-            Self::Xtensa { options } => f.debug_struct("Xtensa").field("options", options).finish(),
+            Self::Riscv { options, .. } => f
+                .debug_struct("Riscv")
+                .field("sequence", &"<RiscvDebugSequence>")
+                .field("options", options)
+                .finish(),
+            Self::Xtensa { options, .. } => f
+                .debug_struct("Xtensa")
+                .field("sequence", &"<XtensaDebugSequence>")
+                .field("options", options)
+                .finish(),
         }
     }
 }
diff --git a/probe-rs/src/core/core_state.rs b/probe-rs/src/core/core_state.rs
index 2c08388b..9e31873b 100644
--- a/probe-rs/src/core/core_state.rs
+++ b/probe-rs/src/core/core_state.rs
@@ -158,12 +158,14 @@ impl CombinedCoreState {
         let memory_regions = &target.memory_map;
         let name = &target.cores[self.id].name;
 
-        let ResolvedCoreOptions::Riscv { options } = &self.core_state.core_access_options else {
+        let ResolvedCoreOptions::Riscv { options, sequence } = &self.core_state.core_access_options
+        else {
             unreachable!(
                 "The stored core state is not compatible with the RISC-V architecture. \
                 This should never happen. Please file a bug if it does."
             );
         };
+        let debug_sequence = sequence.clone();
 
         let SpecificCoreState::Riscv(s) = &mut self.specific_state else {
             unreachable!(
@@ -180,6 +182,7 @@ impl CombinedCoreState {
                 options.hart_id.unwrap_or_default(),
                 interface,
                 s,
+                debug_sequence,
             )?,
         ))
     }
@@ -192,6 +195,15 @@ impl CombinedCoreState {
         let memory_regions = &target.memory_map;
         let name = &target.cores[self.id].name;
 
+        let ResolvedCoreOptions::Xtensa { sequence, .. } = &self.core_state.core_access_options
+        else {
+            unreachable!(
+                "The stored core state is not compatible with the Xtensa architecture. \
+                This should never happen. Please file a bug if it does."
+            );
+        };
+        let debug_sequence = sequence.clone();
+
         let SpecificCoreState::Xtensa(s) = &mut self.specific_state else {
             unreachable!(
                 "The stored core state is not compatible with the Xtensa architecture. \
@@ -203,7 +215,7 @@ impl CombinedCoreState {
             self.id,
             name,
             memory_regions,
-            crate::architecture::xtensa::Xtensa::new(interface, s),
+            crate::architecture::xtensa::Xtensa::new(interface, s, debug_sequence),
         ))
     }
 
diff --git a/probe-rs/src/debug/debug_info.rs b/probe-rs/src/debug/debug_info.rs
index c112665c..cad79e8a 100644
--- a/probe-rs/src/debug/debug_info.rs
+++ b/probe-rs/src/debug/debug_info.rs
@@ -25,6 +25,8 @@ use std::{
 use typed_path::{TypedPath, TypedPathBuf};
 
 pub(crate) type GimliReader = gimli::EndianReader<gimli::LittleEndian, std::rc::Rc<[u8]>>;
+pub(crate) type GimliReaderOffset =
+    <gimli::EndianReader<gimli::LittleEndian, Rc<[u8]>> as gimli::Reader>::Offset;
 
 pub(crate) type GimliAttribute = gimli::Attribute<GimliReader>;
 
@@ -338,7 +340,7 @@ impl DebugInfo {
         &self,
         memory: &mut impl MemoryInterface,
         address: u64,
-        unwind_context: &mut UnwindContext<DwarfReader>,
+        unwind_context: &mut UnwindContext<GimliReaderOffset>,
         unwind_registers: &registers::DebugRegisters,
     ) -> Result<Vec<StackFrame>, DebugError> {
         // When reporting the address, we format it as a hex string, with the width matching
@@ -1000,10 +1002,10 @@ pub(crate) fn canonical_path_eq(
 
 /// Get a handle to the [`gimli::UnwindTableRow`] for this call frame, so that we can reference it to unwind register values.
 fn get_unwind_info<'a>(
-    unwind_context: &'a mut UnwindContext<DwarfReader>,
-    frame_section: &'a DebugFrame<DwarfReader>,
+    unwind_context: &'a mut UnwindContext<GimliReaderOffset>,
+    frame_section: &DebugFrame<DwarfReader>,
     frame_program_counter: u64,
-) -> Result<&'a gimli::UnwindTableRow<DwarfReader, gimli::StoreOnHeap>, DebugError> {
+) -> Result<&'a gimli::UnwindTableRow<GimliReaderOffset>, DebugError> {
     let transform_error = |error| {
         DebugError::Other(anyhow::anyhow!(
             "UNWIND: Error reading FrameDescriptorEntry at PC={} : {}",
@@ -1033,7 +1035,7 @@ fn get_unwind_info<'a>(
 }
 
 /// Determines the CFA (canonical frame address) for the current [`gimli::UnwindTableRow`], using the current register values.
-fn determine_cfa<R: gimli::Reader>(
+fn determine_cfa<R: gimli::ReaderOffset>(
     unwind_registers: &DebugRegisters,
     unwind_info: &UnwindTableRow<R>,
 ) -> Result<Option<u64>, crate::Error> {
@@ -1083,7 +1085,7 @@ fn unwind_register(
     debug_register: &mut super::DebugRegister,
     // The callee_frame_registers are used to lookup values and never updated.
     callee_frame_registers: &DebugRegisters,
-    unwind_info: Option<&gimli::UnwindTableRow<DwarfReader, gimli::StoreOnHeap>>,
+    unwind_info: Option<&gimli::UnwindTableRow<GimliReaderOffset>>,
     unwind_cfa: Option<u64>,
     unwound_return_address: &mut Option<RegisterValue>,
     memory: &mut dyn MemoryInterface,
diff --git a/probe-rs/src/probe.rs b/probe-rs/src/probe.rs
index 5fa7b158..4057a4cc 100644
--- a/probe-rs/src/probe.rs
+++ b/probe-rs/src/probe.rs
@@ -492,6 +492,11 @@ impl Probe {
     pub fn get_target_voltage(&mut self) -> Result<Option<f32>, DebugProbeError> {
         self.inner.get_target_voltage()
     }
+
+    /// Try to get a J-Link interface from the debug probe.
+    pub fn try_into_jlink(&mut self) -> Result<&mut jlink::JLink, DebugProbeError> {
+        self.inner.try_into_jlink()
+    }
 }
 
 /// An abstraction over a probe driver type.
@@ -668,6 +673,13 @@ pub trait DebugProbe: Send + fmt::Debug {
     fn get_target_voltage(&mut self) -> Result<Option<f32>, DebugProbeError> {
         Ok(None)
     }
+
+    /// Try to get a J-Link interface from the debug probe.
+    fn try_into_jlink(&mut self) -> Result<&mut jlink::JLink, DebugProbeError> {
+        Err(DebugProbeError::Other(anyhow::anyhow!(
+            "This probe does not support J-Link functionality."
+        )))
+    }
 }
 
 impl PartialEq for dyn ProbeFactory {
@@ -886,6 +898,9 @@ pub trait JTAGAccess: DebugProbe {
     /// will try to measure and extract `IR` lengths by driving the JTAG interface.
     fn scan_chain(&mut self) -> Result<Vec<JtagChainItem>, DebugProbeError>;
 
+    /// Executes a TAP reset.
+    fn tap_reset(&mut self) -> Result<(), DebugProbeError>;
+
     /// Read a JTAG register.
     ///
     /// This function emulates a read by performing a write with all zeros to the DR.
@@ -928,7 +943,7 @@ pub trait JTAGAccess: DebugProbe {
             match self
                 .write_register(write.address, &write.data, write.len)
                 .map_err(crate::Error::Probe)
-                .and_then(|response| (write.transform)(response))
+                .and_then(|response| (write.transform)(write, response))
             {
                 Ok(res) => results.push(idx, res),
                 Err(e) => return Err(BatchExecutionError::new(e, results)),
@@ -952,7 +967,7 @@ pub struct JtagWriteCommand {
     pub len: u32,
 
     /// A function to transform the raw response into a [`CommandResult`]
-    pub transform: fn(Vec<u8>) -> Result<CommandResult, crate::Error>,
+    pub transform: fn(&JtagWriteCommand, Vec<u8>) -> Result<CommandResult, crate::Error>,
 }
 
 /// Represents a Jtag Tap within the chain.
diff --git a/probe-rs/src/probe/arm_debug_interface.rs b/probe-rs/src/probe/arm_debug_interface.rs
index 9d089b0c..935386f3 100644
--- a/probe-rs/src/probe/arm_debug_interface.rs
+++ b/probe-rs/src/probe/arm_debug_interface.rs
@@ -1533,6 +1533,10 @@ mod test {
             todo!()
         }
 
+        fn tap_reset(&mut self) -> Result<(), DebugProbeError> {
+            todo!()
+        }
+
         fn read_register(&mut self, _address: u32, _len: u32) -> Result<Vec<u8>, DebugProbeError> {
             todo!()
         }
diff --git a/probe-rs/src/probe/common.rs b/probe-rs/src/probe/common.rs
index f7e437ec..ce1c2234 100644
--- a/probe-rs/src/probe/common.rs
+++ b/probe-rs/src/probe/common.rs
@@ -496,7 +496,11 @@ fn shift_ir(
 
     // Check the bit length, enough data has to be available
     if data.len() * 8 < len || len == 0 {
-        return Err(DebugProbeError::Other(anyhow!("Invalid data length")));
+        return Err(DebugProbeError::Other(anyhow!(
+            "Invalid data length. IR bits: {}, expected: {}",
+            data.len(),
+            len
+        )));
     }
 
     // BYPASS commands before and after shifting out data where required
@@ -546,7 +550,11 @@ fn shift_dr(
 
     // Check the bit length, enough data has to be available
     if data.len() * 8 < register_bits || register_bits == 0 {
-        return Err(DebugProbeError::Other(anyhow!("Invalid data length")));
+        return Err(DebugProbeError::Other(anyhow!(
+            "Invalid data length. DR bits: {}, expected: {}",
+            data.len(),
+            register_bits
+        )));
     }
 
     // Last bit of data is shifted out when we exit the SHIFT-DR State
@@ -696,6 +704,10 @@ impl<Probe: DebugProbe + RawJtagIo + 'static> JTAGAccess for Probe {
             .collect())
     }
 
+    fn tap_reset(&mut self) -> Result<(), DebugProbeError> {
+        self.reset_jtag_state_machine()
+    }
+
     fn set_idle_cycles(&mut self, idle_cycles: u8) {
         self.state_mut().jtag_idle_cycles = idle_cycles as usize;
     }
@@ -747,7 +759,7 @@ impl<Probe: DebugProbe + RawJtagIo + 'static> JTAGAccess for Probe {
             )
             .map_err(|e| BatchExecutionError::new(e.into(), DeferredResultSet::new()))?;
 
-            bits.push((idx, write.transform, op));
+            bits.push((idx, write, op));
         }
 
         tracing::debug!("Sending to chip...");
@@ -760,13 +772,13 @@ impl<Probe: DebugProbe + RawJtagIo + 'static> JTAGAccess for Probe {
         let mut responses = DeferredResultSet::with_capacity(bits.len());
 
         let mut bitstream = bitstream.as_bitslice();
-        for (idx, transform, bits) in bits.into_iter() {
+        for (idx, command, bits) in bits.into_iter() {
             if idx.should_capture() {
                 // TODO: this back-and-forth between BitVec and Vec is probably unnecessary
                 let mut reg_bits = bitstream[..bits].to_bitvec();
                 reg_bits.force_align();
                 let response = reg_bits.into_vec();
-                match transform(response) {
+                match (command.transform)(command, response) {
                     Ok(response) => responses.push(idx, response),
                     Err(e) => return Err(BatchExecutionError::new(e, responses)),
                 }
diff --git a/probe-rs/src/probe/jlink/error.rs b/probe-rs/src/probe/jlink/error.rs
index 22823a64..cb753b1e 100644
--- a/probe-rs/src/probe/jlink/error.rs
+++ b/probe-rs/src/probe/jlink/error.rs
@@ -22,7 +22,7 @@ pub enum JlinkError {
     /// advertised as optional *capability* bits. This error occurs when the capability bit for an
     /// operation isn't set when that operation is attempted.
     ///
-    /// Capabilities can be read by calling [`JayLink::capabilities`], which returns a
+    /// Capabilities can be read by calling [`JLink::capabilities`], which returns a
     /// [`Capabilities`] bitflags struct.
     MissingCapability(Capability),
 
diff --git a/probe-rs/src/probe/jlink/interface.rs b/probe-rs/src/probe/jlink/interface.rs
index 89804978..3d2b3462 100644
--- a/probe-rs/src/probe/jlink/interface.rs
+++ b/probe-rs/src/probe/jlink/interface.rs
@@ -19,10 +19,10 @@ enum_and_set!(
         Bdm3 = 2,
         /// FINE, a two-wire debugging interface used by Renesas RX MCUs.
         ///
-        /// **Note**: due to a bug, attempting to select FINE with [`JayLink::select_inferface`] will
+        /// **Note**: due to a bug, attempting to select FINE with [`JLink::select_inferface`] will
         /// currently hang the probe.
         ///
-        /// [`JayLink::select_inferface`]: crate::JayLink::select_interface
+        /// [`JLink::select_inferface`]: crate::JLink::select_interface
         // FIXME: There's a curious bug that hangs the probe when selecting the FINE interface.
         // Specifically, the probe never sends back the previous interface after it receives the `c7 03`
         // SELECT_IF cmd, even though the normal J-Link software also just sends `c7 03` and gets back
diff --git a/probe-rs/src/probe/jlink/mod.rs b/probe-rs/src/probe/jlink/mod.rs
index 8ad0b211..5334216c 100644
--- a/probe-rs/src/probe/jlink/mod.rs
+++ b/probe-rs/src/probe/jlink/mod.rs
@@ -362,7 +362,7 @@ pub struct JLink {
 
 impl fmt::Debug for JLink {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("JayLink").finish()
+        f.debug_struct("JLink").finish()
     }
 }
 
@@ -537,7 +537,7 @@ impl JLink {
 
     /// Selects the interface to use for talking to the target MCU.
     ///
-    /// Switching interfaces will reset the configured transfer speed, so [`JayLink::set_speed`]
+    /// Switching interfaces will reset the configured transfer speed, so [`JLink::set_speed`]
     /// needs to be called *after* `select_interface`.
     ///
     /// This requires the probe to support [`Capability::SelectIf`].
@@ -775,6 +775,15 @@ impl JLink {
 
         Ok(BitIter::new(&buf[..num_bytes], dir_bit_count).collect())
     }
+
+    /// Enable/Disable the Target Power Supply of the probe.
+    ///
+    /// This is not available on all probes.
+    /// This is avialable on some J-Links
+    pub fn set_kickstart_power(&mut self, enable: bool) -> Result<(), JlinkError> {
+        self.require_capability(Capability::SetKsPower)?;
+        self.write_cmd(&[Command::SetKsPower as u8, if enable { 1 } else { 0 }])
+    }
 }
 
 impl DebugProbe for JLink {
@@ -1011,6 +1020,10 @@ impl DebugProbe for JLink {
     fn has_xtensa_interface(&self) -> bool {
         self.supported_protocols.contains(&WireProtocol::Jtag)
     }
+
+    fn try_into_jlink(&mut self) -> Result<&mut JLink, DebugProbeError> {
+        Ok(self)
+    }
 }
 
 impl RawProtocolIo for JLink {
diff --git a/probe-rs/src/probe/jlink/speed.rs b/probe-rs/src/probe/jlink/speed.rs
index a76d48dd..e716c483 100644
--- a/probe-rs/src/probe/jlink/speed.rs
+++ b/probe-rs/src/probe/jlink/speed.rs
@@ -35,7 +35,7 @@ impl SpeedInfo {
 /// Target communication speed setting.
 ///
 /// This determines the clock frequency of the target communication. Supported speeds for the
-/// currently selected target interface can be fetched via [`JayLink::read_speeds`].
+/// currently selected target interface can be fetched via [`JLink::read_speeds`].
 #[derive(Debug, Copy, Clone)]
 pub struct SpeedConfig {
     raw: u16,
diff --git a/probe-rs/src/probe/wlink/mod.rs b/probe-rs/src/probe/wlink/mod.rs
index db9b2f23..cd3ed900 100644
--- a/probe-rs/src/probe/wlink/mod.rs
+++ b/probe-rs/src/probe/wlink/mod.rs
@@ -390,6 +390,10 @@ impl JTAGAccess for WchLink {
         Ok(vec![])
     }
 
+    fn tap_reset(&mut self) -> Result<(), DebugProbeError> {
+        Ok(())
+    }
+
     fn read_register(&mut self, address: u32, len: u32) -> Result<Vec<u8>, DebugProbeError> {
         tracing::debug!("read register 0x{:08x}", address);
         assert_eq!(len, 32);
diff --git a/probe-rs/src/session.rs b/probe-rs/src/session.rs
index 0b34a7c5..fc7e0f60 100644
--- a/probe-rs/src/session.rs
+++ b/probe-rs/src/session.rs
@@ -299,6 +299,15 @@ impl Session {
             configured_trace_sink: None,
         };
 
+        {
+            // Wait for the cores to be halted.
+            for core_id in 0..session.cores.len() {
+                let mut core = session.core(core_id)?;
+
+                core.halt(Duration::from_millis(100))?;
+            }
+        }
+
         session.halted_access(|sess| sequence_handle.on_connect(sess.get_riscv_interface()?))?;
 
         Ok(session)
@@ -335,6 +344,15 @@ impl Session {
             configured_trace_sink: None,
         };
 
+        {
+            // Wait for the cores to be halted.
+            for core_id in 0..session.cores.len() {
+                let mut core = session.core(core_id)?;
+
+                core.halt(Duration::from_millis(100))?;
+            }
+        }
+
         session.halted_access(|sess| sequence_handle.on_connect(sess.get_xtensa_interface()?))?;
 
         Ok(session)
diff --git a/probe-rs/targets/STM32U0_Series.yaml b/probe-rs/targets/STM32U0_Series.yaml
new file mode 100644
index 00000000..8281f2dc
--- /dev/null
+++ b/probe-rs/targets/STM32U0_Series.yaml
@@ -0,0 +1,1651 @@
+name: STM32U0 Series
+generated_from_pack: true
+pack_file_release: 1.0.0
+variants:
+- name: STM32U031C6Tx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20002000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8008000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20002000
+      end: 0x20003000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_32k
+- name: STM32U031C6Ux
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20002000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8008000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20002000
+      end: 0x20003000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_32k
+- name: STM32U031C8Tx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20002000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8010000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20002000
+      end: 0x20003000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_64k
+- name: STM32U031C8Ux
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20002000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8010000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20002000
+      end: 0x20003000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_64k
+- name: STM32U031F4Px
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20002000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8004000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20002000
+      end: 0x20003000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_16k
+- name: STM32U031F6Px
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20002000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8008000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20002000
+      end: 0x20003000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_32k
+- name: STM32U031F8Px
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20002000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8010000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20002000
+      end: 0x20003000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_64k
+- name: STM32U031G6YxT
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20002000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8008000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20002000
+      end: 0x20003000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_32k
+- name: STM32U031G8YxT
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20002000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8010000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20002000
+      end: 0x20003000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_64k
+- name: STM32U031K4Ux
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20002000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8004000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20002000
+      end: 0x20003000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_16k
+- name: STM32U031K6Ux
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20002000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8008000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20002000
+      end: 0x20003000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_32k
+- name: STM32U031K8Ux
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20002000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8010000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20002000
+      end: 0x20003000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_64k
+- name: STM32U031R6Ix
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20002000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8008000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20002000
+      end: 0x20003000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_32k
+- name: STM32U031R6Tx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20002000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8008000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20002000
+      end: 0x20003000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_32k
+- name: STM32U031R8Ix
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20002000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8010000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20002000
+      end: 0x20003000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_64k
+- name: STM32U031R8Tx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20002000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8010000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20002000
+      end: 0x20003000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_64k
+- name: STM32U073C8Tx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8010000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_64k
+- name: STM32U073C8Ux
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8010000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_64k
+- name: STM32U073CBTx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8020000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_128k
+- name: STM32U073CBUx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8020000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_128k
+- name: STM32U073CCTx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8040000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_256k
+- name: STM32U073CCUx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8040000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_256k
+- name: STM32U073H8YxT
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8010000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_64k
+- name: STM32U073HBYxT
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8020000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_128k
+- name: STM32U073HCYxT
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8040000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_256k
+- name: STM32U073K8Ux
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8010000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_64k
+- name: STM32U073KBUx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8020000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_128k
+- name: STM32U073KCUx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8040000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_256k
+- name: STM32U073M8Ix
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8010000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_64k
+- name: STM32U073M8Tx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8010000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_64k
+- name: STM32U073MBIx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8020000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_128k
+- name: STM32U073MBTx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8020000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_128k
+- name: STM32U073MCIx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8040000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_256k
+- name: STM32U073MCTx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8040000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_256k
+- name: STM32U073R8Ix
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8010000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_64k
+- name: STM32U073R8Tx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8010000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_64k
+- name: STM32U073RBIx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8020000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_128k
+- name: STM32U073RBTx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8020000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_128k
+- name: STM32U073RCIx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8040000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_256k
+- name: STM32U073RCTx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8040000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_256k
+- name: STM32U083CCTx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8040000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_256k
+- name: STM32U083CCUx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8040000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_256k
+- name: STM32U083HCYxT
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8040000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_256k
+- name: STM32U083KCUx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8040000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_256k
+- name: STM32U083MCIx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8040000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_256k
+- name: STM32U083MCTx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8040000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_256k
+- name: STM32U083RCIx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8040000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_256k
+- name: STM32U083RCTx
+  cores:
+  - name: main
+    type: armv6m
+    core_access_options: !Arm
+      ap: 0
+      psel: 0
+  memory_map:
+  - !Ram
+    name: SRAM1
+    range:
+      start: 0x20000000
+      end: 0x20008000
+    cores:
+    - main
+  - !Nvm
+    name: Flash
+    range:
+      start: 0x8000000
+      end: 0x8040000
+    is_boot_memory: true
+    cores:
+    - main
+  - !Generic
+    name: SRAM2
+    range:
+      start: 0x20008000
+      end: 0x2000A000
+    cores:
+    - main
+  flash_algorithms:
+  - stm32u0xx_256k
+flash_algorithms:
+- name: stm32u0xx_32k
+  description: STM32U0xx_32
+  default: true
+  instructions: ELUDRnK2jEiMTCBhIEYAagEkJAQgQAAoDdGJSIlMIGBAECBgBiBgYIdIoGDAEIdMYGB/ICBggUhAacAPwAcAKATQg0h9TKBggkigYAAgEL0BRnpIQGkBItIHEEN3SlBhACBwRwNGASBwR3K2AL9zSABpASEJBAhAACj40W9IQGkEIQhDbUlIYQhGQGkBIQkECENqSUhhAL9oSABpASEJBAhAACj40WVIAGljSQhAACgE0AhGYUkIYQEgcEdfSEBpBCGIQ11JSGEAIPbnAUZytllIWksYYRhGQGn/I9sAmENWS1hhASDABggaAgoYRkBpAiMTQxhDUUtYYRhGQGkBIxsEGENNS1hhAL9MSABpASMbBBhAACj40UhIAGlGSxhAACgE0BhGRUsYYQEgcEdDSEBpAiOYQ0FLWGEBIMAGAGhAHAAoBtEYRgBoASMbBBhDOksYYAAg6edwtYiwA0ZytsgdwQjJAAC/NEgAaQElLQQoQAAo+NE4SDBNKGEoRkBpASUoQy1NaGE/4AgpD9MQaBhgUGhYYAgzCDIIOQC/J0gAaQElLQQoQAAo+NEh4AAkBeAQeKUAbkZwUVIcZByMQvfTACQF4P8gZRitAG5GcFFkHAggQBqgQvXYAL8XSABpASUtBChAACj40QCYGGBYYAAhEkgAacAHwA8AKAXQDkgOTShhASAIsHC9ACm90QtIQGlACEAACU1oYQEgwAYAaEAcACgG0ChGAGgBJS0EqEMCTShgACDm5/rDAAAAIAJAqqoAAAAwAED/DwAAACwAQCMBZ0Wrie/N/wEAAAAAAAA=
+  load_address: 0x20000020
+  pc_init: 0x1
+  pc_uninit: 0x51
+  pc_program_page: 0x159
+  pc_erase_sector: 0xcd
+  pc_erase_all: 0x6b
+  data_section_offset: 0x25c
+  flash_properties:
+    address_range:
+      start: 0x8000000
+      end: 0x8008000
+    page_size: 0x400
+    erased_byte_value: 0xff
+    program_page_timeout: 400
+    erase_sector_timeout: 400
+    sectors:
+    - size: 0x800
+      address: 0x0
+- name: stm32u0xx_64k
+  description: STM32U0xx_64
+  default: true
+  instructions: gLWEsAOQApEBkgDwn/kVSRVICGAVSABowAMAKBLU/+cTSRRICGAUSAhgFEkGIAhgE0kUSAhgFEkUSAhgFEl/IAhg/+cTSABowA8AKAbQ/+cRSRJICGASSAhg/+cAIASwgL3ARhAgAkD6wwAAICACQAAwAECqqgAAVVUAAAQwAEAIMABA/w8AAAQsAED/AQAAACwAQBQgAkAIIAJAIwFnRauJ782BsACQBEkIaAEi0gcQQwhgACABsHBHwEYUIAJAg7ACkAGRaEYCcAEgA7BwR4C1grAA8Dr5/+cYSABowAMAKAHV/+f45xVJCGgEIhBDCGAIaAEiEgQQQwhg/+cPSABowAMAKAHV/+f45wtIAGgMSQhCBtD/5whJCkgIYAEgAZAH4AZJCGgEIpBDCGAAIAGQ/+cBmAKwgL3ARhAgAkAUIAJA+sMAAIC1hLACkADw/fgjSSNICGAjSQho/yLSAJBDCGACmB8i0gaAGAAKAZABmApoEEMCIhBDCGAIaAEiEgQQQwhg/+cVSABowAMAKAHV/+f45xJIAGgSSQhCBtD/5w9JD0gIYAEgA5AV4A5JCGgCIpBDCGABIMAGAGhAHAAoB9H/5wlJCGgBIhIEEEMIYP/nACADkP/nA5gEsIC9ECACQPrDAAAUIAJAACACQIC1jrAMkAuRCpIA8Kf4C5jAHQchiEMLkP/nS0gAaMADACgB1f/n+OdHSUhICGBISQhoASIQQwhg/+cLmAAoatD/5wuYCCga0//nCpgAaAyZCGAKmEBoDJlIYAyYCDAMkAqYCDAKkAuYCDgLkP/nNkgAaMADACgB1f/n+Oc+4AAgAZD/5wGYC5mIQg7S/+cKmAB4AZmKAAKpiFAKmEAcCpD/5wGYQBwBkOznACABkP/nAZgLmgghiRqIQgzS/+cBmAuZQBiCAAKp/yCIUP/nAZhAHAGQ7Of/5xtIAGjAAwAoAdX/5/jnApgMmQhggCECqEBYDJlIYAAgC5D/5xJIAGjABwAoBtD/5w9JE0gIYAEgDZAV4JHnDkoRaAEggUMRYMAGAGhAHAAoB9D/5wlJCGgBIhIEkEMIYP/nACANkP/nDZgOsIC9wEYQIAJA/wEAABQgAkAAIAJA+sMAAO/zEIDAB8APcrZwRwAAAAA=
+  load_address: 0x20000020
+  pc_init: 0x1
+  pc_uninit: 0xa5
+  pc_program_page: 0x1f1
+  pc_erase_sector: 0x149
+  pc_erase_all: 0xd1
+  data_section_offset: 0x358
+  flash_properties:
+    address_range:
+      start: 0x8000000
+      end: 0x8010000
+    page_size: 0x400
+    erased_byte_value: 0xff
+    program_page_timeout: 400
+    erase_sector_timeout: 400
+    sectors:
+    - size: 0x800
+      address: 0x0
+- name: stm32u0xx_16k
+  description: STM32U0xx_16
+  default: true
+  instructions: ELUDRnK2jEiMTCBhIEYAagEkJAQgQAAoDdGJSIlMIGBAECBgBiBgYIdIoGDAEIdMYGB/ICBggUhAacAPwAcAKATQg0h9TKBggkigYAAgEL0BRnpIQGkBItIHEEN3SlBhACBwRwNGASBwR3K2AL9zSABpASEJBAhAACj40W9IQGkEIQhDbUlIYQhGQGkBIQkECENqSUhhAL9oSABpASEJBAhAACj40WVIAGljSQhAACgE0AhGYUkIYQEgcEdfSEBpBCGIQ11JSGEAIPbnAUZytllIWksYYRhGQGn/I9sAmENWS1hhASDABggaAgoYRkBpAiMTQxhDUUtYYRhGQGkBIxsEGENNS1hhAL9MSABpASMbBBhAACj40UhIAGlGSxhAACgE0BhGRUsYYQEgcEdDSEBpAiOYQ0FLWGEBIMAGAGhAHAAoBtEYRgBoASMbBBhDOksYYAAg6edwtYiwA0ZytsgdwQjJAAC/NEgAaQElLQQoQAAo+NE4SDBNKGEoRkBpASUoQy1NaGE/4AgpD9MQaBhgUGhYYAgzCDIIOQC/J0gAaQElLQQoQAAo+NEh4AAkBeAQeKUAbkZwUVIcZByMQvfTACQF4P8gZRitAG5GcFFkHAggQBqgQvXYAL8XSABpASUtBChAACj40QCYGGBYYAAhEkgAacAHwA8AKAXQDkgOTShhASAIsHC9ACm90QtIQGlACEAACU1oYQEgwAYAaEAcACgG0ChGAGgBJS0EqEMCTShgACDm5/rDAAAAIAJAqqoAAAAwAED/DwAAACwAQCMBZ0Wrie/N/wEAAAAAAAA=
+  load_address: 0x20000020
+  pc_init: 0x1
+  pc_uninit: 0x51
+  pc_program_page: 0x159
+  pc_erase_sector: 0xcd
+  pc_erase_all: 0x6b
+  data_section_offset: 0x25c
+  flash_properties:
+    address_range:
+      start: 0x8000000
+      end: 0x8004000
+    page_size: 0x400
+    erased_byte_value: 0xff
+    program_page_timeout: 400
+    erase_sector_timeout: 400
+    sectors:
+    - size: 0x800
+      address: 0x0
+- name: stm32u0xx_128k
+  description: STM32U0xx_128
+  default: true
+  instructions: ELUDRnK2jEiMTCBhIEYAagEkJAQgQAAoDdGJSIlMIGBAECBgBiBgYIdIoGDAEIdMYGB/ICBggUhAacAPwAcAKATQg0h9TKBggkigYAAgEL0BRnpIQGkBItIHEEN3SlBhACBwRwNGASBwR3K2AL9zSABpASEJBAhAACj40W9IQGkEIQhDbUlIYQhGQGkBIQkECENqSUhhAL9oSABpASEJBAhAACj40WVIAGljSQhAACgE0AhGYUkIYQEgcEdfSEBpBCGIQ11JSGEAIPbnAUZytllIWksYYRhGQGn/I9sAmENWS1hhASDABggaAgoYRkBpAiMTQxhDUUtYYRhGQGkBIxsEGENNS1hhAL9MSABpASMbBBhAACj40UhIAGlGSxhAACgE0BhGRUsYYQEgcEdDSEBpAiOYQ0FLWGEBIMAGAGhAHAAoBtEYRgBoASMbBBhDOksYYAAg6edwtYiwA0ZytsgdwQjJAAC/NEgAaQElLQQoQAAo+NE4SDBNKGEoRkBpASUoQy1NaGE/4AgpD9MQaBhgUGhYYAgzCDIIOQC/J0gAaQElLQQoQAAo+NEh4AAkBeAQeKUAbkZwUVIcZByMQvfTACQF4P8gZRitAG5GcFFkHAggQBqgQvXYAL8XSABpASUtBChAACj40QCYGGBYYAAhEkgAacAHwA8AKAXQDkgOTShhASAIsHC9ACm90QtIQGlACEAACU1oYQEgwAYAaEAcACgG0ChGAGgBJS0EqEMCTShgACDm5/rDAAAAIAJAqqoAAAAwAED/DwAAACwAQCMBZ0Wrie/N/wEAAAAAAAA=
+  load_address: 0x20000020
+  pc_init: 0x1
+  pc_uninit: 0x51
+  pc_program_page: 0x159
+  pc_erase_sector: 0xcd
+  pc_erase_all: 0x6b
+  data_section_offset: 0x25c
+  flash_properties:
+    address_range:
+      start: 0x8000000
+      end: 0x8020000
+    page_size: 0x400
+    erased_byte_value: 0xff
+    program_page_timeout: 400
+    erase_sector_timeout: 400
+    sectors:
+    - size: 0x800
+      address: 0x0
+- name: stm32u0xx_256k
+  description: STM32U0xx_256
+  default: true
+  instructions: ELUDRnK2jEiMTCBhIEYAagEkJAQgQAAoDdGJSIlMIGBAECBgBiBgYIdIoGDAEIdMYGB/ICBggUhAacAPwAcAKATQg0h9TKBggkigYAAgEL0BRnpIQGkBItIHEEN3SlBhACBwRwNGASBwR3K2AL9zSABpASEJBAhAACj40W9IQGkEIQhDbUlIYQhGQGkBIQkECENqSUhhAL9oSABpASEJBAhAACj40WVIAGljSQhAACgE0AhGYUkIYQEgcEdfSEBpBCGIQ11JSGEAIPbnAUZytllIWksYYRhGQGn/I9sAmENWS1hhASDABggaAgoYRkBpAiMTQxhDUUtYYRhGQGkBIxsEGENNS1hhAL9MSABpASMbBBhAACj40UhIAGlGSxhAACgE0BhGRUsYYQEgcEdDSEBpAiOYQ0FLWGEBIMAGAGhAHAAoBtEYRgBoASMbBBhDOksYYAAg6edwtYiwA0ZytsgdwQjJAAC/NEgAaQElLQQoQAAo+NE4SDBNKGEoRkBpASUoQy1NaGE/4AgpD9MQaBhgUGhYYAgzCDIIOQC/J0gAaQElLQQoQAAo+NEh4AAkBeAQeKUAbkZwUVIcZByMQvfTACQF4P8gZRitAG5GcFFkHAggQBqgQvXYAL8XSABpASUtBChAACj40QCYGGBYYAAhEkgAacAHwA8AKAXQDkgOTShhASAIsHC9ACm90QtIQGlACEAACU1oYQEgwAYAaEAcACgG0ChGAGgBJS0EqEMCTShgACDm5/rDAAAAIAJAqqoAAAAwAED/DwAAACwAQCMBZ0Wrie/N/wEAAAAAAAA=
+  load_address: 0x20000020
+  pc_init: 0x1
+  pc_uninit: 0x51
+  pc_program_page: 0x159
+  pc_erase_sector: 0xcd
+  pc_erase_all: 0x6b
+  data_section_offset: 0x25c
+  flash_properties:
+    address_range:
+      start: 0x8000000
+      end: 0x8040000
+    page_size: 0x400
+    erased_byte_value: 0xff
+    program_page_timeout: 400
+    erase_sector_timeout: 400
+    sectors:
+    - size: 0x800
+      address: 0x0
diff --git a/probe-rs/targets/STM32WB_Series.yaml b/probe-rs/targets/STM32WB_Series.yaml
index e0d5ba29..c276a194 100644
--- a/probe-rs/targets/STM32WB_Series.yaml
+++ b/probe-rs/targets/STM32WB_Series.yaml
@@ -1,484 +1,810 @@
 name: STM32WB Series
-manufacturer:
-  id: 0x20
-  cc: 0x0
+generated_from_pack: true
+pack_file_release: 1.4.0
 variants:
-  - name: STM32WB30CEUx
+  - name: STM32WB10CCUx
     cores:
       - name: main
         type: armv7em
-        core_access_options:
-          !Arm
-            ap: 0x0
-            psel: 0x0
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
     memory_map:
       - !Ram
-          range:
-            start: 0x20000000
-            end: 0x20008000
-          is_boot_memory: false
-          cores:
-            - main
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20003000
+        cores:
+          - main
+      - !Ram
+        name: SRAM2
+        range:
+          start: 0x20030000
+          end: 0x20039000
+        cores:
+          - main
+      - !Nvm
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8050000
+        is_boot_memory: true
+        cores:
+          - main
+    flash_algorithms:
+      - stm32wb1x_320_m4
+  - name: STM32WB15CCUx
+    cores:
+      - name: main
+        type: armv7em
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
+    memory_map:
+      - !Ram
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20003000
+        cores:
+          - main
+      - !Ram
+        name: SRAM2
+        range:
+          start: 0x20030000
+          end: 0x20039000
+        cores:
+          - main
       - !Nvm
-          range:
-            start: 0x8000000
-            end: 0x8080000
-          is_boot_memory: true
-          cores:
-            - main
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8050000
+        is_boot_memory: true
+        cores:
+          - main
+    flash_algorithms:
+      - stm32wb1x_320_m4
+  - name: STM32WB15CCUxE
+    cores:
+      - name: main
+        type: armv7em
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
+    memory_map:
+      - !Ram
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20003000
+        cores:
+          - main
+      - !Ram
+        name: SRAM2
+        range:
+          start: 0x20030000
+          end: 0x20039000
+        cores:
+          - main
+      - !Nvm
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8050000
+        is_boot_memory: true
+        cores:
+          - main
+    flash_algorithms:
+      - stm32wb1x_320_m4
+  - name: STM32WB15CCYx
+    cores:
+      - name: main
+        type: armv7em
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
+    memory_map:
+      - !Ram
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20003000
+        cores:
+          - main
+      - !Ram
+        name: SRAM2
+        range:
+          start: 0x20030000
+          end: 0x20039000
+        cores:
+          - main
+      - !Nvm
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8050000
+        is_boot_memory: true
+        cores:
+          - main
+    flash_algorithms:
+      - stm32wb1x_320_m4
+  - name: STM32WB1MMCHx
+    cores:
+      - name: main
+        type: armv7em
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
+    memory_map:
+      - !Ram
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20003000
+        cores:
+          - main
+      - !Ram
+        name: SRAM2
+        range:
+          start: 0x20030000
+          end: 0x20039000
+        cores:
+          - main
+      - !Nvm
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8050000
+        is_boot_memory: true
+        cores:
+          - main
+    flash_algorithms:
+      - stm32wb1x_320_m4
+  - name: STM32WB30CEUxA
+    cores:
+      - name: main
+        type: armv7em
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
+    memory_map:
+      - !Ram
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20008000
+        cores:
+          - main
+      - !Nvm
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8080000
+        is_boot_memory: true
+        cores:
+          - main
     flash_algorithms:
       - stm32wb3x_512_m4
-  - name: STM32WB35CCUx
+  - name: STM32WB35CCUxA
     cores:
       - name: main
         type: armv7em
-        core_access_options:
-          !Arm
-            ap: 0x0
-            psel: 0x0
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
     memory_map:
       - !Ram
-          range:
-            start: 0x20000000
-            end: 0x20008000
-          is_boot_memory: false
-          cores:
-            - main
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20008000
+        cores:
+          - main
       - !Nvm
-          range:
-            start: 0x8000000
-            end: 0x8040000
-          is_boot_memory: true
-          cores:
-            - main
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8040000
+        is_boot_memory: true
+        cores:
+          - main
     flash_algorithms:
       - stm32wb3x_256_m4
-  - name: STM32WB35CEUx
+  - name: STM32WB35CEUxA
     cores:
       - name: main
         type: armv7em
-        core_access_options:
-          !Arm
-            ap: 0x0
-            psel: 0x0
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
     memory_map:
       - !Ram
-          range:
-            start: 0x20000000
-            end: 0x20008000
-          is_boot_memory: false
-          cores:
-            - main
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20008000
+        cores:
+          - main
       - !Nvm
-          range:
-            start: 0x8000000
-            end: 0x8080000
-          is_boot_memory: true
-          cores:
-            - main
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8080000
+        is_boot_memory: true
+        cores:
+          - main
     flash_algorithms:
       - stm32wb3x_512_m4
   - name: STM32WB50CGUx
     cores:
       - name: main
         type: armv7em
-        core_access_options:
-          !Arm
-            ap: 0x0
-            psel: 0x0
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
     memory_map:
       - !Ram
-          range:
-            start: 0x20000000
-            end: 0x20020000
-          is_boot_memory: false
-          cores:
-            - main
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20010000
+        cores:
+          - main
       - !Nvm
-          range:
-            start: 0x8000000
-            end: 0x8100000
-          is_boot_memory: true
-          cores:
-            - main
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8100000
+        is_boot_memory: true
+        cores:
+          - main
     flash_algorithms:
-      - stm32wb_m4
+      - stm32wb5x_m4_1024
   - name: STM32WB55CCUx
-    part: 0x495
     cores:
       - name: main
         type: armv7em
-        core_access_options:
-          !Arm
-            ap: 0x0
-            psel: 0x0
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
     memory_map:
       - !Ram
-          range:
-            start: 0x20000000
-            end: 0x20030000
-          is_boot_memory: false
-          cores:
-            - main
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20010000
+        cores:
+          - main
       - !Nvm
-          range:
-            start: 0x8000000
-            end: 0x8040000
-          is_boot_memory: true
-          cores:
-            - main
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8040000
+        is_boot_memory: true
+        cores:
+          - main
     flash_algorithms:
-      - stm32wb_m4
+      - stm32wb5x_m4_256
+      - stm32wb55x_35x_m4_opt
   - name: STM32WB55CEUx
-    part: 0x495
     cores:
       - name: main
         type: armv7em
-        core_access_options:
-          !Arm
-            ap: 0x0
-            psel: 0x0
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
     memory_map:
       - !Ram
-          range:
-            start: 0x20000000
-            end: 0x20040000
-          is_boot_memory: false
-          cores:
-            - main
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20030000
+        cores:
+          - main
       - !Nvm
-          range:
-            start: 0x8000000
-            end: 0x8080000
-          is_boot_memory: true
-          cores:
-            - main
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8080000
+        is_boot_memory: true
+        cores:
+          - main
     flash_algorithms:
-      - stm32wb_m4
+      - stm32wb5x_m4_512
+      - stm32wb55x_35x_m4_opt
   - name: STM32WB55CGUx
-    part: 0x495
     cores:
       - name: main
         type: armv7em
-        core_access_options:
-          !Arm
-            ap: 0x0
-            psel: 0x0
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
     memory_map:
       - !Ram
-          range:
-            start: 0x20000000
-            end: 0x20040000
-          is_boot_memory: false
-          cores:
-            - main
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20030000
+        cores:
+          - main
       - !Nvm
-          range:
-            start: 0x8000000
-            end: 0x8100000
-          is_boot_memory: true
-          cores:
-            - main
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8100000
+        is_boot_memory: true
+        cores:
+          - main
     flash_algorithms:
-      - stm32wb_m4
+      - stm32wb5x_m4_1024
+      - stm32wb55x_35x_m4_opt
   - name: STM32WB55RCVx
-    part: 0x495
     cores:
       - name: main
         type: armv7em
-        core_access_options:
-          !Arm
-            ap: 0x0
-            psel: 0x0
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
     memory_map:
       - !Ram
-          range:
-            start: 0x20000000
-            end: 0x20020000
-          is_boot_memory: false
-          cores:
-            - main
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20010000
+        cores:
+          - main
       - !Nvm
-          range:
-            start: 0x8000000
-            end: 0x8040000
-          is_boot_memory: true
-          cores:
-            - main
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8040000
+        is_boot_memory: true
+        cores:
+          - main
     flash_algorithms:
-      - stm32wb_m4
+      - stm32wb5x_m4_256
+      - stm32wb55x_35x_m4_opt
   - name: STM32WB55REVx
-    part: 0x495
     cores:
       - name: main
         type: armv7em
-        core_access_options:
-          !Arm
-            ap: 0x0
-            psel: 0x0
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
     memory_map:
       - !Ram
-          range:
-            start: 0x20000000
-            end: 0x20040000
-          is_boot_memory: false
-          cores:
-            - main
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20030000
+        cores:
+          - main
       - !Nvm
-          range:
-            start: 0x8000000
-            end: 0x8080000
-          is_boot_memory: true
-          cores:
-            - main
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8080000
+        is_boot_memory: true
+        cores:
+          - main
     flash_algorithms:
-      - stm32wb_m4
+      - stm32wb5x_m4_512
+      - stm32wb55x_35x_m4_opt
   - name: STM32WB55RGVx
-    part: 0x495
     cores:
       - name: main
         type: armv7em
-        core_access_options:
-          !Arm
-            ap: 0x0
-            psel: 0x0
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
     memory_map:
       - !Ram
-          range:
-            start: 0x20000000
-            end: 0x20040000
-          is_boot_memory: false
-          cores:
-            - main
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20030000
+        cores:
+          - main
       - !Nvm
-          range:
-            start: 0x8000000
-            end: 0x8100000
-          is_boot_memory: true
-          cores:
-            - main
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8100000
+        is_boot_memory: true
+        cores:
+          - main
     flash_algorithms:
-      - stm32wb_m4
+      - stm32wb5x_m4_1024
+      - stm32wb55x_35x_m4_opt
   - name: STM32WB55VCQx
     cores:
       - name: main
         type: armv7em
-        core_access_options:
-          !Arm
-            ap: 0x0
-            psel: 0x0
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
     memory_map:
       - !Ram
-          range:
-            start: 0x20000000
-            end: 0x20020000
-          is_boot_memory: false
-          cores:
-            - main
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20010000
+        cores:
+          - main
       - !Nvm
-          range:
-            start: 0x8000000
-            end: 0x8040000
-          is_boot_memory: true
-          cores:
-            - main
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8040000
+        is_boot_memory: true
+        cores:
+          - main
     flash_algorithms:
-      - stm32wb_m4
+      - stm32wb5x_m4_256
+      - stm32wb55x_35x_m4_opt
   - name: STM32WB55VCYx
-    part: 0x495
     cores:
       - name: main
         type: armv7em
-        core_access_options:
-          !Arm
-            ap: 0x0
-            psel: 0x0
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
     memory_map:
       - !Ram
-          range:
-            start: 0x20000000
-            end: 0x20020000
-          is_boot_memory: false
-          cores:
-            - main
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20010000
+        cores:
+          - main
       - !Nvm
-          range:
-            start: 0x8000000
-            end: 0x8040000
-          is_boot_memory: true
-          cores:
-            - main
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8040000
+        is_boot_memory: true
+        cores:
+          - main
     flash_algorithms:
-      - stm32wb_m4
+      - stm32wb5x_m4_256
+      - stm32wb55x_35x_m4_opt
   - name: STM32WB55VEQx
     cores:
       - name: main
         type: armv7em
-        core_access_options:
-          !Arm
-            ap: 0x0
-            psel: 0x0
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
     memory_map:
       - !Ram
-          range:
-            start: 0x20000000
-            end: 0x20040000
-          is_boot_memory: false
-          cores:
-            - main
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20030000
+        cores:
+          - main
       - !Nvm
-          range:
-            start: 0x8000000
-            end: 0x8080000
-          is_boot_memory: true
-          cores:
-            - main
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8080000
+        is_boot_memory: true
+        cores:
+          - main
     flash_algorithms:
-      - stm32wb_m4
+      - stm32wb5x_m4_512
+      - stm32wb55x_35x_m4_opt
   - name: STM32WB55VEYx
-    part: 0x495
     cores:
       - name: main
         type: armv7em
-        core_access_options:
-          !Arm
-            ap: 0x0
-            psel: 0x0
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
     memory_map:
       - !Ram
-          range:
-            start: 0x20000000
-            end: 0x20040000
-          is_boot_memory: false
-          cores:
-            - main
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20030000
+        cores:
+          - main
       - !Nvm
-          range:
-            start: 0x8000000
-            end: 0x8080000
-          is_boot_memory: true
-          cores:
-            - main
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8080000
+        is_boot_memory: true
+        cores:
+          - main
     flash_algorithms:
-      - stm32wb_m4
+      - stm32wb5x_m4_512
+      - stm32wb55x_35x_m4_opt
   - name: STM32WB55VGQx
     cores:
       - name: main
         type: armv7em
-        core_access_options:
-          !Arm
-            ap: 0x0
-            psel: 0x0
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
     memory_map:
       - !Ram
-          range:
-            start: 0x20000000
-            end: 0x20040000
-          is_boot_memory: false
-          cores:
-            - main
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20030000
+        cores:
+          - main
       - !Nvm
-          range:
-            start: 0x8000000
-            end: 0x8100000
-          is_boot_memory: true
-          cores:
-            - main
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8100000
+        is_boot_memory: true
+        cores:
+          - main
     flash_algorithms:
-      - stm32wb_m4
+      - stm32wb5x_m4_1024
+      - stm32wb55x_35x_m4_opt
   - name: STM32WB55VGYx
-    part: 0x495
     cores:
       - name: main
         type: armv7em
-        core_access_options:
-          !Arm
-            ap: 0x0
-            psel: 0x0
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
+    memory_map:
+      - !Ram
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20030000
+        cores:
+          - main
+      - !Nvm
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8100000
+        is_boot_memory: true
+        cores:
+          - main
+    flash_algorithms:
+      - stm32wb5x_m4_1024
+      - stm32wb55x_35x_m4_opt
+  - name: STM32WB55VYYx
+    cores:
+      - name: main
+        type: armv7em
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
+    memory_map:
+      - !Ram
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20030000
+        cores:
+          - main
+      - !Nvm
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x80a0000
+        is_boot_memory: true
+        cores:
+          - main
+    flash_algorithms:
+      - stm32wb5x_m4_640
+      - stm32wb55x_35x_m4_opt
+  - name: STM32WB5MMGHx
+    cores:
+      - name: main
+        type: armv7em
+        core_access_options: !Arm
+          ap: 0
+          psel: 0
     memory_map:
       - !Ram
-          range:
-            start: 0x20000000
-            end: 0x20040000
-          is_boot_memory: false
-          cores:
-            - main
+        name: SRAM1
+        range:
+          start: 0x20000000
+          end: 0x20030000
+        cores:
+          - main
       - !Nvm
-          range:
-            start: 0x8000000
-            end: 0x8100000
-          is_boot_memory: true
-          cores:
-            - main
+        name: Main_Flash
+        range:
+          start: 0x8000000
+          end: 0x8100000
+        is_boot_memory: true
+        cores:
+          - main
     flash_algorithms:
-      - stm32wb_m4
+      - stm32wb5x_m4_1024
 flash_algorithms:
+  - name: stm32wb1x_320_m4
+    description: STM32WB1x_M4 320 Flash
+    default: true
+    instructions: QLpwR8C6cEdP6jAAcEcAAHK2kUhBaQApA9qQSYFgkEmBYABqwAMQ1I5ISvaqIQFgSRABYAYhQWBA9v9xgWDIEIlJCGB/IAkfCGBitgAgcEeBSEFpQfAAQUFhACBwRxC1crZ9SUTy+jIKYUH2+HQE6hAjSGmgQ0hhCGnAA/zUCGkAA/zUCGlAA/zUSGlD8AIDGENIYUhpQPSAMEhhAL8AvwhpwAP81AhpQAP81AhpAAP81EhpIPACAEhhCGkQQgLQCmEBIBC9T/AAYABoQBwD0QhoQPSAMAhgYrYAIBC9MLVytl1IAWpfSssFSvaqIRDVkPiAAF1JT/AAZAHrwCUE4CBG//es/wT1AGSsQvjZIeARYANp2wP71ANpRPL6NCNDA2FDaUPwBANDYUNpQ/SAM0NhAOARYANp2wP71EFpIfAEAUFhAWkhQgTQAWkhQwFhASAwvWK2ACAwvS3p8E2IsHK2SvaqKt/4/LA7TgHgy/gAoDNp2wP61ETy+jc3YU/wAQ7G+BTg7EZU4Mb4FOAIKRPTE2gDYFNoQ2AAvwC/VEZbRgDgHGA1ae0D+9QzaTtCO9EIMAg5CDI84AAjBOAS+AFLTPgjQFsci0L40wAj/yTB8QgFBOAD6wEIWxxM+ChAnUL42N3pABMB6wMhApsDnBsEA+sEYxlEAJHd6QQTAesDIQabB5wbBAPrBGMZRAGRAJkBYAGZQWAAvwC/ACEzadsD/NQzaTtCBNA3YQEgCLC96PCNACmo0XBpIPABAHBhT/AAYABoQBwD0DBoIPSAMDBgYrYAIOrnAEAAWCMBZ0Wrie/NADAAQAQsAEAA+P8HAAAAAA==
+    load_address: 0x20000020
+    pc_init: 0x11
+    pc_uninit: 0x51
+    pc_program_page: 0x15b
+    pc_erase_sector: 0x5f
+    pc_erase_all: 0xdf
+    data_section_offset: 0x270
+    flash_properties:
+      address_range:
+        start: 0x8000000
+        end: 0x8050000
+      page_size: 0x400
+      erased_byte_value: 0xff
+      program_page_timeout: 400
+      erase_sector_timeout: 400
+      sectors:
+        - size: 0x800
+          address: 0x0
+
+  - name: stm32wb3x_512_m4
+    description: STM32WB3_M4 512 Flash
+    default: true
+    instructions: QLpwR8C6cEeQSUAKCEBwR7/zT49wR3K2jUhBaQApA9qMSYFgjEmBYABqwAMN1IxIikkBYEkQAWAGIUFgiUmBYIlIyRBBYH8hAWBitgAgcEd/SEFpQgQRQ0FhACBwR3C1crb/99H/ekkKadID/NQKaVID/NQKaRID/NQLaXtKE0MLYUtpcUzkQyNAS2FMaQIjGEMEQ0xhSGncAyBDSGFvSG9NAOAoYA5p9gP71EhpmENIYQhpEEIE0AhpEEMIYQEgcL0BIMAGAGhAHALRCGggQwhgYrYAIHC9cLVytlxIAWpfSssFXUkR1VlIYUmAMAB4ASQAA0UY5AaWFAPgIEb/967/pBmsQvnZH+ARYANp2wP71ARpVUscQwRhRWkEJCVDRWFFaaYDNUNFYQDgEWAFae0D+9RBaaFDQWEBaRlCBNABaRlDAWEBIHC9YrYAIHC98LWIsHK2PksC4EFNP0wsYBxp5AP51EFMHGEBJFxhWuA3TAEjY2EIKRXTE2gDYFNoQ2C/80+PNUw1TTFLAOAsYB5p9gP71BtpNEwjQj3RCDAIOQgyP+AAI25GBOAUeJ0AUhx0UVsci0L40wAj/yQIJW0aA+BfGL8A9FFbHJ1C+dgBmwCZGwLLGAKZA5wJBCQGCRlZGACRBZsEmRsCyxgGmQecCQQkBgkZWRgBkQCZAWABmUFgv/NPjxFLACEcaeQD/NQcaRVLHEIF0A1JE0gIYQEgCLDwvQApotEJSEFpSQhJAEFhQQMJaEkcBNABaAEiEgSRQwFgYrYAIOrn+B8AAABAAFgjAWdFq4nvzaqqAAAAMABA/w8AAAAsAED6QwAAAPD/BwAAAAA=
+    load_address: 0x20000020
+    pc_init: 0x17
+    pc_uninit: 0x51
+    pc_program_page: 0x151
+    pc_erase_sector: 0x5f
+    pc_erase_all: 0xd9
+    data_section_offset: 0x274
+    flash_properties:
+      address_range:
+        start: 0x8000000
+        end: 0x8080000
+      page_size: 0x400
+      erased_byte_value: 0xff
+      program_page_timeout: 400
+      erase_sector_timeout: 400
+      sectors:
+        - size: 0x1000
+          address: 0x0
+
   - name: stm32wb3x_256_m4
     description: STM32WB3_M4 256 Flash
-    cores:
-      - main
     default: true
-    instructions: YUhBaQApA9pgSYFgYEmBYAAgcEdcSEFpQgQRQ0FhACBwRxC1WEhbSVtKAOARYANp2wP71FlKAmEBackD/NQBaQkD/NQBaUkD/NQBaVRLGUMBYUFpBCMZQ0FhQWmcAyFDQWEBackD/NQBaUkD/NQBaQkD/NRBaZlDQWEAIUFhAWkRQgLQAmEBIBC9ACAQvRC1PUlCSgphS2lCTCNAS2FACuNDGEALadsD/NQLaVsD/NQLaRsD/NRMaQIjGEMEQ0xhSGncAyBDSGEAvwC/CGnAA/zUCGlAA/zUCGkAA/zUSGmYQ0hhACBIYQhpEEIC0AphASAQvQEgwAYAaEAcAtEIaCBDCGAAIBC9cLXJHR5LyQgjTckAHWFcaQEmNENcYRpOQDYe4B1hHGnkA/zUHGlkA/zUHGkkA/zUFGgEYFRoRGAcaeQD/NQcaWQD/NQcaSQD/NQ0aggwCDkIMuQHAdABIHC9ACne0VhpQAhAAFhhASDABgBoQBwE0BhoASEJBIhDGGAAIHC9AAAAQABYIwFnRauJ782qqgAAADAAQPpDAAD/AQAAB+D//wAAAAA=
-    pc_init: 0x1
-    pc_uninit: 0x15
-    pc_program_page: 0x109
-    pc_erase_sector: 0x8f
-    pc_erase_all: 0x23
-    data_section_offset: 0x1a8
+    instructions: QLpwR8C6cEeQSUAKCEBwR7/zT49wR3K2jUhBaQApA9qMSYFgjEmBYABqwAMN1IxIikkBYEkQAWAGIUFgiUmBYIlIyRBBYH8hAWBitgAgcEd/SEFpQgQRQ0FhACBwR3C1crb/99H/ekkKadID/NQKaVID/NQKaRID/NQLaXtKE0MLYUtpcUzkQyNAS2FMaQIjGEMEQ0xhSGncAyBDSGFvSG9NAOAoYA5p9gP71EhpmENIYQhpEEIE0AhpEEMIYQEgcL0BIMAGAGhAHALRCGggQwhgYrYAIHC9cLVytlxIAWpfSssFXUkR1VlIYUmAMAB4ASQAA0UY5AaWFAPgIEb/967/pBmsQvnZH+ARYANp2wP71ARpVUscQwRhRWkEJCVDRWFFaaYDNUNFYQDgEWAFae0D+9RBaaFDQWEBaRlCBNABaRlDAWEBIHC9YrYAIHC98LWIsHK2PksC4EFNP0wsYBxp5AP51EFMHGEBJFxhWuA3TAEjY2EIKRXTE2gDYFNoQ2C/80+PNUw1TTFLAOAsYB5p9gP71BtpNEwjQj3RCDAIOQgyP+AAI25GBOAUeJ0AUhx0UVsci0L40wAj/yQIJW0aA+BfGL8A9FFbHJ1C+dgBmwCZGwLLGAKZA5wJBCQGCRlZGACRBZsEmRsCyxgGmQecCQQkBgkZWRgBkQCZAWABmUFgv/NPjxFLACEcaeQD/NQcaRVLHEIF0A1JE0gIYQEgCLDwvQApotEJSEFpSQhJAEFhQQMJaEkcBNABaAEiEgSRQwFgYrYAIOrn+B8AAABAAFgjAWdFq4nvzaqqAAAAMABA/w8AAAAsAED6QwAAAPD/BwAAAAA=
+    load_address: 0x20000020
+    pc_init: 0x17
+    pc_uninit: 0x51
+    pc_program_page: 0x151
+    pc_erase_sector: 0x5f
+    pc_erase_all: 0xd9
+    data_section_offset: 0x274
     flash_properties:
       address_range:
         start: 0x8000000
         end: 0x8040000
       page_size: 0x400
       erased_byte_value: 0xff
-      program_page_timeout: 0x190
-      erase_sector_timeout: 0x190
+      program_page_timeout: 400
+      erase_sector_timeout: 400
       sectors:
         - size: 0x1000
           address: 0x0
-  - name: stm32wb3x_512_m4
-    description: STM32WB3_M4 512 Flash
-    cores:
-      - main
+
+  - name: stm32wb5x_m4_1024
+    description: STM32WB5x_M4_1024 Flash
     default: true
-    instructions: YUhBaQApA9pgSYFgYEmBYAAgcEdcSEFpQgQRQ0FhACBwRxC1WEhbSVtKAOARYANp2wP71FlKAmEBackD/NQBaQkD/NQBaUkD/NQBaVRLGUMBYUFpBCMZQ0FhQWmcAyFDQWEBackD/NQBaUkD/NQBaQkD/NRBaZlDQWEAIUFhAWkRQgLQAmEBIBC9ACAQvRC1PUlCSgphS2lCTCNAS2FACuNDGEALadsD/NQLaVsD/NQLaRsD/NRMaQIjGEMEQ0xhSGncAyBDSGEAvwC/CGnAA/zUCGlAA/zUCGkAA/zUSGmYQ0hhACBIYQhpEEIC0AphASAQvQEgwAYAaEAcAtEIaCBDCGAAIBC9cLXJHR5LyQgjTckAHWFcaQEmNENcYRpOQDYe4B1hHGnkA/zUHGlkA/zUHGkkA/zUFGgEYFRoRGAcaeQD/NQcaWQD/NQcaSQD/NQ0aggwCDkIMuQHAdABIHC9ACne0VhpQAhAAFhhASDABgBoQBwE0BhoASEJBIhDGGAAIHC9AAAAQABYIwFnRauJ782qqgAAADAAQPpDAAD/AQAAB+D//wAAAAA=
+    instructions: QLpwR8C6cEdP6jAAcEcAAMDzTCBwR7/zT49wR3K2kkhBaQApA9qRSYFgkUmBYABqwAMQ1I9ISvaqIQFgSRABYAYhQWBA9v9xgWDIEIpJCGB/IAkfCGBitgAgcEeCSEFpQfAAQUFhACBwRxC1crbA80wifUgBackD/NQBaUkD/NQBaQkD/NQBaUTy+jQhQwFhQWlB9vhzmUNBYUFpQvACAhFDQWFBaUH0gDFBYUr2qiFwSgDgEWADadsD+9RBaSHwAgFBYQFpIUIE0AFpIUMBYQEgEL1P8ABhCWhJHAPRAWhB9IAxAWBitgAgEL0wtXK2XUgBal9KywVK9qohENWQ+IAAXklP8ABkAesANQTgIEb/96v/BPWAVKxC+Nkh4BFgA2nbA/vUA2lE8vo0I0MDYUNpQ/AEA0NhQ2lD9IAzQ2EA4BFgA2nbA/vUQWkh8AQBQWEBaSFCBNABaSFDAWEBIDC9YrYAIDC9LenwTYiwcrZK9qoq3/j8sDtOAeDL+ACgM2nbA/rURPL6NzdhT/ABDsb4FODsRlTgxvgU4AgpE9MTaANgU2hDYL/zT49URltGAOAcYDVp7QP71DNpO0I70QgwCDkIMjzgACME4BL4AUtM+CNAWxyLQvjTACP/JMHxCAUE4APrAQhbHEz4KECdQvjY3ekAEwHrAyECmwOcGwQD6wRjGUQAkd3pBBMB6wMhBpsHnBsEA+sEYxlEAZEAmQFgAZlBYL/zT48AITNp2wP81DNpO0IE0DdhASAIsL3o8I0AKajRcGkg8AEAcGFP8ABgAGhAHAPQMGgg9IAwMGBitgAg6ucAAABAAFgjAWdFq4nvzQAwAEAELABAAPD/BwAAAAA=
+    load_address: 0x20000020
+    pc_init: 0x1d
+    pc_uninit: 0x5d
+    pc_program_page: 0x169
+    pc_erase_sector: 0x6b
+    pc_erase_all: 0xed
+    data_section_offset: 0x280
+    flash_properties:
+      address_range:
+        start: 0x8000000
+        end: 0x8100000
+      page_size: 0x400
+      erased_byte_value: 0xff
+      program_page_timeout: 400
+      erase_sector_timeout: 400
+      sectors:
+        - size: 0x1000
+          address: 0x0
+
+  - name: stm32wb5x_m4_256
+    description: STM32WB5x_M4_256 Flash
+    default: true
+    instructions: QLpwR8C6cEdP6jAAcEcAAMDzTCBwR7/zT49wR3K2kkhBaQApA9qRSYFgkUmBYABqwAMQ1I9ISvaqIQFgSRABYAYhQWBA9v9xgWDIEIpJCGB/IAkfCGBitgAgcEeCSEFpQfAAQUFhACBwRxC1crbA80wifUgBackD/NQBaUkD/NQBaQkD/NQBaUTy+jQhQwFhQWlB9vhzmUNBYUFpQvACAhFDQWFBaUH0gDFBYUr2qiFwSgDgEWADadsD+9RBaSHwAgFBYQFpIUIE0AFpIUMBYQEgEL1P8ABhCWhJHAPRAWhB9IAxAWBitgAgEL0wtXK2XUgBal9KywVK9qohENWQ+IAAXklP8ABkAesANQTgIEb/96v/BPWAVKxC+Nkh4BFgA2nbA/vUA2lE8vo0I0MDYUNpQ/AEA0NhQ2lD9IAzQ2EA4BFgA2nbA/vUQWkh8AQBQWEBaSFCBNABaSFDAWEBIDC9YrYAIDC9LenwTYiwcrZK9qoq3/j8sDtOAeDL+ACgM2nbA/rURPL6NzdhT/ABDsb4FODsRlTgxvgU4AgpE9MTaANgU2hDYL/zT49URltGAOAcYDVp7QP71DNpO0I70QgwCDkIMjzgACME4BL4AUtM+CNAWxyLQvjTACP/JMHxCAUE4APrAQhbHEz4KECdQvjY3ekAEwHrAyECmwOcGwQD6wRjGUQAkd3pBBMB6wMhBpsHnBsEA+sEYxlEAZEAmQFgAZlBYL/zT48AITNp2wP81DNpO0IE0DdhASAIsL3o8I0AKajRcGkg8AEAcGFP8ABgAGhAHAPQMGgg9IAwMGBitgAg6ucAAABAAFgjAWdFq4nvzQAwAEAELABAAPD/BwAAAAA=
+    load_address: 0x20000020
+    pc_init: 0x1d
+    pc_uninit: 0x5d
+    pc_program_page: 0x169
+    pc_erase_sector: 0x6b
+    pc_erase_all: 0xed
+    data_section_offset: 0x280
+    flash_properties:
+      address_range:
+        start: 0x8000000
+        end: 0x8040000
+      page_size: 0x400
+      erased_byte_value: 0xff
+      program_page_timeout: 400
+      erase_sector_timeout: 400
+      sectors:
+        - size: 0x1000
+          address: 0x0
+
+  - name: stm32wb55x_35x_m4_opt
+    description: STM32WB55x/35x Flash Options
+    instructions: RPIQAMX2AAABackDQ/IAAcTyAAEH1EXyVVIKYAYiSmBA9v9yimBA8iMSxPJnUkD4CCxI9qsSzPbvUkD4CCy/80+PAmjSAxLUQvY7IsD2GQJA+AQsRvZ/YsT2XUJA+AQsv/NPjwJo0gMV1AAgcEdK9qoiCmADaNsD5tUKYANo2wNCvwpgA2hf6sMz3dUKYANo2wPu1NjnSvaqIgpgA2jbA+PVCmADaNsDQr8KYANoX+rDM9rVCmADaNsD7tTV5wC/RPIQAMX2AABP8IBBQWC/80+PAWjJA0PyAAHE8gABCdRP8ABCQmC/80+PAmjSAxXUACBwR0r2qiIKYANo2wPv1QpgA2jbA0K/CmADaF/qwzPm1QpgA2jbA+7U4edK9qoiCmADaNsD49UKYANo2wNCvwpgA2hf6sMz2tUKYANo2wPu1NXnACBwR0TyEABP8qoSxfYAAEzy+jzD9v9SwPgAwAJhQPL/Ek/wAENCYYNh/yPDYQNiQmIAIoJiTPIAAs/2/3LCYk/0ADJCYL/zT48CaNIDCdQBaBHqDA8PvwAgTPL6MQFgASBwR0PyAALE8gACSvaqIxNgAWjJA+vVE2ABaMkDQr8TYAFoX+rBMeLVE2ABaMkD7tTd5wAgcEct6fBNhLARfBBoAJERfUf2/2wCkRF+FXkDkVF+VnnXepL4DICS+A7gkvgSoJL4FbABkc72j3wTf1F/EokM6gAMRPIQAMX2AABM8vo0ReoGJk/2AGVC6gdiT/YAZwRgTPCAVM/2/3XH9v93RPThBC5DOkMEYUZhgmFI6g5CQvD/IsJhAJpD6gEhQuoKQkLw/yICYgKaQuoLIipDQmIDmgGfQuoHIipDgmKl9XhSEUPBYk/0ADG/80+PQWC/80+PAWjJAw3UAWhM8voyEUIg0AFoTPL6MhFDAWABIASwvejwjUPyAAHE8gABSvaqIwtgAmjSA+fVC2ACaNIDQr8LYAJoX+rCMt7VC2ACaNID7tTZ5wAgBLC96PCNELVI8gAMwfb/fNL4AOC/80+P3PgAMI7qAw5H9v9jzvaPcx7qAw8YvxC9kvgE4Nz4CDBUeW/zXyNk8wguc0UcvwEwEL2y+Ajg1Hrc+BAwTuoEZGNAQPL/FMjyAAQjQhy/AjAQvZL4DOCUe9z4GDBO6gREP/qD86NCHL8DMBC9kvgQ4JR83PggME7qBEQ/+oPzo0IcvwQwEL1UfZL4FODc+CgwJAIE9IB0b/NfI3REo0IcvwUwEL1UfpL4GODc+DAwJAIE9IB0b/NfI3REo0IcvwYwEL0Tf1J/3PhoQBICAvR8Um/znzQaRJRCHL8HMBC9CEQQvQAAAAA=
+    load_address: 0x20000020
     pc_init: 0x1
-    pc_uninit: 0x15
-    pc_program_page: 0x109
-    pc_erase_sector: 0x8f
-    pc_erase_all: 0x23
-    data_section_offset: 0x1a8
+    pc_uninit: 0xc1
+    pc_program_page: 0x1dd
+    pc_erase_sector: 0x1d9
+    pc_erase_all: 0x149
+    data_section_offset: 0x3e8
+    flash_properties:
+      address_range:
+        start: 0x1fff8000
+        end: 0x1fff8020
+      page_size: 0x20
+      erased_byte_value: 0xff
+      program_page_timeout: 3000
+      erase_sector_timeout: 3000
+      sectors:
+        - size: 0x20
+          address: 0x0
+
+  - name: stm32wb5x_m4_512
+    description: STM32WB5x_M4_512 Flash
+    default: true
+    instructions: QLpwR8C6cEdP6jAAcEcAAMDzTCBwR7/zT49wR3K2kkhBaQApA9qRSYFgkUmBYABqwAMQ1I9ISvaqIQFgSRABYAYhQWBA9v9xgWDIEIpJCGB/IAkfCGBitgAgcEeCSEFpQfAAQUFhACBwRxC1crbA80wifUgBackD/NQBaUkD/NQBaQkD/NQBaUTy+jQhQwFhQWlB9vhzmUNBYUFpQvACAhFDQWFBaUH0gDFBYUr2qiFwSgDgEWADadsD+9RBaSHwAgFBYQFpIUIE0AFpIUMBYQEgEL1P8ABhCWhJHAPRAWhB9IAxAWBitgAgEL0wtXK2XUgBal9KywVK9qohENWQ+IAAXklP8ABkAesANQTgIEb/96v/BPWAVKxC+Nkh4BFgA2nbA/vUA2lE8vo0I0MDYUNpQ/AEA0NhQ2lD9IAzQ2EA4BFgA2nbA/vUQWkh8AQBQWEBaSFCBNABaSFDAWEBIDC9YrYAIDC9LenwTYiwcrZK9qoq3/j8sDtOAeDL+ACgM2nbA/rURPL6NzdhT/ABDsb4FODsRlTgxvgU4AgpE9MTaANgU2hDYL/zT49URltGAOAcYDVp7QP71DNpO0I70QgwCDkIMjzgACME4BL4AUtM+CNAWxyLQvjTACP/JMHxCAUE4APrAQhbHEz4KECdQvjY3ekAEwHrAyECmwOcGwQD6wRjGUQAkd3pBBMB6wMhBpsHnBsEA+sEYxlEAZEAmQFgAZlBYL/zT48AITNp2wP81DNpO0IE0DdhASAIsL3o8I0AKajRcGkg8AEAcGFP8ABgAGhAHAPQMGgg9IAwMGBitgAg6ucAAABAAFgjAWdFq4nvzQAwAEAELABAAPD/BwAAAAA=
+    load_address: 0x20000020
+    pc_init: 0x1d
+    pc_uninit: 0x5d
+    pc_program_page: 0x169
+    pc_erase_sector: 0x6b
+    pc_erase_all: 0xed
+    data_section_offset: 0x280
     flash_properties:
       address_range:
         start: 0x8000000
         end: 0x8080000
       page_size: 0x400
       erased_byte_value: 0xff
-      program_page_timeout: 0x190
-      erase_sector_timeout: 0x190
+      program_page_timeout: 400
+      erase_sector_timeout: 400
       sectors:
         - size: 0x1000
           address: 0x0
-  - name: stm32wb_m4
-    description: STM32WB_M4 Flash
-    cores:
-      - main
+
+  - name: stm32wb5x_m4_640
+    description: STM32WB5x_M4_640 Flash
     default: true
-    instructions: Qfb4cQHqUCBwR0pISEmBYElJgWAAIHBHRkhBaUHwAEFBYQAgcEcBIHBHELVK9qoiQklASADgCmADadsD+9RE8vo0BGFI8gQDQ2FDaUP0gDNDYQDgCmADadsD+9QAIUFhAWkhQgLQBGEBIBC9ACAQvUH2+HEB6lAiELUuSAFpEfRAP/vRAWlJA/zUAWkJA/zURPL6NARhQvACAUFhQWlB9IAxQWFK9qohJEoA4BFgA2nbA/vUACFBYQFpIUIC0ARhASAQvQAgEL0QtRpLyR1A8v8UIfAHARxhASRcYR/gHGkU9EA/+9EcaWQD/NQcaSQD/NQUaARgVGhEYBxpFPRAP/vRHGlkA/zUHGkkA/zUHGmkBwHVASAQvQgwCDkIMgAp3dFYaSDwAQBYYQAgEL0AACMBZ0UAQABYq4nvzQAwAEAAAAAA
-    pc_init: 0xb
-    pc_uninit: 0x19
-    pc_program_page: 0xc9
-    pc_erase_sector: 0x71
-    pc_erase_all: 0x2b
-    data_section_offset: 0x140
+    instructions: QLpwR8C6cEdP6jAAcEcAAMDzTCBwR7/zT49wR3K2kkhBaQApA9qRSYFgkUmBYABqwAMQ1I9ISvaqIQFgSRABYAYhQWBA9v9xgWDIEIpJCGB/IAkfCGBitgAgcEeCSEFpQfAAQUFhACBwRxC1crbA80wifUgBackD/NQBaUkD/NQBaQkD/NQBaUTy+jQhQwFhQWlB9vhzmUNBYUFpQvACAhFDQWFBaUH0gDFBYUr2qiFwSgDgEWADadsD+9RBaSHwAgFBYQFpIUIE0AFpIUMBYQEgEL1P8ABhCWhJHAPRAWhB9IAxAWBitgAgEL0wtXK2XUgBal9KywVK9qohENWQ+IAAXklP8ABkAesANQTgIEb/96v/BPWAVKxC+Nkh4BFgA2nbA/vUA2lE8vo0I0MDYUNpQ/AEA0NhQ2lD9IAzQ2EA4BFgA2nbA/vUQWkh8AQBQWEBaSFCBNABaSFDAWEBIDC9YrYAIDC9LenwTYiwcrZK9qoq3/j8sDtOAeDL+ACgM2nbA/rURPL6NzdhT/ABDsb4FODsRlTgxvgU4AgpE9MTaANgU2hDYL/zT49URltGAOAcYDVp7QP71DNpO0I70QgwCDkIMjzgACME4BL4AUtM+CNAWxyLQvjTACP/JMHxCAUE4APrAQhbHEz4KECdQvjY3ekAEwHrAyECmwOcGwQD6wRjGUQAkd3pBBMB6wMhBpsHnBsEA+sEYxlEAZEAmQFgAZlBYL/zT48AITNp2wP81DNpO0IE0DdhASAIsL3o8I0AKajRcGkg8AEAcGFP8ABgAGhAHAPQMGgg9IAwMGBitgAg6ucAAABAAFgjAWdFq4nvzQAwAEAELABAAPD/BwAAAAA=
+    load_address: 0x20000020
+    pc_init: 0x1d
+    pc_uninit: 0x5d
+    pc_program_page: 0x169
+    pc_erase_sector: 0x6b
+    pc_erase_all: 0xed
+    data_section_offset: 0x280
     flash_properties:
       address_range:
         start: 0x8000000
-        end: 0x8100000
+        end: 0x80a0000
       page_size: 0x400
       erased_byte_value: 0xff
-      program_page_timeout: 0x190
-      erase_sector_timeout: 0x190
+      program_page_timeout: 400
+      erase_sector_timeout: 400
       sectors:
         - size: 0x1000
           address: 0x0
diff --git a/target-gen/Cargo.toml b/target-gen/Cargo.toml
index 874253f2..4df59055 100644
--- a/target-gen/Cargo.toml
+++ b/target-gen/Cargo.toml
@@ -31,7 +31,7 @@ log = "0.4.21"
 zip = "0.6.6"
 clap = { version = "4.5", features = ["derive"] }
 colored = "2"
-anyhow = "1.0.81"
+anyhow = "1.0.82"
 reqwest = { version = "0.12.3", features = ["json", "rustls-tls"], default-features = false }
 futures = "0.3.30"
 tokio = { version = "1.37.0", features = ["macros", "rt", "rt-multi-thread"] }


Test patch:
diff --git a/.github/workflows/smoketest.yml b/.github/workflows/smoketest.yml
index d58099a8..fec93f1e 100644
--- a/.github/workflows/smoketest.yml
+++ b/.github/workflows/smoketest.yml
@@ -23,7 +23,7 @@ jobs:
         run: rustup target add aarch64-unknown-linux-gnu
 
       - name: Install cross 
-        uses: taiki-e/install-action@v2.32.9
+        uses: taiki-e/install-action@v2.32.17
         with:
           tool: cross
 
diff --git a/smoke-tester/Cargo.toml b/smoke-tester/Cargo.toml
index ef27a3e8..8adc77a1 100644
--- a/smoke-tester/Cargo.toml
+++ b/smoke-tester/Cargo.toml
@@ -11,7 +11,7 @@ publish = false
 [dependencies]
 probe-rs = { workspace = true }
 toml = "0.8.12"
-anyhow = "1.0.81"
+anyhow = "1.0.82"
 serde = { version = "1", features = ["derive"] }
 pretty_env_logger = "0.5.0"
 log = "0.4.21"