mirror of
https://github.com/mytechnotalent/Embedded-Hacking.git
synced 2026-07-07 13:08:09 +02:00
Initial commit
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
[build]
|
||||
target = "thumbv8m.main-none-eabihf"
|
||||
|
||||
[target.thumbv6m-none-eabi]
|
||||
linker = "flip-link"
|
||||
rustflags = [
|
||||
"-C", "link-arg=--nmagic",
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
"-C", "link-arg=-Tdefmt.x",
|
||||
"-C", "no-vectorize-loops",
|
||||
]
|
||||
runner = "${PICOTOOL_PATH} load -u -v -x -t elf"
|
||||
|
||||
[target.thumbv8m.main-none-eabihf]
|
||||
rustflags = [
|
||||
"-C", "link-arg=--nmagic",
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
"-C", "link-arg=-Tdefmt.x",
|
||||
"-C", "target-cpu=cortex-m33",
|
||||
]
|
||||
runner = "${PICOTOOL_PATH} load -u -v -x -t elf"
|
||||
|
||||
[target.riscv32imac-unknown-none-elf]
|
||||
rustflags = [
|
||||
"-C", "link-arg=--nmagic",
|
||||
"-C", "link-arg=-Trp2350_riscv.x",
|
||||
"-C", "link-arg=-Tdefmt.x",
|
||||
]
|
||||
runner = "${PICOTOOL_PATH} load -u -v -x -t elf"
|
||||
|
||||
[env]
|
||||
DEFMT_LOG = "debug"
|
||||
@@ -0,0 +1 @@
|
||||
rp2350
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"marus25.cortex-debug",
|
||||
"rust-lang.rust-analyzer",
|
||||
"probe-rs.probe-rs-debugger",
|
||||
"raspberry-pi.raspberry-pi-pico"
|
||||
]
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Pico Debug (probe-rs)",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"request": "launch",
|
||||
"type": "probe-rs-debug",
|
||||
"connectUnderReset": false,
|
||||
"speed": 5000,
|
||||
"runtimeExecutable": "probe-rs",
|
||||
"chip": "${command:raspberry-pi-pico.getChip}",
|
||||
"runtimeArgs": [
|
||||
"dap-server"
|
||||
],
|
||||
"flashingConfig": {
|
||||
"flashingEnabled": true,
|
||||
"haltAfterReset": false
|
||||
},
|
||||
"coreConfigs": [
|
||||
{
|
||||
"coreIndex": 0,
|
||||
"programBinary": "${command:raspberry-pi-pico.launchTargetPath}",
|
||||
"rttEnabled": true,
|
||||
"svdFile": "${command:raspberry-pi-pico.getSVDPath}",
|
||||
"rttChannelFormats": [
|
||||
{
|
||||
"channelNumber": 0,
|
||||
"dataFormat": "Defmt",
|
||||
"mode": "NoBlockSkip",
|
||||
"showTimestamps": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"preLaunchTask": "Build + Generate SBOM (debug)",
|
||||
"consoleLogLevel": "Debug",
|
||||
"wireProtocol": "Swd"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"rust-analyzer.cargo.target": "thumbv8m.main-none-eabihf",
|
||||
"rust-analyzer.check.allTargets": false,
|
||||
"editor.formatOnSave": true,
|
||||
"files.exclude": {
|
||||
".pico-rs": true
|
||||
}
|
||||
}
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Compile Project",
|
||||
"type": "process",
|
||||
"isBuildCommand": true,
|
||||
"command": "cargo",
|
||||
"args": [
|
||||
"build",
|
||||
"--release"
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "dedicated"
|
||||
},
|
||||
"problemMatcher": "$rustc",
|
||||
"options": {
|
||||
"env": {
|
||||
"PICOTOOL_PATH": "${command:raspberry-pi-pico.getPicotoolPath}",
|
||||
"CHIP": "${command:raspberry-pi-pico.getChip}"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Build + Generate SBOM (release)",
|
||||
"type": "shell",
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-lc",
|
||||
"cargo sbom > ${command:raspberry-pi-pico.sbomTargetPathRelease}"
|
||||
],
|
||||
"windows": {
|
||||
"command": "powershell",
|
||||
"args": [
|
||||
"-NoProfile",
|
||||
"-ExecutionPolicy",
|
||||
"Bypass",
|
||||
"-Command",
|
||||
"cargo sbom | Set-Content -Encoding utf8 ${command:raspberry-pi-pico.sbomTargetPathRelease}"
|
||||
]
|
||||
},
|
||||
"dependsOn": "Compile Project",
|
||||
"presentation": {
|
||||
"reveal": "silent",
|
||||
"panel": "shared"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Compile Project (debug)",
|
||||
"type": "process",
|
||||
"isBuildCommand": true,
|
||||
"command": "cargo",
|
||||
"args": [
|
||||
"build"
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": false
|
||||
},
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "dedicated"
|
||||
},
|
||||
"problemMatcher": "$rustc",
|
||||
"options": {
|
||||
"env": {
|
||||
"PICOTOOL_PATH": "${command:raspberry-pi-pico.getPicotoolPath}",
|
||||
"CHIP": "${command:raspberry-pi-pico.getChip}"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Build + Generate SBOM (debug)",
|
||||
"type": "shell",
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-lc",
|
||||
"cargo sbom > ${command:raspberry-pi-pico.sbomTargetPathDebug}"
|
||||
],
|
||||
"windows": {
|
||||
"command": "powershell",
|
||||
"args": [
|
||||
"-NoProfile",
|
||||
"-ExecutionPolicy",
|
||||
"Bypass",
|
||||
"-Command",
|
||||
"cargo sbom | Set-Content -Encoding utf8 ${command:raspberry-pi-pico.sbomTargetPathDebug}"
|
||||
]
|
||||
},
|
||||
"dependsOn": "Compile Project (debug)",
|
||||
"presentation": {
|
||||
"reveal": "silent",
|
||||
"panel": "shared"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Run Project",
|
||||
"type": "shell",
|
||||
"dependsOn": [
|
||||
"Build + Generate SBOM (release)"
|
||||
],
|
||||
"command": "${command:raspberry-pi-pico.getPicotoolPath}",
|
||||
"args": [
|
||||
"load",
|
||||
"-x",
|
||||
"${command:raspberry-pi-pico.launchTargetPathRelease}",
|
||||
"-t",
|
||||
"elf"
|
||||
],
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "dedicated"
|
||||
},
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
||||
Generated
+704
@@ -0,0 +1,704 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||
|
||||
[[package]]
|
||||
name = "bare-metal"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
|
||||
dependencies = [
|
||||
"rustc_version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitfield"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
|
||||
|
||||
[[package]]
|
||||
name = "bitfield"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m"
|
||||
version = "0.7.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9"
|
||||
dependencies = [
|
||||
"bare-metal",
|
||||
"bitfield 0.13.2",
|
||||
"embedded-hal 0.2.7",
|
||||
"volatile-register",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m-rt"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "801d4dec46b34c299ccf6b036717ae0fce602faa4f4fe816d9013b9a7c9f5ba6"
|
||||
dependencies = [
|
||||
"cortex-m-rt-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m-rt-macros"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e37549a379a9e0e6e576fd208ee60394ccb8be963889eebba3ffe0980364f472"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc-any"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a62ec9ff5f7965e4d7280bd5482acd20aadb50d632cf6c1d74493856b011fa73"
|
||||
dependencies = [
|
||||
"debug-helper",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "critical-section"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
||||
|
||||
[[package]]
|
||||
name = "debug-helper"
|
||||
version = "0.3.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f578e8e2c440e7297e008bb5486a3a8a194775224bbc23729b0dbdfaeebf162e"
|
||||
|
||||
[[package]]
|
||||
name = "defmt"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "548d977b6da32fa1d1fda2876453da1e7df63ad0304c8b3dae4dbe7b96f39b78"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"defmt-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "defmt-macros"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d4fc12a85bcf441cfe44344c4b72d58493178ce635338a3f3b78943aceb258e"
|
||||
dependencies = [
|
||||
"defmt-parser",
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "defmt-parser"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "defmt-rtt"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93d5a25c99d89c40f5676bec8cefe0614f17f0f40e916f98e345dae941807f9e"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
"defmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||
|
||||
[[package]]
|
||||
name = "embedded-dma"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "994f7e5b5cb23521c22304927195f236813053eb9c065dd2226a32ba64695446"
|
||||
dependencies = [
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff"
|
||||
dependencies = [
|
||||
"nb 0.1.3",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89"
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal-async"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884"
|
||||
dependencies = [
|
||||
"embedded-hal 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal-nb"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605"
|
||||
dependencies = [
|
||||
"embedded-hal 1.0.0",
|
||||
"nb 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-io"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
|
||||
|
||||
[[package]]
|
||||
name = "flash"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cortex-m",
|
||||
"cortex-m-rt",
|
||||
"defmt",
|
||||
"defmt-rtt",
|
||||
"fugit",
|
||||
"panic-halt",
|
||||
"panic-probe",
|
||||
"rp2040-boot2",
|
||||
"rp2040-hal",
|
||||
"rp235x-hal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "frunk"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28aef0f9aa070bce60767c12ba9cb41efeaf1a2bc6427f87b7d83f11239a16d7"
|
||||
dependencies = [
|
||||
"frunk_core",
|
||||
"frunk_derives",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "frunk_core"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "476eeaa382e3462b84da5d6ba3da97b5786823c2d0d3a0d04ef088d073da225c"
|
||||
|
||||
[[package]]
|
||||
name = "frunk_derives"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0b4095fc99e1d858e5b8c7125d2638372ec85aa0fe6c807105cf10b0265ca6c"
|
||||
dependencies = [
|
||||
"frunk_proc_macro_helpers",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "frunk_proc_macro_helpers"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1952b802269f2db12ab7c0bd328d0ae8feaabf19f352a7b0af7bb0c5693abfce"
|
||||
dependencies = [
|
||||
"frunk_core",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fugit"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e639847d312d9a82d2e75b0edcc1e934efcc64e6cb7aa94f0b1fbec0bc231d6"
|
||||
dependencies = [
|
||||
"gcd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gcd"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a"
|
||||
|
||||
[[package]]
|
||||
name = "hash32"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heapless"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
|
||||
dependencies = [
|
||||
"hash32",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nb"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
|
||||
dependencies = [
|
||||
"nb 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nb"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d"
|
||||
|
||||
[[package]]
|
||||
name = "num_enum"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9"
|
||||
dependencies = [
|
||||
"num_enum_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_enum_derive"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "panic-halt"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a513e167849a384b7f9b746e517604398518590a9142f4846a32e3c2a4de7b11"
|
||||
|
||||
[[package]]
|
||||
name = "panic-probe"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd402d00b0fb94c5aee000029204a46884b1262e0c443f166d86d2c0747e1a1a"
|
||||
dependencies = [
|
||||
"cortex-m",
|
||||
"defmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||
|
||||
[[package]]
|
||||
name = "pio"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76e09694b50f89f302ed531c1f2a7569f0be5867aee4ab4f8f729bbeec0078e3"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"num_enum",
|
||||
"paste",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr2"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
|
||||
[[package]]
|
||||
name = "riscv"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f5c1b8bf41ea746266cdee443d1d1e9125c86ce1447e1a2615abd34330d33a9"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
"embedded-hal 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "riscv-rt"
|
||||
version = "0.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0d35e32cf1383183e8885d8a9aa4402a087fd094dc34c2cb6df6687d0229dfe"
|
||||
dependencies = [
|
||||
"riscv",
|
||||
"riscv-rt-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "riscv-rt-macros"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30f19a85fe107b65031e0ba8ec60c34c2494069fe910d6c297f5e7cb5a6f76d0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rp-binary-info"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f582261945fa215d40e2988b4df595d11c0908c0fff97a0fe23df766d117b790"
|
||||
|
||||
[[package]]
|
||||
name = "rp-hal-common"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8288358786b1458fb2caac8c4b40fb529ef4200d6c46467e2695b7a8ba573ae8"
|
||||
dependencies = [
|
||||
"fugit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rp2040-boot2"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c92f344f63f950ee36cf4080050e4dce850839b9175da38f9d2ffb69b4dbb21"
|
||||
dependencies = [
|
||||
"crc-any",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rp2040-hal"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fb79a4590775204387f334672e6f79c0d734d0a159da23d60677b3c10fa1245"
|
||||
dependencies = [
|
||||
"bitfield 0.14.0",
|
||||
"cortex-m",
|
||||
"critical-section",
|
||||
"embedded-dma",
|
||||
"embedded-hal 0.2.7",
|
||||
"embedded-hal 1.0.0",
|
||||
"embedded-hal-async",
|
||||
"embedded-hal-nb",
|
||||
"embedded-io",
|
||||
"frunk",
|
||||
"fugit",
|
||||
"itertools 0.10.5",
|
||||
"nb 1.1.0",
|
||||
"paste",
|
||||
"pio",
|
||||
"rand_core",
|
||||
"rp-binary-info",
|
||||
"rp-hal-common",
|
||||
"rp2040-hal-macros",
|
||||
"rp2040-pac",
|
||||
"usb-device",
|
||||
"vcell",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rp2040-hal-macros"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86479063e497efe1ae81995ef9071f54fd1c7427e04d6c5b84cde545ff672a5e"
|
||||
dependencies = [
|
||||
"cortex-m-rt",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rp2040-pac"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83cbcd3f7a0ca7bbe61dc4eb7e202842bee4e27b769a7bf3a4a72fa399d6e404"
|
||||
dependencies = [
|
||||
"cortex-m",
|
||||
"cortex-m-rt",
|
||||
"critical-section",
|
||||
"vcell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rp235x-hal"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2939c82776b0b4ae110168b4298b5adf831e6cff249b057bf2a2187453b959c"
|
||||
dependencies = [
|
||||
"bitfield 0.14.0",
|
||||
"cortex-m",
|
||||
"cortex-m-rt",
|
||||
"critical-section",
|
||||
"embedded-dma",
|
||||
"embedded-hal 0.2.7",
|
||||
"embedded-hal 1.0.0",
|
||||
"embedded-hal-async",
|
||||
"embedded-hal-nb",
|
||||
"embedded-io",
|
||||
"frunk",
|
||||
"fugit",
|
||||
"gcd",
|
||||
"itertools 0.13.0",
|
||||
"nb 1.1.0",
|
||||
"paste",
|
||||
"pio",
|
||||
"rand_core",
|
||||
"riscv",
|
||||
"riscv-rt",
|
||||
"rp-binary-info",
|
||||
"rp-hal-common",
|
||||
"rp235x-hal-macros",
|
||||
"rp235x-pac",
|
||||
"sha2-const-stable",
|
||||
"usb-device",
|
||||
"vcell",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rp235x-hal-macros"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74edd7a5979e9763bbb98e9746e711bac7464ee3397af7288e6c288ff0d3c764"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rp235x-pac"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ffcb6931deee4242886b5a1df62db5e2555b0eb6ae1e8be101f3ea3e58e65c6"
|
||||
dependencies = [
|
||||
"cortex-m",
|
||||
"cortex-m-rt",
|
||||
"critical-section",
|
||||
"vcell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "sha2-const-stable"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f179d4e11094a893b82fff208f74d448a7512f99f5a0acbd5c679b705f83ed9"
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "usb-device"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98816b1accafbb09085168b90f27e93d790b4bfa19d883466b5e53315b5f06a6"
|
||||
dependencies = [
|
||||
"heapless",
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vcell"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
||||
[[package]]
|
||||
name = "volatile-register"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc"
|
||||
dependencies = [
|
||||
"vcell",
|
||||
]
|
||||
@@ -0,0 +1,79 @@
|
||||
[package]
|
||||
edition = "2024"
|
||||
name = "flash"
|
||||
version = "0.1.0"
|
||||
license = "MIT or Apache-2.0"
|
||||
|
||||
[lib]
|
||||
name = "flash_lib"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "flash"
|
||||
path = "src/main.rs"
|
||||
|
||||
|
||||
[dependencies]
|
||||
cortex-m = "0.7"
|
||||
cortex-m-rt = "0.7"
|
||||
fugit = "0.3"
|
||||
defmt = "1"
|
||||
defmt-rtt = "1"
|
||||
|
||||
[target.'cfg( target_arch = "arm" )'.dependencies]
|
||||
panic-probe = { version = "1", features = ["print-defmt"] }
|
||||
|
||||
[target.'cfg( target_arch = "riscv32" )'.dependencies]
|
||||
panic-halt = { version = "1.0.0" }
|
||||
|
||||
[target.thumbv6m-none-eabi.dependencies]
|
||||
rp2040-boot2 = "0.3"
|
||||
rp2040-hal = { version = "0.11", features = ["rt", "critical-section-impl"] }
|
||||
|
||||
[target.riscv32imac-unknown-none-elf.dependencies]
|
||||
rp235x-hal = { version = "0.3", features = ["rt", "critical-section-impl"] }
|
||||
|
||||
[target."thumbv8m.main-none-eabihf".dependencies]
|
||||
rp235x-hal = { version = "0.3", features = ["rt", "critical-section-impl"] }
|
||||
|
||||
# cargo build/run
|
||||
[profile.dev]
|
||||
debug = 2
|
||||
debug-assertions = true
|
||||
opt-level = 2
|
||||
overflow-checks = true
|
||||
|
||||
# cargo build/run --release
|
||||
[profile.release]
|
||||
debug = 2
|
||||
debug-assertions = false
|
||||
lto = "fat"
|
||||
opt-level = 2
|
||||
overflow-checks = false
|
||||
|
||||
# do not optimize proc-macro crates = faster builds from scratch
|
||||
[profile.dev.build-override]
|
||||
debug = false
|
||||
debug-assertions = false
|
||||
overflow-checks = false
|
||||
opt-level = 0
|
||||
|
||||
[profile.release.build-override]
|
||||
debug = false
|
||||
debug-assertions = false
|
||||
overflow-checks = false
|
||||
opt-level = 0
|
||||
|
||||
# cargo test
|
||||
[profile.test]
|
||||
debug = 2
|
||||
debug-assertions = true
|
||||
opt-level = 2
|
||||
overflow-checks = true
|
||||
|
||||
# cargo test --release
|
||||
[profile.bench]
|
||||
debug = 2
|
||||
debug-assertions = false
|
||||
lto = "fat"
|
||||
opt-level = 3
|
||||
@@ -0,0 +1,112 @@
|
||||
# 0x0f Flash Rust Driver
|
||||
|
||||
This repository contains a Bare-Metal Rust driver demonstrating **Hardware Flash Memory** access (reading, erasing, and writing) on the **RP2350** (and RP2040) microcontrollers.
|
||||
|
||||
It includes:
|
||||
- A demo (`src/main.rs`) that erases a sector of flash, writes a message into it, reads the message back out of flash, and prints it over UART.
|
||||
- A reusable library module (`src/flash.rs`) providing a hardware-agnostic `flash_lib` containing constants, buffer preparation, and formatting helpers.
|
||||
- Board initialization logic (`src/board.rs`).
|
||||
|
||||
## 🚀 Getting Started from Scratch
|
||||
|
||||
If you're starting with a fresh machine, follow these exact steps to install the toolchain, build the code, and flash it to your microcontroller.
|
||||
|
||||
### 1. Install Rust
|
||||
First, install `rustup` (the Rust toolchain installer) if you haven't already:
|
||||
```bash
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
```
|
||||
*Note: Restart your terminal or run `source $HOME/.cargo/env` after this finishes.*
|
||||
|
||||
Ensure your Rust compiler is up to date:
|
||||
```bash
|
||||
rustup update
|
||||
```
|
||||
|
||||
### 2. Install the Target Architecture
|
||||
This project is configured for the **RP2350** (ARM Cortex-M33). We need to install the cross-compilation target for it:
|
||||
```bash
|
||||
rustup target add thumbv8m.main-none-eabihf
|
||||
```
|
||||
*(If you were targeting the RP2040, you would use `thumbv6m-none-eabi` instead).*
|
||||
|
||||
### 3. Install Build Tools
|
||||
You will need a few extra tools to help link and format the firmware for the RP-series chips.
|
||||
|
||||
Install `flip-link` (adds zero-cost stack overflow protection):
|
||||
```bash
|
||||
cargo install flip-link
|
||||
```
|
||||
|
||||
Install `picotool` (used by `cargo run` to flash the chip):
|
||||
- **macOS:** `brew install picotool`
|
||||
- **Linux/Windows:** Follow the official Raspberry Pi documentation to install `picotool` or build it from source.
|
||||
|
||||
### 4. Building the Code
|
||||
To compile the code for the microcontroller, simply run:
|
||||
```bash
|
||||
cargo build
|
||||
```
|
||||
|
||||
To build a highly optimized release version (smaller and faster):
|
||||
```bash
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
### 5. Flashing to the Microcontroller
|
||||
This project is pre-configured in `.cargo/config.toml` to use `picotool` as the custom runner.
|
||||
|
||||
To flash the code:
|
||||
1. Hold down the **BOOTSEL** button on your RP2350 board.
|
||||
2. Plug it into your computer via USB (or press the RUN/RESET button while holding BOOTSEL).
|
||||
3. Run the following command:
|
||||
|
||||
```bash
|
||||
cargo run --release
|
||||
```
|
||||
*`cargo` will compile the code and automatically use `picotool` to upload the `.elf` file directly to your board and start executing it!*
|
||||
|
||||
### 6. Testing on the Host
|
||||
Because the data manipulation and string formatting logic is separated into a reusable library without touching hardware registers, you can run the unit tests natively on your computer!
|
||||
|
||||
However, because this project sets a default bare-metal target (`thumbv8m.main-none-eabihf`) in `.cargo/config.toml`, running a plain `cargo test` will fail because the standard library doesn't exist on the microcontroller. You must explicitly tell Cargo to compile the tests for your host computer's processor architecture:
|
||||
|
||||
**Mac (Apple Silicon):**
|
||||
```bash
|
||||
cargo test --lib --target aarch64-apple-darwin
|
||||
```
|
||||
|
||||
**Linux (Intel/AMD 64-bit):**
|
||||
```bash
|
||||
cargo test --lib --target x86_64-unknown-linux-gnu
|
||||
```
|
||||
|
||||
**Windows (64-bit):**
|
||||
```bash
|
||||
cargo test --lib --target x86_64-pc-windows-msvc
|
||||
```
|
||||
|
||||
## 🧠 Code Walkthrough
|
||||
|
||||
This section explains exactly how the code works, where the entry point is, and traces the flow of execution as if you were stepping through it line-by-line.
|
||||
|
||||
### 1. The Entry Point (`src/main.rs`)
|
||||
Unlike a standard computer program, bare-metal microcontrollers do not have an operating system to call `main()`. Instead, we use the `#[entry]` macro from the HAL (Hardware Abstraction Layer) to define the very first function that runs after the chip boots up.
|
||||
|
||||
* **`main() -> !`**: This is the absolute start of our code. It takes ownership of all the hardware peripherals (`hal::pac::Peripherals::take().unwrap()`) and immediately passes them into `board::run(...)`. The `-> !` means this function never returns (because embedded devices run in an infinite loop).
|
||||
|
||||
### 2. Board Initialization (`src/board.rs`)
|
||||
Once execution enters `board.rs`, we initialize the system clocks, pins, UART (for logging), and interact with the hardware Flash peripheral.
|
||||
|
||||
* **`run(...)`**: The master setup function. Initializes the clocks and UART, then runs the `flash_demo(...)`. After the demo finishes, it parks the CPU in a low-power `wfe` (wait for event) infinite loop.
|
||||
* **`flash_demo(...)`**: Orchestrates the core flash workflow. It prepares a write buffer in RAM (filling it with `0xFF` and inserting a demo string), calls `flash_write(...)` to program it to the last sector of flash memory, reads the data back into a `read_buf`, and then formats/prints the result.
|
||||
* **`flash_write(...)`**: A high-level wrapper that ensures flash modification is safe. It wraps the low-level flash operations in an interrupt-free critical section (`cortex_m::interrupt::free`) to prevent the CPU from trying to fetch instructions from flash while it is being erased or programmed.
|
||||
* **`flash_prepare_sector(...)` / `flash_program_and_restore(...)`**: Low-level, `unsafe` functions that call directly into the RP2040/RP2350 BootROM routines. They disconnect flash from the XIP (eXecute In Place) cache, erase the target sector, program the new data, flush the hardware cache, and then safely restore XIP mode so the CPU can resume executing code from flash.
|
||||
* **`flash_read(...)`**: Since the flash memory on the RP2350/RP2040 is mapped directly into the CPU's memory address space (XIP), reading from flash is as simple as performing a standard pointer read from `XIP_BASE + offset`.
|
||||
|
||||
### 3. The Reusable Flash Library (`src/flash.rs`)
|
||||
While `board.rs` directly manipulates the flash via BootROM calls, `flash.rs` defines the memory layout constants and handles buffer manipulation and string formatting for logging.
|
||||
|
||||
* **Constants**: Defines `FLASH_SIZE_BYTES`, `FLASH_SECTOR_SIZE`, `FLASH_PAGE_SIZE`, and `XIP_BASE`, keeping magic numbers out of the application code.
|
||||
* **`prepare_write_buf(...)`**: Fills a provided buffer with `0xFF` (representing the erased state of flash memory) and then copies our `DEMO_MSG` into the start of the buffer.
|
||||
* **`format_readback(...)`**: Extracts the NUL-terminated C-style string from the raw flash read buffer and formats it nicely for printing over UART.
|
||||
@@ -0,0 +1,105 @@
|
||||
//! Implementation module
|
||||
//!
|
||||
//! **File:** `build.rs`
|
||||
//! **Author:** Kevin Thomas
|
||||
//! **Date:** 2025
|
||||
//!
|
||||
//! MIT License
|
||||
//!
|
||||
//! Copyright (c) 2025 Kevin Thomas
|
||||
//!
|
||||
//! Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
//! of this software and associated documentation files (the "Software"), to deal
|
||||
//! in the Software without restriction, including without limitation the rights
|
||||
//! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
//! copies of the Software, and to permit persons to whom the Software is
|
||||
//! furnished to do so, subject to the following conditions:
|
||||
//!
|
||||
//! The above copyright notice and this permission notice shall be included in
|
||||
//! all copies or substantial portions of the Software.
|
||||
//!
|
||||
//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
//! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
//! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
//! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
//! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
//! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
//! SOFTWARE.
|
||||
|
||||
// Import dependencies from std::fs
|
||||
use std::fs::{read_to_string, File};
|
||||
// Import std::io::Write
|
||||
use std::io::Write;
|
||||
// Import std::path::{Path, PathBuf}
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// The main entry point.
|
||||
fn main() {
|
||||
let out = PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
|
||||
let c = read_to_string(".pico-rs").unwrap_or_default().trim().to_lowercase();
|
||||
setup_target(&c, &out);
|
||||
write_riscv(&out);
|
||||
print_cfgs(&out);
|
||||
}
|
||||
|
||||
/// Executes the setup target operation.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `c` - Target string from config.
|
||||
/// * `out` - Output path.
|
||||
fn setup_target(c: &str, out: &Path) {
|
||||
if c == "rp2040" {
|
||||
write_rp2040(out);
|
||||
} else {
|
||||
write_rp2350(out);
|
||||
}
|
||||
}
|
||||
|
||||
/// Executes the write rp2040 operation.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `out` - Output path.
|
||||
fn write_rp2040(out: &Path) {
|
||||
let b = include_bytes!("rp2040.x");
|
||||
File::create(out.join("memory.x")).unwrap().write_all(b).unwrap();
|
||||
println!("cargo::rustc-cfg=rp2040");
|
||||
println!("cargo:rerun-if-changed=rp2040.x");
|
||||
}
|
||||
|
||||
/// Executes the write rp2350 operation.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `out` - Output path.
|
||||
fn write_rp2350(out: &Path) {
|
||||
let b = include_bytes!("rp2350.x");
|
||||
File::create(out.join("memory.x")).unwrap().write_all(b).unwrap();
|
||||
println!("cargo::rustc-cfg=rp2350");
|
||||
println!("cargo:rerun-if-changed=rp2350.x");
|
||||
}
|
||||
|
||||
/// Executes the write riscv operation.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `out` - Output path.
|
||||
fn write_riscv(out: &Path) {
|
||||
let b = include_bytes!("rp2350_riscv.x");
|
||||
File::create(out.join("rp2350_riscv.x")).unwrap().write_all(b).unwrap();
|
||||
}
|
||||
|
||||
/// Executes the print cfgs operation.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `out` - Output path.
|
||||
fn print_cfgs(out: &Path) {
|
||||
println!("cargo::rustc-check-cfg=cfg(rp2040)");
|
||||
println!("cargo::rustc-check-cfg=cfg(rp2350)");
|
||||
println!("cargo:rustc-link-search={}", out.display());
|
||||
println!("cargo:rerun-if-changed=.pico-rs");
|
||||
println!("cargo:rerun-if-changed=rp2350_riscv.x");
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
*
|
||||
* Copyright (c) 2021-2024 The rp-rs Developers
|
||||
* Copyright (c) 2021 rp-rs organization
|
||||
* Copyright (c) 2025 Raspberry Pi Ltd.
|
||||
*/
|
||||
|
||||
MEMORY {
|
||||
BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
|
||||
FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
|
||||
RAM : ORIGIN = 0x20000000, LENGTH = 256K
|
||||
SRAM4 : ORIGIN = 0x20040000, LENGTH = 4k
|
||||
SRAM5 : ORIGIN = 0x20041000, LENGTH = 4k
|
||||
}
|
||||
|
||||
EXTERN(BOOT2_FIRMWARE)
|
||||
|
||||
SECTIONS {
|
||||
.boot2 ORIGIN(BOOT2) :
|
||||
{
|
||||
KEEP(*(.boot2));
|
||||
} > BOOT2
|
||||
} INSERT BEFORE .text;
|
||||
|
||||
SECTIONS {
|
||||
.boot_info : ALIGN(4)
|
||||
{
|
||||
KEEP(*(.boot_info));
|
||||
} > FLASH
|
||||
|
||||
} INSERT AFTER .vector_table;
|
||||
|
||||
_stext = ADDR(.boot_info) + SIZEOF(.boot_info);
|
||||
|
||||
SECTIONS {
|
||||
.bi_entries : ALIGN(4)
|
||||
{
|
||||
__bi_entries_start = .;
|
||||
KEEP(*(.bi_entries));
|
||||
. = ALIGN(4);
|
||||
__bi_entries_end = .;
|
||||
} > FLASH
|
||||
} INSERT AFTER .text;
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
*
|
||||
* Copyright (c) 2021-2024 The rp-rs Developers
|
||||
* Copyright (c) 2021 rp-rs organization
|
||||
* Copyright (c) 2025 Raspberry Pi Ltd.
|
||||
*/
|
||||
|
||||
MEMORY {
|
||||
FLASH : ORIGIN = 0x10000000, LENGTH = 2048K
|
||||
RAM : ORIGIN = 0x20000000, LENGTH = 512K
|
||||
SRAM4 : ORIGIN = 0x20080000, LENGTH = 4K
|
||||
SRAM5 : ORIGIN = 0x20081000, LENGTH = 4K
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
.start_block : ALIGN(4)
|
||||
{
|
||||
__start_block_addr = .;
|
||||
KEEP(*(.start_block));
|
||||
} > FLASH
|
||||
|
||||
} INSERT AFTER .vector_table;
|
||||
|
||||
_stext = ADDR(.start_block) + SIZEOF(.start_block);
|
||||
|
||||
SECTIONS {
|
||||
.bi_entries : ALIGN(4)
|
||||
{
|
||||
__bi_entries_start = .;
|
||||
KEEP(*(.bi_entries));
|
||||
. = ALIGN(4);
|
||||
__bi_entries_end = .;
|
||||
} > FLASH
|
||||
} INSERT AFTER .text;
|
||||
|
||||
SECTIONS {
|
||||
.end_block : ALIGN(4)
|
||||
{
|
||||
__end_block_addr = .;
|
||||
KEEP(*(.end_block));
|
||||
} > FLASH
|
||||
|
||||
} INSERT AFTER .uninit;
|
||||
|
||||
PROVIDE(start_to_end = __end_block_addr - __start_block_addr);
|
||||
PROVIDE(end_to_start = __start_block_addr - __end_block_addr);
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
*
|
||||
* Copyright (c) 2021-2024 The rp-rs Developers
|
||||
* Copyright (c) 2021 rp-rs organization
|
||||
* Copyright (c) 2025 Raspberry Pi Ltd.
|
||||
*/
|
||||
|
||||
MEMORY {
|
||||
FLASH : ORIGIN = 0x10000000, LENGTH = 2048K
|
||||
RAM : ORIGIN = 0x20000000, LENGTH = 512K
|
||||
SRAM4 : ORIGIN = 0x20080000, LENGTH = 4K
|
||||
SRAM5 : ORIGIN = 0x20081000, LENGTH = 4K
|
||||
}
|
||||
|
||||
PROVIDE(_stext = ORIGIN(FLASH));
|
||||
PROVIDE(_stack_start = ORIGIN(RAM) + LENGTH(RAM));
|
||||
PROVIDE(_max_hart_id = 0);
|
||||
PROVIDE(_hart_stack_size = 2K);
|
||||
PROVIDE(_heap_size = 0);
|
||||
|
||||
PROVIDE(InstructionMisaligned = ExceptionHandler);
|
||||
PROVIDE(InstructionFault = ExceptionHandler);
|
||||
PROVIDE(IllegalInstruction = ExceptionHandler);
|
||||
PROVIDE(Breakpoint = ExceptionHandler);
|
||||
PROVIDE(LoadMisaligned = ExceptionHandler);
|
||||
PROVIDE(LoadFault = ExceptionHandler);
|
||||
PROVIDE(StoreMisaligned = ExceptionHandler);
|
||||
PROVIDE(StoreFault = ExceptionHandler);
|
||||
PROVIDE(UserEnvCall = ExceptionHandler);
|
||||
PROVIDE(SupervisorEnvCall = ExceptionHandler);
|
||||
PROVIDE(MachineEnvCall = ExceptionHandler);
|
||||
PROVIDE(InstructionPageFault = ExceptionHandler);
|
||||
PROVIDE(LoadPageFault = ExceptionHandler);
|
||||
PROVIDE(StorePageFault = ExceptionHandler);
|
||||
|
||||
PROVIDE(SupervisorSoft = DefaultHandler);
|
||||
PROVIDE(MachineSoft = DefaultHandler);
|
||||
PROVIDE(SupervisorTimer = DefaultHandler);
|
||||
PROVIDE(MachineTimer = DefaultHandler);
|
||||
PROVIDE(SupervisorExternal = DefaultHandler);
|
||||
PROVIDE(MachineExternal = DefaultHandler);
|
||||
|
||||
PROVIDE(DefaultHandler = DefaultInterruptHandler);
|
||||
PROVIDE(ExceptionHandler = DefaultExceptionHandler);
|
||||
|
||||
PROVIDE(__pre_init = default_pre_init);
|
||||
PROVIDE(_setup_interrupts = default_setup_interrupts);
|
||||
PROVIDE(_mp_hook = default_mp_hook);
|
||||
PROVIDE(_start_trap = default_start_trap);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text.dummy (NOLOAD) :
|
||||
{
|
||||
. = ABSOLUTE(_stext);
|
||||
} > FLASH
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
//! Implementation module
|
||||
//!
|
||||
//! **File:** `board.rs`
|
||||
//! **Author:** Kevin Thomas
|
||||
//! **Date:** 2025
|
||||
//!
|
||||
//! MIT License
|
||||
//!
|
||||
//! Copyright (c) 2025 Kevin Thomas
|
||||
//!
|
||||
//! Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
//! of this software and associated documentation files (the "Software"), to deal
|
||||
//! in the Software without restriction, including without limitation the rights
|
||||
//! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
//! copies of the Software, and to permit persons to whom the Software is
|
||||
//! furnished to do so, subject to the following conditions:
|
||||
//!
|
||||
//! The above copyright notice and this permission notice shall be included in
|
||||
//! all copies or substantial portions of the Software.
|
||||
//!
|
||||
//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
//! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
//! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
//! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
//! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
//! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
//! SOFTWARE.
|
||||
|
||||
// Flash driver pure-logic functions and constants
|
||||
use flash_lib::flash;
|
||||
// Rate extension trait for .Hz() baud rate construction
|
||||
use fugit::RateExtU32;
|
||||
// Clock trait for accessing system clock frequency
|
||||
use hal::Clock;
|
||||
// GPIO pin types and function selectors
|
||||
use hal::gpio::{FunctionNull, FunctionUart, Pin, PullDown, PullNone};
|
||||
// ROM data flash functions for low-level flash operations
|
||||
use hal::rom_data;
|
||||
// UART configuration and peripheral types
|
||||
use hal::uart::{DataBits, Enabled, StopBits, UartConfig, UartPeripheral};
|
||||
// Alias our HAL crate
|
||||
#[cfg(rp2350)]
|
||||
// Import rp235x_hal as hal
|
||||
use rp235x_hal as hal;
|
||||
#[cfg(rp2040)]
|
||||
// Import rp2040_hal as hal
|
||||
use rp2040_hal as hal;
|
||||
|
||||
/// External crystal frequency in Hz (12 MHz).
|
||||
pub(crate) const XTAL_FREQ_HZ: u32 = 12_000_000u32;
|
||||
|
||||
/// UART baud rate in bits per second.
|
||||
pub(crate) const UART_BAUD: u32 = 115_200;
|
||||
|
||||
/// Type alias for the configured TX pin (GPIO 0, UART function, no pull).
|
||||
pub(crate) type TxPin = Pin<hal::gpio::bank0::Gpio0, FunctionUart, PullNone>;
|
||||
|
||||
/// Type alias for the configured RX pin (GPIO 1, UART function, no pull).
|
||||
pub(crate) type RxPin = Pin<hal::gpio::bank0::Gpio1, FunctionUart, PullNone>;
|
||||
|
||||
/// Type alias for the default TX pin state from `Pins::new()`.
|
||||
pub(crate) type TxPinDefault = Pin<hal::gpio::bank0::Gpio0, FunctionNull, PullDown>;
|
||||
|
||||
/// Type alias for the default RX pin state from `Pins::new()`.
|
||||
pub(crate) type RxPinDefault = Pin<hal::gpio::bank0::Gpio1, FunctionNull, PullDown>;
|
||||
|
||||
/// Type alias for the fully-enabled UART0 peripheral with TX/RX p.
|
||||
pub(crate) type EnabledUart = UartPeripheral<Enabled, hal::pac::UART0, (TxPin, RxPin)>;
|
||||
|
||||
/// Initialise system clocks and PLLs from the external 12 MHz crystal.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `xosc` - XOSC peripheral singleton.
|
||||
/// * `clocks` - CLOCKS peripheral singleton.
|
||||
/// * `pll_sys` - PLL_SYS peripheral singleton.
|
||||
/// * `pll_usb` - PLL_USB peripheral singleton.
|
||||
/// * `resets` - Mutable reference to the RESETS peripheral.
|
||||
/// * `watchdog` - Mutable reference to the watchdog timer.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Configured clocks manager.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if clock initialisation fails.
|
||||
pub(crate) fn init_clocks(
|
||||
xosc: hal::pac::XOSC, clocks: hal::pac::CLOCKS, pll_sys: hal::pac::PLL_SYS, pll_usb: hal::pac::PLL_USB,
|
||||
resets: &mut hal::pac::RESETS, watchdog: &mut hal::Watchdog,
|
||||
) -> hal::clocks::ClocksManager {
|
||||
hal::clocks::init_clocks_and_plls(XTAL_FREQ_HZ, xosc, clocks, pll_sys, pll_usb, resets, watchdog).unwrap()
|
||||
}
|
||||
|
||||
/// Unlock the GPIO bank and return the pin set.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `io_bank0` - IO_BANK0 peripheral singleton.
|
||||
/// * `pads_bank0` - PADS_BANK0 peripheral singleton.
|
||||
/// * `sio` - SIO peripheral singleton.
|
||||
/// * `resets` - Mutable reference to the RESETS peripheral.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// GPIO pin set for the entire bank.
|
||||
pub(crate) fn init_pins(
|
||||
io: hal::pac::IO_BANK0, pads: hal::pac::PADS_BANK0, sio: hal::pac::SIO, rst: &mut hal::pac::RESETS
|
||||
) -> hal::gpio::Pins {
|
||||
hal::gpio::Pins::new(io, pads, hal::Sio::new(sio).gpio_bank0, rst)
|
||||
}
|
||||
|
||||
/// Initialise UART0 for serial output (stdio equivalent).
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `uart0` - PAC UART0 peripheral singleton.
|
||||
/// * `tx_pin` - GPIO pin to use as UART0 TX (GPIO 0).
|
||||
/// * `rx_pin` - GPIO pin to use as UART0 RX (GPIO 1).
|
||||
/// * `resets` - Mutable reference to the RESETS peripheral.
|
||||
/// * `clocks` - Reference to the initialised clock configuration.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Enabled UART0 peripheral ready for blocking writes.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the HAL cannot achieve the requested baud rate.
|
||||
pub(crate) fn init_uart(
|
||||
uart0: hal::pac::UART0, tx: TxPinDefault, rx: RxPinDefault, rst: &mut hal::pac::RESETS, c: &hal::clocks::ClocksManager
|
||||
) -> EnabledUart {
|
||||
let pins = (tx.reconfigure::<FunctionUart, PullNone>(), rx.reconfigure::<FunctionUart, PullNone>());
|
||||
let cfg = UartConfig::new(UART_BAUD.Hz(), DataBits::Eight, None, StopBits::One);
|
||||
UartPeripheral::new(uart0, pins, rst).enable(cfg, c.peripheral_clock.freq()).unwrap()
|
||||
}
|
||||
|
||||
/// Transition flash out of XIP mode and erase the target sector.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Must be called with interrupts disabled and no other flash access active.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `flash_offset` - The `flash_offset` parameter.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `flash_offset` - The `flash_offset` parameter.
|
||||
unsafe fn flash_prepare_sector(flash_offset: u32) {
|
||||
unsafe {
|
||||
rom_data::connect_internal_flash(); rom_data::flash_exit_xip();
|
||||
rom_data::flash_range_erase(flash_offset, flash::FLASH_SECTOR_SIZE as usize, flash::FLASH_SECTOR_SIZE, 0x20);
|
||||
}
|
||||
}
|
||||
|
||||
/// Program data into the erased sector and restore XIP mode.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Must be called with interrupts disabled and no other flash access active.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `flash_offset` - The `flash_offset` parameter.
|
||||
/// * `data` - Data to send/write.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `flash_offset` - The `flash_offset` parameter.
|
||||
/// * `data` - Data to send/write.
|
||||
unsafe fn flash_program_and_restore(flash_offset: u32, data: &[u8]) {
|
||||
unsafe {
|
||||
rom_data::flash_range_program(flash_offset, data.as_ptr(), data.len());
|
||||
rom_data::flash_flush_cache(); rom_data::flash_enter_cmd_xip();
|
||||
}
|
||||
}
|
||||
|
||||
/// Erase one 4096-byte sector and write data to on-chip flash.
|
||||
///
|
||||
/// Disables interrupts, transitions the flash device out of XIP mode,
|
||||
/// erases the sector at `flash_offset`, programs `data` into it, flushes
|
||||
/// the cache, re-enters XIP mode, and restores interrupts. This mirrors
|
||||
/// the C demo's `flash_driver_write()`.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `flash_offset` - Byte offset from the start of flash (must be sector-aligned).
|
||||
/// * `data` - Data buffer to write (length must be a multiple of 256).
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Caller must ensure no other core or DMA is accessing flash/XIP during
|
||||
/// this operation.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `flash_offset` - The `flash_offset` parameter.
|
||||
/// * `data` - Data to send/write.
|
||||
pub(crate) fn flash_write(flash_offset: u32, data: &[u8]) {
|
||||
cortex_m::interrupt::free(|_| unsafe {
|
||||
flash_prepare_sector(flash_offset);
|
||||
flash_program_and_restore(flash_offset, data);
|
||||
});
|
||||
}
|
||||
|
||||
/// Read bytes from on-chip flash via the XIP memory map.
|
||||
///
|
||||
/// Flash is memory-mapped starting at XIP_BASE (0x10000000). This
|
||||
/// function copies `out.len()` bytes from the XIP address corresponding
|
||||
/// to `flash_offset` into `out`, matching the C demo's
|
||||
/// `flash_driver_read()`.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `flash_offset` - Byte offset from the start of flash.
|
||||
/// * `out` - Destination buffer.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `flash_offset` - The `flash_offset` parameter.
|
||||
/// * `out` - The `out` parameter.
|
||||
pub(crate) fn flash_read(flash_offset: u32, out: &mut [u8]) {
|
||||
let addr = (flash::XIP_BASE + flash_offset) as *const u8;
|
||||
for (i, byte) in out.iter_mut().enumerate() { *byte = unsafe { core::ptr::read_volatile(addr.add(i)) }; }
|
||||
}
|
||||
|
||||
/// Initialise all peripherals and run the flash demo.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `pac` - PAC Peripherals singleton (consumed).
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A value of type `!`.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `pac` - The `pac` parameter.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A value of type `!`.
|
||||
pub(crate) fn run(mut p: hal::pac::Peripherals) -> ! {
|
||||
let c = init_clocks(p.XOSC, p.CLOCKS, p.PLL_SYS, p.PLL_USB, &mut p.RESETS, &mut hal::Watchdog::new(p.WATCHDOG));
|
||||
let pins = init_pins(p.IO_BANK0, p.PADS_BANK0, p.SIO, &mut p.RESETS);
|
||||
let uart = init_uart(p.UART0, pins.gpio0, pins.gpio1, &mut p.RESETS, &c);
|
||||
flash_demo(&uart);
|
||||
loop { cortex_m::asm::wfe(); }
|
||||
}
|
||||
|
||||
/// Execute the flash write / read-back / report sequence.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `uart` - Reference to the enabled UART peripheral for serial output.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `uart` - The `uart` parameter.
|
||||
fn flash_demo(uart: &EnabledUart) {
|
||||
let mut write_buf = [0u8; flash::FLASH_WRITE_LEN]; flash::prepare_write_buf(&mut write_buf);
|
||||
flash_write(flash::FLASH_TARGET_OFFSET, &write_buf);
|
||||
let mut read_buf = [0u8; flash::FLASH_WRITE_LEN]; flash_read(flash::FLASH_TARGET_OFFSET, &mut read_buf);
|
||||
report_readback(uart, &read_buf);
|
||||
}
|
||||
|
||||
/// Format and print the flash read-back result over UART.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `uart` - Reference to the enabled UART peripheral for serial output.
|
||||
/// * `read_buf` - Buffer containing the data read back from flash.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `uart` - The `uart` parameter.
|
||||
/// * `read_buf` - The `read_buf` parameter.
|
||||
fn report_readback(uart: &EnabledUart, read_buf: &[u8]) {
|
||||
let mut out = [0u8; 128]; let n = flash::format_readback(&mut out, read_buf);
|
||||
uart.write_full_blocking(&out[..n]);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,301 @@
|
||||
//! Implementation module
|
||||
//!
|
||||
//! **File:** `flash.rs`
|
||||
//! **Author:** Kevin Thomas
|
||||
//! **Date:** 2025
|
||||
//!
|
||||
//! MIT License
|
||||
//!
|
||||
//! Copyright (c) 2025 Kevin Thomas
|
||||
//!
|
||||
//! Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
//! of this software and associated documentation files (the "Software"), to deal
|
||||
//! in the Software without restriction, including without limitation the rights
|
||||
//! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
//! copies of the Software, and to permit persons to whom the Software is
|
||||
//! furnished to do so, subject to the following conditions:
|
||||
//!
|
||||
//! The above copyright notice and this permission notice shall be included in
|
||||
//! all copies or substantial portions of the Software.
|
||||
//!
|
||||
//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
//! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
//! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
//! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
//! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
//! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
//! SOFTWARE.
|
||||
|
||||
/// Total on-chip flash size in bytes (4 MB).
|
||||
pub const FLASH_SIZE_BYTES: u32 = 4 * 1024 * 1024;
|
||||
|
||||
/// Flash sector size in bytes (4096).
|
||||
pub const FLASH_SECTOR_SIZE: u32 = 4096;
|
||||
|
||||
/// Flash page size in bytes (256).
|
||||
pub const FLASH_PAGE_SIZE: u32 = 256;
|
||||
|
||||
/// Flash target offset: last sector of flash.
|
||||
pub const FLASH_TARGET_OFFSET: u32 = FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE;
|
||||
|
||||
/// Write buffer length matching the C demo (one page = 256 bytes).
|
||||
pub const FLASH_WRITE_LEN: usize = FLASH_PAGE_SIZE as usize;
|
||||
|
||||
/// XIP base address where flash is memory-mapped.
|
||||
pub const XIP_BASE: u32 = 0x1000_0000;
|
||||
|
||||
/// Demo string written to flash, matching the C demo exactly.
|
||||
pub const DEMO_MSG: &[u8] = b"Embedded Hacking flash driver demo";
|
||||
|
||||
/// Fill the entire buffer with 0xFF (erased flash state).
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `buf` - The `buf` parameter.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `buf` - The `buf` parameter.
|
||||
#[inline]
|
||||
fn fill_erased(buf: &mut [u8]) {
|
||||
for b in buf.iter_mut() { *b = 0xFF; }
|
||||
}
|
||||
|
||||
/// Copy the demo string and NUL terminator into `buf`, returning meaningful length.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `buf` - The `buf` parameter.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A value of type `usize`.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `buf` - The `buf` parameter.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A value of type `usize`.
|
||||
#[inline]
|
||||
fn copy_demo_msg(buf: &mut [u8]) -> usize {
|
||||
let (n, len) = ((DEMO_MSG.len() + 1).min(buf.len()), DEMO_MSG.len());
|
||||
let copy_len = len.min(n); buf[..copy_len].copy_from_slice(&DEMO_MSG[..copy_len]);
|
||||
if copy_len < n { buf[copy_len] = 0x00; }
|
||||
n
|
||||
}
|
||||
|
||||
/// Prepare a write buffer with 0xFF fill and the demo string at the start.
|
||||
///
|
||||
/// Mirrors the C demo's `_prepare_write_buf()` function. The buffer is
|
||||
/// filled with 0xFF (erased flash state), then the demo string including
|
||||
/// its NUL terminator is copied to the beginning.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `buf` - Output buffer (should be `FLASH_WRITE_LEN` bytes).
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Number of meaningful bytes (string length + NUL terminator).
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `buf` - The `buf` parameter.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A value of type `usize`.
|
||||
#[inline]
|
||||
pub fn prepare_write_buf(buf: &mut [u8]) -> usize {
|
||||
fill_erased(buf); copy_demo_msg(buf)
|
||||
}
|
||||
|
||||
/// Format the "Flash readback: <string>\r\n" message into `buf`.
|
||||
///
|
||||
/// Reads from `read_data` up to the first NUL byte (or end of slice)
|
||||
/// and formats the output message matching the C demo's printf.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `buf` - Output buffer (should be >= 64 bytes).
|
||||
/// * `read_data` - Data read back from flash.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Number of bytes written to `buf`.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `buf` - The `buf` parameter.
|
||||
/// * `read_data` - The `read_data` parameter.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A value of type `usize`.
|
||||
#[inline]
|
||||
pub fn format_readback(buf: &mut [u8], read_data: &[u8]) -> usize {
|
||||
let mut pos = copy_slice(buf, 0, b"Flash readback: ");
|
||||
pos += copy_c_string(&mut buf[pos..], read_data);
|
||||
pos += copy_slice(buf, pos, b"\r\n"); pos
|
||||
}
|
||||
|
||||
/// Copy a byte slice into `buf` at the given offset, returning bytes written.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `buf` - The `buf` parameter.
|
||||
/// * `offset` - The `offset` parameter.
|
||||
/// * `src` - The `src` parameter.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A value of type `usize`.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `buf` - The `buf` parameter.
|
||||
/// * `offset` - The `offset` parameter.
|
||||
/// * `src` - The `src` parameter.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A value of type `usize`.
|
||||
#[inline]
|
||||
fn copy_slice(buf: &mut [u8], offset: usize, src: &[u8]) -> usize {
|
||||
let n = src.len().min(buf.len().saturating_sub(offset));
|
||||
buf[offset..offset + n].copy_from_slice(&src[..n]); n
|
||||
}
|
||||
|
||||
/// Copy bytes from `data` up to the first NUL into `buf`.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `buf` - The `buf` parameter.
|
||||
/// * `data` - Data to send/write.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A value of type `usize`.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `buf` - The `buf` parameter.
|
||||
/// * `data` - Data to send/write.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A value of type `usize`.
|
||||
#[inline]
|
||||
fn copy_c_string(buf: &mut [u8], data: &[u8]) -> usize {
|
||||
let n = data.iter().position(|&b| b == 0).unwrap_or(data.len()).min(buf.len());
|
||||
buf[..n].copy_from_slice(&data[..n]); n
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
// Import all parent module items
|
||||
use super::*;
|
||||
|
||||
/// Executes the flash size is 4mb operation.
|
||||
#[test]
|
||||
fn flash_size_is_4mb() {
|
||||
assert_eq!(FLASH_SIZE_BYTES, 4 * 1024 * 1024);
|
||||
}
|
||||
|
||||
/// Executes the sector size is 4096 operation.
|
||||
#[test]
|
||||
fn sector_size_is_4096() {
|
||||
assert_eq!(FLASH_SECTOR_SIZE, 4096);
|
||||
}
|
||||
|
||||
/// Executes the page size is 256 operation.
|
||||
#[test]
|
||||
fn page_size_is_256() {
|
||||
assert_eq!(FLASH_PAGE_SIZE, 256);
|
||||
}
|
||||
|
||||
/// Executes the target offset is last sector operation.
|
||||
#[test]
|
||||
fn target_offset_is_last_sector() {
|
||||
assert_eq!(FLASH_TARGET_OFFSET, FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE);
|
||||
}
|
||||
|
||||
/// Executes the write len matches page size operation.
|
||||
#[test]
|
||||
fn write_len_matches_page_size() {
|
||||
assert_eq!(FLASH_WRITE_LEN, 256);
|
||||
}
|
||||
|
||||
/// Executes the xip base address operation.
|
||||
#[test]
|
||||
fn xip_base_address() {
|
||||
assert_eq!(XIP_BASE, 0x1000_0000);
|
||||
}
|
||||
|
||||
/// Executes the prepare write buf fills 0xff operation.
|
||||
#[test]
|
||||
fn prepare_write_buf_fills_0xff() {
|
||||
let mut buf = [0u8; FLASH_WRITE_LEN];
|
||||
prepare_write_buf(&mut buf);
|
||||
for &b in &buf[(DEMO_MSG.len() + 1)..] {
|
||||
assert_eq!(b, 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
/// Executes the prepare write buf has demo string operation.
|
||||
#[test]
|
||||
fn prepare_write_buf_has_demo_string() {
|
||||
let mut buf = [0u8; FLASH_WRITE_LEN];
|
||||
prepare_write_buf(&mut buf);
|
||||
assert_eq!(&buf[..DEMO_MSG.len()], DEMO_MSG);
|
||||
}
|
||||
|
||||
/// Executes the prepare write buf has nul terminator operation.
|
||||
#[test]
|
||||
fn prepare_write_buf_has_nul_terminator() {
|
||||
let mut buf = [0u8; FLASH_WRITE_LEN];
|
||||
prepare_write_buf(&mut buf);
|
||||
assert_eq!(buf[DEMO_MSG.len()], 0x00);
|
||||
}
|
||||
|
||||
/// Executes the format readback matches c output operation.
|
||||
#[test]
|
||||
fn format_readback_matches_c_output() {
|
||||
let mut read_data = [0xFFu8; FLASH_WRITE_LEN];
|
||||
let msg = b"Embedded Hacking flash driver demo";
|
||||
read_data[..msg.len()].copy_from_slice(msg);
|
||||
read_data[msg.len()] = 0x00;
|
||||
let mut buf = [0u8; 128];
|
||||
let n = format_readback(&mut buf, &read_data);
|
||||
assert_eq!(
|
||||
&buf[..n],
|
||||
b"Flash readback: Embedded Hacking flash driver demo\r\n"
|
||||
);
|
||||
}
|
||||
|
||||
/// Executes the format readback empty string operation.
|
||||
#[test]
|
||||
fn format_readback_empty_string() {
|
||||
let read_data = [0u8; 8];
|
||||
let mut buf = [0u8; 64];
|
||||
let n = format_readback(&mut buf, &read_data);
|
||||
assert_eq!(&buf[..n], b"Flash readback: \r\n");
|
||||
}
|
||||
|
||||
/// Executes the format readback no nul operation.
|
||||
#[test]
|
||||
fn format_readback_no_nul() {
|
||||
let read_data = [b'A'; 8];
|
||||
let mut buf = [0u8; 64];
|
||||
let n = format_readback(&mut buf, &read_data);
|
||||
assert_eq!(&buf[..n], b"Flash readback: AAAAAAAA\r\n");
|
||||
}
|
||||
|
||||
/// Executes the demo msg matches c string operation.
|
||||
#[test]
|
||||
fn demo_msg_matches_c_string() {
|
||||
assert_eq!(DEMO_MSG, b"Embedded Hacking flash driver demo");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
//! Driver crate
|
||||
|
||||
#![deny(missing_docs)]
|
||||
#![deny(clippy::missing_docs_in_private_items)]
|
||||
#![cfg_attr(not(test), no_std)]
|
||||
pub mod flash;
|
||||
@@ -0,0 +1,102 @@
|
||||
//! Driver crate
|
||||
|
||||
#![deny(missing_docs)]
|
||||
#![deny(clippy::missing_docs_in_private_items)]
|
||||
|
||||
//! Implementation module
|
||||
//!
|
||||
//! **File:** `main.rs`
|
||||
//! **Author:** Kevin Thomas
|
||||
//! **Date:** 2025
|
||||
//!
|
||||
//! MIT License
|
||||
//!
|
||||
//! Copyright (c) 2025 Kevin Thomas
|
||||
//!
|
||||
//! Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
//! of this software and associated documentation files (the "Software"), to deal
|
||||
//! in the Software without restriction, including without limitation the rights
|
||||
//! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
//! copies of the Software, and to permit persons to whom the Software is
|
||||
//! furnished to do so, subject to the following conditions:
|
||||
//!
|
||||
//! The above copyright notice and this permission notice shall be included in
|
||||
//! all copies or substantial portions of the Software.
|
||||
//!
|
||||
//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
//! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
//! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
//! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
//! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
//! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
//! SOFTWARE.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
// Board-level helpers: constants, type aliases, and init functions
|
||||
mod board;
|
||||
// Flash driver module — suppress warnings for unused public API functions
|
||||
|
||||
// Debugging output over RTT
|
||||
use defmt_rtt as _;
|
||||
// Panic handler for RISC-V targets
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
// Import panic_halt as _
|
||||
use panic_halt as _;
|
||||
// Panic handler for ARM targets
|
||||
#[cfg(target_arch = "arm")]
|
||||
// Import panic_probe as _
|
||||
use panic_probe as _;
|
||||
// HAL entry-point macro
|
||||
use hal::entry;
|
||||
// Alias our HAL crate
|
||||
#[cfg(rp2350)]
|
||||
// Import rp235x_hal as hal
|
||||
use rp235x_hal as hal;
|
||||
#[cfg(rp2040)]
|
||||
// Import rp2040_hal as hal
|
||||
use rp2040_hal as hal;
|
||||
|
||||
/// Second-stage boot loader for RP2040
|
||||
#[unsafe(link_section = ".boot2")]
|
||||
#[used]
|
||||
#[cfg(rp2040)]
|
||||
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
|
||||
|
||||
/// Boot metadata for the RP2350 Boot ROM
|
||||
#[unsafe(link_section = ".start_block")]
|
||||
#[used]
|
||||
#[cfg(rp2350)]
|
||||
pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();
|
||||
|
||||
/// Application entry point for the on-chip flash demo.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A value of type `!`.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A value of type `!`.
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
board::run(hal::pac::Peripherals::take().unwrap())
|
||||
}
|
||||
|
||||
/// Picotool binary info metadata
|
||||
#[unsafe(link_section = ".bi_entries")]
|
||||
#[used]
|
||||
pub static PICOTOOL_ENTRIES: [hal::binary_info::EntryAddr; 5] = [
|
||||
hal::binary_info::rp_cargo_bin_name!(),
|
||||
hal::binary_info::rp_cargo_version!(),
|
||||
hal::binary_info::rp_program_description!(c"On-chip Flash Demo"),
|
||||
hal::binary_info::rp_cargo_homepage_url!(),
|
||||
hal::binary_info::rp_program_build_attribute!(),
|
||||
];
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
// Import all parent module items
|
||||
use super::*;
|
||||
}
|
||||
Reference in New Issue
Block a user