Repository: probe-rs/probe-rs
Pull request #2581 (2024-06-23 21:38:47)

Add memory access attributes
STM32F4 CCM RAM does not seem to be executable. This causes problems with the smoke tester, which downloads stepping code into the first RAM section it finds.


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 22b66324..f52814ea 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -496,9 +496,9 @@ dependencies = [
 
 [[package]]
 name = "clap_complete"
-version = "4.5.5"
+version = "4.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2020fa13af48afc65a9a87335bda648309ab3d154cd03c7ff95b378c7ed39c4"
+checksum = "fbca90c87c2a04da41e95d1856e8bcd22f159bdbfa147314d2ce5218057b0e58"
 dependencies = [
  "clap",
 ]
@@ -1489,19 +1489,21 @@ dependencies = [
 
 [[package]]
 name = "hyper-rustls"
-version = "0.26.0"
+version = "0.27.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c"
+checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155"
 dependencies = [
  "futures-util",
  "http",
  "hyper",
  "hyper-util",
  "rustls",
+ "rustls-native-certs",
  "rustls-pki-types",
  "tokio",
  "tokio-rustls",
  "tower-service",
+ "webpki-roots",
 ]
 
 [[package]]
@@ -1524,124 +1526,6 @@ dependencies = [
  "tracing",
 ]
 
-[[package]]
-name = "icu_collections"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
-dependencies = [
- "displaydoc",
- "yoke",
- "zerofrom",
- "zerovec",
-]
-
-[[package]]
-name = "icu_locid"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
-dependencies = [
- "displaydoc",
- "litemap",
- "tinystr",
- "writeable",
- "zerovec",
-]
-
-[[package]]
-name = "icu_locid_transform"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
-dependencies = [
- "displaydoc",
- "icu_locid",
- "icu_locid_transform_data",
- "icu_provider",
- "tinystr",
- "zerovec",
-]
-
-[[package]]
-name = "icu_locid_transform_data"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
-
-[[package]]
-name = "icu_normalizer"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
-dependencies = [
- "displaydoc",
- "icu_collections",
- "icu_normalizer_data",
- "icu_properties",
- "icu_provider",
- "smallvec",
- "utf16_iter",
- "utf8_iter",
- "write16",
- "zerovec",
-]
-
-[[package]]
-name = "icu_normalizer_data"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
-
-[[package]]
-name = "icu_properties"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036"
-dependencies = [
- "displaydoc",
- "icu_collections",
- "icu_locid_transform",
- "icu_properties_data",
- "icu_provider",
- "tinystr",
- "zerovec",
-]
-
-[[package]]
-name = "icu_properties_data"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
-
-[[package]]
-name = "icu_provider"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
-dependencies = [
- "displaydoc",
- "icu_locid",
- "icu_provider_macros",
- "stable_deref_trait",
- "tinystr",
- "writeable",
- "yoke",
- "zerofrom",
- "zerovec",
-]
-
-[[package]]
-name = "icu_provider_macros"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.60",
-]
-
 [[package]]
 name = "ident_case"
 version = "1.0.1"
@@ -1650,14 +1534,12 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
 
 [[package]]
 name = "idna"
-version = "1.0.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed"
+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
 dependencies = [
- "icu_normalizer",
- "icu_properties",
- "smallvec",
- "utf8_iter",
+ "unicode-bidi",
+ "unicode-normalization",
 ]
 
 [[package]]
@@ -1907,12 +1789,6 @@ version = "0.4.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
 
-[[package]]
-name = "litemap"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704"
-
 [[package]]
 name = "lock_api"
 version = "0.4.11"
@@ -2066,9 +1942,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
 
 [[package]]
 name = "miniz_oxide"
-version = "0.7.3"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae"
+checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
 dependencies = [
  "adler",
 ]
@@ -2394,6 +2270,12 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
 
+[[package]]
+name = "ppv-lite86"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+
 [[package]]
 name = "predicates"
 version = "3.1.0"
@@ -2612,6 +2494,53 @@ dependencies = [
  "memchr",
 ]
 
+[[package]]
+name = "quinn"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad"
+dependencies = [
+ "bytes",
+ "pin-project-lite",
+ "quinn-proto",
+ "quinn-udp",
+ "rustc-hash",
+ "rustls",
+ "thiserror",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
+name = "quinn-proto"
+version = "0.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe"
+dependencies = [
+ "bytes",
+ "rand",
+ "ring",
+ "rustc-hash",
+ "rustls",
+ "slab",
+ "thiserror",
+ "tinyvec",
+ "tracing",
+]
+
+[[package]]
+name = "quinn-udp"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46"
+dependencies = [
+ "libc",
+ "once_cell",
+ "socket2",
+ "tracing",
+ "windows-sys 0.52.0",
+]
+
 [[package]]
 name = "quote"
 version = "1.0.36"
@@ -2627,6 +2556,36 @@ version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
 
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
 [[package]]
 name = "ratatui"
 version = "0.26.3"
@@ -2713,9 +2672,9 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
 
 [[package]]
 name = "reqwest"
-version = "0.12.4"
+version = "0.12.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10"
+checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37"
 dependencies = [
  "base64",
  "bytes",
@@ -2734,6 +2693,7 @@ dependencies = [
  "once_cell",
  "percent-encoding",
  "pin-project-lite",
+ "quinn",
  "rustls",
  "rustls-native-certs",
  "rustls-pemfile",
@@ -2814,6 +2774,12 @@ version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
 
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
 [[package]]
 name = "rustix"
 version = "0.38.34"
@@ -2829,11 +2795,11 @@ dependencies = [
 
 [[package]]
 name = "rustls"
-version = "0.22.4"
+version = "0.23.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432"
+checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402"
 dependencies = [
- "log",
+ "once_cell",
  "ring",
  "rustls-pki-types",
  "rustls-webpki",
@@ -2866,15 +2832,15 @@ dependencies = [
 
 [[package]]
 name = "rustls-pki-types"
-version = "1.5.0"
+version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "beb461507cee2c2ff151784c52762cf4d9ff6a61f3e80968600ed24fa837fa54"
+checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d"
 
 [[package]]
 name = "rustls-webpki"
-version = "0.102.3"
+version = "0.102.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3bce581c0dd41bce533ce695a1437fa16a7ab5ac3ccfa99fe1a620a7885eabf"
+checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e"
 dependencies = [
  "ring",
  "rustls-pki-types",
@@ -3382,20 +3348,9 @@ dependencies = [
 
 [[package]]
 name = "sync_wrapper"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
-
-[[package]]
-name = "synstructure"
-version = "0.13.1"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.60",
-]
+checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
 
 [[package]]
 name = "tap"
@@ -3583,15 +3538,20 @@ dependencies = [
 ]
 
 [[package]]
-name = "tinystr"
-version = "0.7.6"
+name = "tinyvec"
+version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
 dependencies = [
- "displaydoc",
- "zerovec",
+ "tinyvec_macros",
 ]
 
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
 [[package]]
 name = "tokio"
 version = "1.38.0"
@@ -3622,9 +3582,9 @@ dependencies = [
 
 [[package]]
 name = "tokio-rustls"
-version = "0.25.0"
+version = "0.26.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f"
+checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
 dependencies = [
  "rustls",
  "rustls-pki-types",
@@ -3864,6 +3824,12 @@ dependencies = [
  "version_check",
 ]
 
+[[package]]
+name = "unicode-bidi"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
+
 [[package]]
 name = "unicode-ident"
 version = "1.0.12"
@@ -3876,6 +3842,15 @@ version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
 
+[[package]]
+name = "unicode-normalization"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
+dependencies = [
+ "tinyvec",
+]
+
 [[package]]
 name = "unicode-segmentation"
 version = "1.11.0"
@@ -3922,9 +3897,9 @@ dependencies = [
 
 [[package]]
 name = "url"
-version = "2.5.1"
+version = "2.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56"
+checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
 dependencies = [
  "form_urlencoded",
  "idna",
@@ -3938,18 +3913,6 @@ version = "2.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
 
-[[package]]
-name = "utf16_iter"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
-
-[[package]]
-name = "utf8_iter"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
-
 [[package]]
 name = "utf8parse"
 version = "0.2.1"
@@ -4288,18 +4251,6 @@ dependencies = [
  "windows-sys 0.48.0",
 ]
 
-[[package]]
-name = "write16"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
-
-[[package]]
-name = "writeable"
-version = "0.5.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
-
 [[package]]
 name = "wyz"
 version = "0.5.1"
@@ -4356,30 +4307,6 @@ version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
 
-[[package]]
-name = "yoke"
-version = "0.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5"
-dependencies = [
- "serde",
- "stable_deref_trait",
- "yoke-derive",
- "zerofrom",
-]
-
-[[package]]
-name = "yoke-derive"
-version = "0.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.60",
- "synstructure",
-]
-
 [[package]]
 name = "zero"
 version = "0.1.3"
@@ -4407,55 +4334,12 @@ dependencies = [
  "syn 2.0.60",
 ]
 
-[[package]]
-name = "zerofrom"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55"
-dependencies = [
- "zerofrom-derive",
-]
-
-[[package]]
-name = "zerofrom-derive"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.60",
- "synstructure",
-]
-
 [[package]]
 name = "zeroize"
 version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
 
-[[package]]
-name = "zerovec"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c"
-dependencies = [
- "yoke",
- "zerofrom",
- "zerovec-derive",
-]
-
-[[package]]
-name = "zerovec-derive"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.60",
-]
-
 [[package]]
 name = "zip"
 version = "2.1.3"
diff --git a/changelog/added-memory-access.md b/changelog/added-memory-access.md
new file mode 100644
index 00000000..766955ed
--- /dev/null
+++ b/changelog/added-memory-access.md
@@ -0,0 +1,1 @@
+Added `MemoryAccess` attributes to `RamRegion`, `NvmRegion` and `GenericRegion`
\ No newline at end of file
diff --git a/changelog/changed-is-boot-memory.md b/changelog/changed-is-boot-memory.md
new file mode 100644
index 00000000..3b626784
--- /dev/null
+++ b/changelog/changed-is-boot-memory.md
@@ -0,0 +1,1 @@
+Moved `RamRegion::is_boot_memory` to `MemoryAccess::boot`
\ No newline at end of file
diff --git a/probe-rs-target/src/lib.rs b/probe-rs-target/src/lib.rs
index ab90f2a6..02da3512 100644
--- a/probe-rs-target/src/lib.rs
+++ b/probe-rs-target/src/lib.rs
@@ -28,6 +28,6 @@ pub use chip_family::{
 pub use flash_algorithm::{RawFlashAlgorithm, TransferEncoding};
 pub use flash_properties::FlashProperties;
 pub use memory::{
-    GenericRegion, MemoryRange, MemoryRegion, NvmRegion, PageInfo, RamRegion, SectorDescription,
-    SectorInfo,
+    GenericRegion, MemoryAccess, MemoryRange, MemoryRegion, NvmRegion, PageInfo, RamRegion,
+    SectorDescription, SectorInfo,
 };
diff --git a/probe-rs-target/src/memory.rs b/probe-rs-target/src/memory.rs
index 771a67b6..250b9c15 100644
--- a/probe-rs-target/src/memory.rs
+++ b/probe-rs-target/src/memory.rs
@@ -10,14 +10,41 @@ pub struct NvmRegion {
     /// Address range of the region
     #[serde(serialize_with = "hex_range")]
     pub range: Range<u64>,
-    /// True if the chip boots from this memory
-    #[serde(default)]
-    pub is_boot_memory: bool,
     /// List of cores that can access this region
     pub cores: Vec<String>,
     /// True if the memory region is an alias of a different memory region.
     #[serde(default)]
     pub is_alias: bool,
+    /// Access permissions for the region.
+    #[serde(default)]
+    pub access: Option<MemoryAccess>,
+}
+
+impl NvmRegion {
+    /// Returns the access permissions for the region.
+    pub fn access(&self) -> MemoryAccess {
+        self.access.unwrap_or_default()
+    }
+
+    /// Returns whether the region is readable.
+    pub fn is_readable(&self) -> bool {
+        self.access().read
+    }
+
+    /// Returns whether the region is writable.
+    pub fn is_writable(&self) -> bool {
+        self.access().write
+    }
+
+    /// Returns whether the region is executable.
+    pub fn is_executable(&self) -> bool {
+        self.access().execute
+    }
+
+    /// Returns whether the region is boot memory.
+    pub fn is_boot_memory(&self) -> bool {
+        self.access().boot
+    }
 }
 
 impl NvmRegion {
@@ -29,6 +56,38 @@ impl NvmRegion {
     }
 }
 
+fn default_true() -> bool {
+    true
+}
+
+/// Represents access permissions of a region in RAM.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
+pub struct MemoryAccess {
+    /// True if the region is readable.
+    #[serde(default = "default_true")]
+    pub read: bool,
+    /// True if the region is writable.
+    #[serde(default = "default_true")]
+    pub write: bool,
+    /// True if the region is executable.
+    #[serde(default = "default_true")]
+    pub execute: bool,
+    /// True if the chip boots from this memory
+    #[serde(default)]
+    pub boot: bool,
+}
+
+impl Default for MemoryAccess {
+    fn default() -> Self {
+        MemoryAccess {
+            read: true,
+            write: true,
+            execute: true,
+            boot: false,
+        }
+    }
+}
+
 /// Represents a region in RAM.
 #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
 pub struct RamRegion {
@@ -37,11 +96,38 @@ pub struct RamRegion {
     /// Address range of the region
     #[serde(serialize_with = "hex_range")]
     pub range: Range<u64>,
-    /// True if the chip boots from this memory
-    #[serde(default)]
-    pub is_boot_memory: bool,
     /// List of cores that can access this region
     pub cores: Vec<String>,
+    /// Access permissions for the region.
+    #[serde(default)]
+    pub access: Option<MemoryAccess>,
+}
+
+impl RamRegion {
+    /// Returns the access permissions for the region.
+    pub fn access(&self) -> MemoryAccess {
+        self.access.unwrap_or_default()
+    }
+
+    /// Returns whether the region is readable.
+    pub fn is_readable(&self) -> bool {
+        self.access().read
+    }
+
+    /// Returns whether the region is writable.
+    pub fn is_writable(&self) -> bool {
+        self.access().write
+    }
+
+    /// Returns whether the region is executable.
+    pub fn is_executable(&self) -> bool {
+        self.access().execute
+    }
+
+    /// Returns whether the region is boot memory.
+    pub fn is_boot_memory(&self) -> bool {
+        self.access().boot
+    }
 }
 
 /// Represents a generic region.
@@ -54,6 +140,31 @@ pub struct GenericRegion {
     pub range: Range<u64>,
     /// List of cores that can access this region
     pub cores: Vec<String>,
+    /// Access permissions for the region.
+    #[serde(default)]
+    pub access: Option<MemoryAccess>,
+}
+
+impl GenericRegion {
+    /// Returns the access permissions for the region.
+    pub fn access(&self) -> MemoryAccess {
+        self.access.unwrap_or_default()
+    }
+
+    /// Returns whether the region is readable.
+    pub fn is_readable(&self) -> bool {
+        self.access().read
+    }
+
+    /// Returns whether the region is writable.
+    pub fn is_writable(&self) -> bool {
+        self.access().write
+    }
+
+    /// Returns whether the region is executable.
+    pub fn is_executable(&self) -> bool {
+        self.access().execute
+    }
 }
 
 /// Holds information about a specific, individual flash
diff --git a/probe-rs-tools/src/bin/probe-rs/cmd/dap_server/server/debugger.rs b/probe-rs-tools/src/bin/probe-rs/cmd/dap_server/server/debugger.rs
index ff6e6d32..29f9a917 100644
--- a/probe-rs-tools/src/bin/probe-rs/cmd/dap_server/server/debugger.rs
+++ b/probe-rs-tools/src/bin/probe-rs/cmd/dap_server/server/debugger.rs
@@ -440,21 +440,6 @@ impl Debugger {
             return Err(bad_config);
         }
 
-        if requested_target_session_type == TargetSessionType::AttachRequest {
-            // Since VSCode doesn't do field validation checks for relationships in launch.json request types, check it here.
-            if self.config.flashing_config.flashing_enabled
-                || self.config.flashing_config.halt_after_reset
-                || self.config.flashing_config.full_chip_erase
-                || self.config.flashing_config.restore_unwritten_bytes
-            {
-                let error = DebuggerError::Other(anyhow!(
-                                            "Please do not use any of the `flashing_enabled`, `reset_after_flashing`, halt_after_reset`, `full_chip_erase`, or `restore_unwritten_bytes` options when using `attach` request type."));
-
-                debug_adapter.send_response::<()>(launch_attach_request, Err(&error))?;
-                return Err(error);
-            }
-        }
-
         debug_adapter
             .set_console_log_level(self.config.console_log_level.unwrap_or(ConsoleLog::Console));
 
diff --git a/probe-rs/src/flashing/builder.rs b/probe-rs/src/flashing/builder.rs
index c8807496..acf0050e 100644
--- a/probe-rs/src/flashing/builder.rs
+++ b/probe-rs/src/flashing/builder.rs
@@ -371,7 +371,7 @@ impl FlashBuilder {
 
 #[cfg(test)]
 mod tests {
-    use probe_rs_target::{FlashProperties, SectorDescription};
+    use probe_rs_target::{FlashProperties, MemoryAccess, SectorDescription};
 
     use super::*;
 
@@ -395,7 +395,10 @@ mod tests {
 
         let region = NvmRegion {
             name: Some("FLASH".into()),
-            is_boot_memory: true,
+            access: Some(MemoryAccess {
+                boot: true,
+                ..Default::default()
+            }),
             range: 0..1 << 16,
             cores: vec!["main".into()],
             is_alias: false,
@@ -424,7 +427,10 @@ mod tests {
 
         let region = NvmRegion {
             name: Some("FLASH".into()),
-            is_boot_memory: true,
+            access: Some(MemoryAccess {
+                boot: true,
+                ..Default::default()
+            }),
             range: 0..1 << 16,
             cores: vec!["main".into()],
             is_alias: false,
diff --git a/target-gen/src/commands/elf.rs b/target-gen/src/commands/elf.rs
index 8cd9eb7c..704dc2a8 100644
--- a/target-gen/src/commands/elf.rs
+++ b/target-gen/src/commands/elf.rs
@@ -1,7 +1,7 @@
 use anyhow::{bail, Context, Result};
 use probe_rs_target::{
-    ArmCoreAccessOptions, Chip, ChipFamily, Core, CoreAccessOptions, CoreType, MemoryRegion,
-    NvmRegion, RamRegion, RawFlashAlgorithm, TargetDescriptionSource,
+    ArmCoreAccessOptions, Chip, ChipFamily, Core, CoreAccessOptions, CoreType, MemoryAccess,
+    MemoryRegion, NvmRegion, RamRegion, RawFlashAlgorithm, TargetDescriptionSource,
 };
 use std::{
     borrow::Cow,
@@ -95,17 +95,20 @@ pub fn cmd_elf(
                 name: "<chip name>".to_owned(),
                 memory_map: vec![
                     MemoryRegion::Nvm(NvmRegion {
-                        is_boot_memory: false,
+                        access: None,
                         range: 0..0x2000,
                         cores: vec!["main".to_owned()],
                         name: None,
                         is_alias: false,
                     }),
                     MemoryRegion::Ram(RamRegion {
-                        is_boot_memory: true,
                         range: 0x1_0000..0x2_0000,
                         cores: vec!["main".to_owned()],
                         name: None,
+                        access: Some(MemoryAccess {
+                            boot: true,
+                            ..Default::default()
+                        }),
                     }),
                 ],
                 flash_algorithms: vec![algorithm_name],
diff --git a/target-gen/src/generate.rs b/target-gen/src/generate.rs
index b53af92e..d2769659 100644
--- a/target-gen/src/generate.rs
+++ b/target-gen/src/generate.rs
@@ -5,7 +5,7 @@ use futures::StreamExt;
 use probe_rs::flashing::FlashAlgorithm;
 use probe_rs_target::{
     Architecture, ArmCoreAccessOptions, Chip, ChipFamily, Core as ProbeCore, CoreAccessOptions,
-    CoreType, GenericRegion, MemoryRegion, NvmRegion, RamRegion, RawFlashAlgorithm,
+    CoreType, GenericRegion, MemoryAccess, MemoryRegion, NvmRegion, RamRegion, RawFlashAlgorithm,
     RiscvCoreAccessOptions, TargetDescriptionSource, XtensaCoreAccessOptions,
 };
 use std::collections::HashMap;
@@ -444,7 +444,7 @@ where
 }
 
 /// A flag to indicate what type of memory this is.
-#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
 enum MemoryType {
     /// A RAM memory.
     Ram,
@@ -457,14 +457,28 @@ enum MemoryType {
 /// A struct to combine essential information from [`cmsis_pack::pdsc::Device::memories`].
 /// This is used to apply the necessary sorting and filtering in creating [`MemoryRegion`]s.
 // The sequence of the fields is important for the sorting by derived natural order.
-#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Debug, Clone, PartialEq, Eq)]
 struct DeviceMemory {
     memory_type: MemoryType,
     p_name: Option<String>,
-    is_boot_memory: bool,
     memory_start: u64,
     memory_end: u64,
     name: String,
+    access: MemoryAccess,
+}
+
+impl DeviceMemory {
+    fn access(&self) -> Option<MemoryAccess> {
+        fn is_default(access: &MemoryAccess) -> bool {
+            access == &MemoryAccess::default()
+        }
+
+        if is_default(&self.access) {
+            None
+        } else {
+            Some(self.access)
+        }
+    }
 }
 
 /// Extracts the memory regions in the package.
@@ -491,12 +505,24 @@ pub(crate) fn get_mem_map(device: &Device, cores: &[probe_rs_target::Core]) -> V
             },
             memory_start: memory.start,
             memory_end: memory.start + memory.size,
-            is_boot_memory: memory.startup,
+            access: MemoryAccess {
+                read: memory.access.read,
+                write: memory.access.write,
+                execute: memory.access.execute,
+                boot: memory.startup,
+            },
         })
         .collect();
 
     // Sort by memory type, then by processor name, then by boot memory, then by start address.
-    device_memories.sort();
+    device_memories.sort_by_key(|memory| {
+        (
+            memory.memory_type,
+            memory.p_name.clone(),
+            memory.access.boot,
+            memory.memory_start,
+        )
+    });
 
     let all_cores: Vec<_> = cores.iter().map(|core| core.name.clone()).collect();
 
@@ -518,30 +544,30 @@ pub(crate) fn get_mem_map(device: &Device, cores: &[probe_rs_target::Core]) -> V
         match region.memory_type {
             MemoryType::Ram => {
                 if let Some(MemoryRegion::Ram(existing_region)) = mem_map.iter_mut().find(|existing_region| {
-                        matches!(existing_region, MemoryRegion::Ram(ram_region) if ram_region.name.as_deref() == Some(&region.name))
+                        matches!(existing_region, MemoryRegion::Ram(ram_region) if ram_region.name.as_deref() == Some(&region.name) && ram_region.access == region.access())
                     })
                 {
                     existing_region.cores.extend_from_slice(&cores);
                 } else {
                     mem_map.push(MemoryRegion::Ram(RamRegion {
+                        access: region.access(),
                         name: Some(region.name),
                         range: region.memory_start..region.memory_end,
-                        is_boot_memory: region.is_boot_memory,
                         cores,
                     }));
                 }
             },
             MemoryType::Nvm => {
                 if let Some(MemoryRegion::Nvm(existing_region)) = mem_map.iter_mut().find(|existing_region| {
-                        matches!(existing_region, MemoryRegion::Nvm(nvm_region) if nvm_region.name.as_deref() == Some(&region.name))
+                        matches!(existing_region, MemoryRegion::Nvm(nvm_region) if nvm_region.name.as_deref() == Some(&region.name) && nvm_region.access == region.access())
                     })
                 {
                     existing_region.cores.extend_from_slice(&cores);
                 } else {
                     mem_map.push(MemoryRegion::Nvm(NvmRegion {
+                        access: region.access(),
                         name: Some(region.name),
                         range: region.memory_start..region.memory_end,
-                        is_boot_memory: region.is_boot_memory,
                         cores,
                         is_alias: false,
                     }));
@@ -549,12 +575,13 @@ pub(crate) fn get_mem_map(device: &Device, cores: &[probe_rs_target::Core]) -> V
             },
             MemoryType::Generic => {
                 if let Some(MemoryRegion::Generic(existing_region)) = mem_map.iter_mut().find(|existing_region| {
-                        matches!(existing_region, MemoryRegion::Generic(generic_region) if generic_region.name.as_deref() == Some(&region.name))
+                        matches!(existing_region, MemoryRegion::Generic(generic_region) if generic_region.name.as_deref() == Some(&region.name) && generic_region.access == region.access())
                     })
                 {
                     existing_region.cores.extend_from_slice(&cores);
                 } else {
                     mem_map.push(MemoryRegion::Generic(GenericRegion {
+                        access: region.access(),
                         name: Some(region.name),
                         range: region.memory_start..region.memory_end,
                         cores,


Test patch:
diff --git a/.github/workflows/smoketest.yml b/.github/workflows/smoketest.yml
index 0f2c6adc..b9ce27e2 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.39.1
+        uses: taiki-e/install-action@v2.41.3
         with:
           tool: cross
 
diff --git a/probe-rs/tests/gpio-hal-blinky/Cargo.lock b/probe-rs/tests/gpio-hal-blinky/Cargo.lock
index 489f4d27..868b2c11 100644
--- a/probe-rs/tests/gpio-hal-blinky/Cargo.lock
+++ b/probe-rs/tests/gpio-hal-blinky/Cargo.lock
@@ -158,18 +158,18 @@ dependencies = [
 
 [[package]]
 name = "microbit"
-version = "0.14.0"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ea941ae60d022668f789ff6a6439fdb59b5cea202cd2affbb967e9af7425356"
+checksum = "e65a87c29e39e928c536c160bacf679d815e0c00bca26665b34e2c7eac926b93"
 dependencies = [
  "microbit-common",
 ]
 
 [[package]]
 name = "microbit-common"
-version = "0.14.0"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37409f40befaa165d8a94255955475337422f5fe2fecaeeeedde170562ee114b"
+checksum = "26d84d7858bbe6cdd89c429be9aa62f2820d1a271e66580df22fe9093bb63c51"
 dependencies = [
  "embedded-hal 1.0.0",
  "nrf51-hal",
@@ -193,9 +193,9 @@ checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d"
 
 [[package]]
 name = "nrf-hal-common"
-version = "0.17.1"
+version = "0.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56fbecd598c7f16e32bd4783447ca023aa7897d4a4c8e70f6b7c5739c81b4ceb"
+checksum = "0c134de1f2f0191aed3fc24d3831da8808d1e636b06edf81a5717103095f625d"
 dependencies = [
  "cast",
  "cfg-if",
@@ -213,9 +213,9 @@ dependencies = [
 
 [[package]]
 name = "nrf51-hal"
-version = "0.17.1"
+version = "0.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fb186285d15fdfe7329ebb25e64b898f1c619831c43dc96849f11c3ef244b2a"
+checksum = "22ed1244a7c2c8da0ce121b6ef28175a253c1ddb2ef9849b8f15825295253bcd"
 dependencies = [
  "nrf-hal-common",
  "nrf51-pac",
diff --git a/probe-rs/tests/gpio-hal-blinky/Cargo.toml b/probe-rs/tests/gpio-hal-blinky/Cargo.toml
index 47ac193f..f5643dcc 100644
--- a/probe-rs/tests/gpio-hal-blinky/Cargo.toml
+++ b/probe-rs/tests/gpio-hal-blinky/Cargo.toml
@@ -13,4 +13,4 @@ cortex-m = { version = "0.7", features = [
     "inline-asm",
 ] }
 panic-halt = "0.2.0"
-microbit = "0.14.0"
+microbit = "0.15.0"
diff --git a/smoke-tester/src/tests/stepping.rs b/smoke-tester/src/tests/stepping.rs
index 3c34d05c..45f33a4a 100644
--- a/smoke-tester/src/tests/stepping.rs
+++ b/smoke-tester/src/tests/stepping.rs
@@ -15,29 +15,33 @@ const TEST_CODE: &[u8] = include_bytes!("test_arm.bin");
 fn test_stepping(tracker: &TestTracker, core: &mut Core) -> TestResult {
     println!("Testing stepping...");
 
-    if core.architecture() == Architecture::Riscv {
+    if core.architecture() != Architecture::Arm {
         // Not implemented for RISC-V yet
         return Err(TestFailure::UnimplementedForTarget(
             Box::new(tracker.current_target().clone()),
-            "Testing stepping is not implemented for RISC-V yet.".to_string(),
+            format!(
+                "Testing stepping is not implemented for {:?} yet.",
+                core.architecture()
+            ),
         ));
     }
 
-    let ram_region = core.memory_regions().find_map(MemoryRegion::as_ram_region);
+    let ram_region = core
+        .memory_regions()
+        .filter_map(MemoryRegion::as_ram_region)
+        .find(|r| r.is_executable());
 
-    let ram_region = if let Some(ram_region) = ram_region {
-        ram_region.clone()
-    } else {
+    let Some(ram_region) = ram_region else {
         return Err(TestFailure::Skipped(
             "No RAM configured for core, unable to test stepping".to_string(),
         ));
     };
 
+    let code_load_address = ram_region.range.start;
+
     core.reset_and_halt(Duration::from_millis(100))
         .into_diagnostic()?;
 
-    let code_load_address = ram_region.range.start;
-
     core.write_8(code_load_address, TEST_CODE)
         .into_diagnostic()?;