Compare commits
12 Commits
zynq7000-h
...
add-sdio-s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
337b00a442
|
||
|
|
848e2113a0 | ||
|
|
82296ecc79 | ||
|
|
3533faa7cc | ||
|
|
5235eb422d | ||
|
|
0d227e7f68 | ||
| 0aa86cd085 | |||
|
|
a8339153c4 | ||
| b394da69f3 | |||
|
|
064f99ddea | ||
| 2e1efd154d | |||
|
|
c53b6ae2bb |
2
justfile
2
justfile
@@ -19,7 +19,7 @@ clean target:
|
||||
cd {{target}} && cargo clean
|
||||
|
||||
fmt target:
|
||||
cd {{target}} && cargo +stable fmt --all -- --check
|
||||
cd {{target}} && cargo +stable fmt
|
||||
|
||||
clippy target:
|
||||
cd {{target}} && cargo clippy -- -D warnings
|
||||
|
||||
188
tools/Cargo.lock
generated
188
tools/Cargo.lock
generated
@@ -2,6 +2,19 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aarch32-cpu"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5db6700cf01549520abec199376115e1ceb6fde1d1de30064f0f230be8a0c305"
|
||||
dependencies = [
|
||||
"arbitrary-int 2.0.0",
|
||||
"arm-targets",
|
||||
"bitbybit",
|
||||
"num_enum",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
@@ -75,9 +88,9 @@ checksum = "c858caffa49edfc4ecc45a4bec37abd3e88041a2903816f10f990b7b41abc281"
|
||||
|
||||
[[package]]
|
||||
name = "arm-targets"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3371884971a96d71d8bd4e781188a7d327d7e5e455d07ef4c352922c66695e9e"
|
||||
checksum = "8d29a37f252452446b67d5e50dee82a6ce12781218b915244bb6507c10b72812"
|
||||
|
||||
[[package]]
|
||||
name = "bitbybit"
|
||||
@@ -101,9 +114,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.48"
|
||||
version = "4.5.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae"
|
||||
checksum = "0c2cfd7bf8a6017ddaa4e32ffe7403d547790db06bd171c1c53926faab501623"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -111,9 +124,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.48"
|
||||
version = "4.5.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9"
|
||||
checksum = "0a4c05b9e80c5ccd3a7ef080ad7b6ba7d6fc00a985b8b157197075677c82c7a0"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -123,9 +136,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.47"
|
||||
version = "4.5.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c"
|
||||
checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
@@ -135,9 +148,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.5"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
|
||||
checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
@@ -147,27 +160,13 @@ checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "2.2.0"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
|
||||
checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cortex-ar"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4ea2a354642e242870bc43b57a517359b0be6e96d302b2811cd0644c979c54e"
|
||||
dependencies = [
|
||||
"arbitrary-int 2.0.0",
|
||||
"arm-targets",
|
||||
"bitbybit",
|
||||
"num_enum",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "critical-section"
|
||||
version = "1.2.0"
|
||||
@@ -176,9 +175,9 @@ checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.5.4"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071"
|
||||
checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
]
|
||||
@@ -213,9 +212,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.1"
|
||||
version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
@@ -223,17 +222,11 @@ version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.176"
|
||||
version = "0.2.177"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174"
|
||||
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
@@ -263,9 +256,9 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||
|
||||
[[package]]
|
||||
name = "num_enum"
|
||||
version = "0.7.4"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a"
|
||||
checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c"
|
||||
dependencies = [
|
||||
"num_enum_derive",
|
||||
"rustversion",
|
||||
@@ -273,9 +266,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num_enum_derive"
|
||||
version = "0.7.4"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d"
|
||||
checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -303,9 +296,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
version = "1.70.1"
|
||||
version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
||||
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
@@ -343,9 +336,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.101"
|
||||
version = "1.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
|
||||
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -361,9 +354,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.11.3"
|
||||
version = "1.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b5288124840bee7b386bc413c487869b360b2b4ec421ea56425128692f2a82c"
|
||||
checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -373,9 +366,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.11"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "833eb9ce86d40ef33cb1306d8accf7bc8ec2bfea4355cbdebb3df68b40925cad"
|
||||
checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -384,9 +377,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.6"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
|
||||
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
@@ -425,14 +418,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "simple_logger"
|
||||
version = "5.0.0"
|
||||
version = "5.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8c5dfa5e08767553704aa0ffd9d9794d527103c736aba9854773851fd7497eb"
|
||||
checksum = "291bee647ce7310b0ea721bfd7e0525517b4468eb7c7e15eb8bd774343179702"
|
||||
dependencies = [
|
||||
"colored",
|
||||
"log",
|
||||
"time",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -449,9 +442,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.106"
|
||||
version = "2.0.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
|
||||
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -513,9 +506,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.19"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
|
||||
checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
@@ -529,15 +522,6 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
@@ -557,18 +541,12 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -604,12 +582,6 @@ dependencies = [
|
||||
"windows_x86_64_msvc 0.53.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
@@ -622,12 +594,6 @@ version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
@@ -640,12 +606,6 @@ version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
@@ -670,12 +630,6 @@ version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
@@ -688,12 +642,6 @@ version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
@@ -706,12 +654,6 @@ version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
@@ -724,12 +666,6 @@ version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
@@ -744,7 +680,7 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
|
||||
|
||||
[[package]]
|
||||
name = "zynq7000"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"arbitrary-int 2.0.0",
|
||||
"bitbybit",
|
||||
@@ -766,9 +702,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zynq7000-mmu"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"cortex-ar",
|
||||
"aarch32-cpu",
|
||||
"arm-targets",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
@@ -788,9 +725,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zynq7000-rt"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"aarch32-cpu",
|
||||
"arbitrary-int 2.0.0",
|
||||
"cortex-ar",
|
||||
"arm-targets",
|
||||
"zynq7000-mmu",
|
||||
]
|
||||
|
||||
@@ -11,7 +11,7 @@ keywords = ["no-std", "arm", "cortex-a", "amd", "zynq7000"]
|
||||
categories = ["embedded", "no-std", "hardware-support"]
|
||||
|
||||
[dependencies]
|
||||
cortex-ar = { version = "0.3", features = ["critical-section-single-core"] }
|
||||
aarch32-cpu = { version = "0.1", features = ["critical-section-single-core"] }
|
||||
zynq7000-rt = { path = "../../zynq7000-rt" }
|
||||
zynq7000 = { path = "../../zynq7000" }
|
||||
zynq7000-hal = { path = "../../zynq7000-hal" }
|
||||
@@ -25,7 +25,7 @@ embedded-hal = "1"
|
||||
fugit = "0.3"
|
||||
log = "0.4"
|
||||
|
||||
embassy-executor = { git = "https://github.com/embassy-rs/embassy.git", features = [
|
||||
embassy-executor = { version = "0.9", features = [
|
||||
"arch-cortex-ar",
|
||||
"executor-thread",
|
||||
]}
|
||||
|
||||
@@ -7,6 +7,7 @@ MEMORY
|
||||
UNCACHED(rx): ORIGIN = 0x4000000, LENGTH = 1M
|
||||
}
|
||||
|
||||
REGION_ALIAS("VECTORS", CODE);
|
||||
REGION_ALIAS("DATA", CODE);
|
||||
|
||||
SECTIONS
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use aarch32_cpu::asm::nop;
|
||||
use core::panic::PanicInfo;
|
||||
use cortex_ar::asm::nop;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Delay, Duration, Ticker};
|
||||
use embedded_hal::{delay::DelayNs, digital::StatefulOutputPin};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use aarch32_cpu::asm::nop;
|
||||
use core::panic::PanicInfo;
|
||||
use cortex_ar::asm::nop;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Duration, Ticker};
|
||||
use embedded_hal::digital::StatefulOutputPin;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use aarch32_cpu::asm::nop;
|
||||
use core::panic::PanicInfo;
|
||||
use cortex_ar::asm::nop;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Duration, Ticker};
|
||||
use embedded_hal::digital::StatefulOutputPin;
|
||||
@@ -70,6 +70,7 @@ async fn main(spawner: Spawner) -> ! {
|
||||
uart.write_all(b"-- Zynq 7000 Logging example --\n\r")
|
||||
.unwrap();
|
||||
uart.flush().unwrap();
|
||||
|
||||
let (tx, _rx) = uart.split();
|
||||
let mut logger = TxAsync::new(tx);
|
||||
|
||||
@@ -79,7 +80,7 @@ async fn main(spawner: Spawner) -> ! {
|
||||
info!("Boot mode: {:?}", boot_mode);
|
||||
|
||||
let led = Output::new_for_mio(mio_pins.mio7, PinState::Low);
|
||||
spawner.spawn(led_task(led).unwrap());
|
||||
spawner.spawn(led_task(led)).unwrap();
|
||||
let mut log_buf: [u8; 2048] = [0; 2048];
|
||||
let frame_queue = zynq7000_hal::log::rb::get_frame_queue();
|
||||
loop {
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use aarch32_cpu::asm::nop;
|
||||
use core::panic::PanicInfo;
|
||||
use cortex_ar::asm::nop;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Duration, Ticker};
|
||||
use embedded_hal::{digital::StatefulOutputPin, pwm::SetDutyCycle};
|
||||
@@ -80,8 +80,7 @@ async fn main(_spawner: Spawner) -> ! {
|
||||
(mio_pins.mio48, mio_pins.mio49),
|
||||
)
|
||||
.unwrap();
|
||||
uart.write_all(b"-- Zynq 7000 Embassy Hello World --\n\r")
|
||||
.unwrap();
|
||||
uart.write_all(b"-- Zynq 7000 PWM example--\n\r").unwrap();
|
||||
// Safety: We are not multi-threaded yet.
|
||||
unsafe {
|
||||
zynq7000_hal::log::uart_blocking::init_unsafe_single_core(
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use aarch32_cpu::asm::nop;
|
||||
use core::panic::PanicInfo;
|
||||
use cortex_ar::asm::nop;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Duration, Ticker};
|
||||
use embedded_hal::digital::StatefulOutputPin;
|
||||
|
||||
@@ -9,7 +9,7 @@ repository = "https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
cortex-ar = "0.3"
|
||||
aarch32-cpu = { version = "0.1" }
|
||||
zynq7000-rt = { path = "../../zynq7000-rt" }
|
||||
zynq7000 = { path = "../../zynq7000" }
|
||||
zynq7000-hal = { path = "../../zynq7000-hal" }
|
||||
|
||||
@@ -7,6 +7,7 @@ MEMORY
|
||||
UNCACHED(rx): ORIGIN = 0x4000000, LENGTH = 1M
|
||||
}
|
||||
|
||||
REGION_ALIAS("VECTORS", CODE);
|
||||
REGION_ALIAS("DATA", CODE);
|
||||
|
||||
SECTIONS
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use aarch32_cpu::asm::nop;
|
||||
use core::panic::PanicInfo;
|
||||
use cortex_ar::asm::nop;
|
||||
use embedded_hal::{delay::DelayNs, digital::StatefulOutputPin};
|
||||
use zynq7000::Peripherals;
|
||||
use zynq7000_hal::{
|
||||
@@ -42,10 +42,10 @@ pub extern "C" fn boot_core(cpu_id: u32) -> ! {
|
||||
|
||||
#[unsafe(export_name = "main")]
|
||||
pub fn main() -> ! {
|
||||
l2_cache::init_with_defaults(&mut unsafe { zynq7000::l2_cache::L2Cache::new_mmio_fixed() });
|
||||
l2_cache::init_with_defaults(&mut unsafe { zynq7000::l2_cache::Registers::new_mmio_fixed() });
|
||||
match LIB {
|
||||
Lib::Pac => {
|
||||
let mut gpio = unsafe { zynq7000::gpio::Gpio::new_mmio_fixed() };
|
||||
let mut gpio = unsafe { zynq7000::gpio::Registers::new_mmio_fixed() };
|
||||
gpio.bank_0().modify_dirm(|v| v | ZEDBOARD_LED_MASK);
|
||||
gpio.bank_0().modify_out_en(|v| v | ZEDBOARD_LED_MASK);
|
||||
loop {
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use aarch32_cpu::asm::nop;
|
||||
use core::{panic::PanicInfo, sync::atomic::AtomicU64};
|
||||
use cortex_ar::asm::nop;
|
||||
use embedded_hal::digital::StatefulOutputPin;
|
||||
use embedded_io::Write;
|
||||
use log::{error, info};
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use aarch32_cpu::asm::nop;
|
||||
use core::{panic::PanicInfo, sync::atomic::AtomicU64};
|
||||
use cortex_ar::asm::nop;
|
||||
use embedded_hal::digital::StatefulOutputPin;
|
||||
use embedded_io::Write;
|
||||
use log::{error, info};
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use aarch32_cpu::asm::nop;
|
||||
use core::panic::PanicInfo;
|
||||
use cortex_ar::asm::nop;
|
||||
use zynq7000_rt as _;
|
||||
|
||||
/// Entry point (not called like a normal main function)
|
||||
@@ -18,7 +18,7 @@ pub extern "C" fn boot_core(cpu_id: u32) -> ! {
|
||||
#[unsafe(export_name = "main")]
|
||||
pub fn main() -> ! {
|
||||
loop {
|
||||
cortex_ar::asm::nop();
|
||||
nop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ keywords = ["no-std", "arm", "cortex-a", "amd", "zynq7000"]
|
||||
categories = ["embedded", "no-std", "hardware-support"]
|
||||
|
||||
[dependencies]
|
||||
cortex-ar = "0.3"
|
||||
aarch32-cpu = { version = "0.1" }
|
||||
zynq7000-rt = { path = "../../zynq7000-rt" }
|
||||
zynq7000 = { path = "../../zynq7000" }
|
||||
zynq7000-hal = { path = "../../zynq7000-hal" }
|
||||
|
||||
@@ -7,6 +7,7 @@ MEMORY
|
||||
UNCACHED(rx): ORIGIN = 0x4000000, LENGTH = 1M
|
||||
}
|
||||
|
||||
REGION_ALIAS("VECTORS", CODE);
|
||||
REGION_ALIAS("DATA", CODE);
|
||||
|
||||
SECTIONS
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use aarch32_cpu::asm::nop;
|
||||
use core::{net::Ipv4Addr, panic::PanicInfo};
|
||||
use cortex_ar::asm::nop;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_net::{Ipv4Cidr, StaticConfigV4, tcp::TcpSocket, udp::UdpSocket};
|
||||
use embassy_time::{Duration, Timer};
|
||||
@@ -290,7 +290,7 @@ async fn main(spawner: Spawner) -> ! {
|
||||
);
|
||||
// Configures all the physical pins for ethernet operation and sets up the
|
||||
// ethernet peripheral.
|
||||
let mut eth = zynq7000_hal::eth::Ethernet::new_with_mio(
|
||||
let mut eth = zynq7000_hal::eth::Ethernet::new_with_mio_eth_0(
|
||||
eth_ll,
|
||||
eth_cfg,
|
||||
gpio_pins.mio.mio16,
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use aarch32_cpu::asm::nop;
|
||||
use core::panic::PanicInfo;
|
||||
use cortex_ar::asm::nop;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Delay, Duration, Ticker};
|
||||
use embedded_hal::digital::StatefulOutputPin;
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use aarch32_cpu::asm::nop;
|
||||
use core::panic::PanicInfo;
|
||||
use cortex_ar::asm::nop;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Delay, Duration, Ticker};
|
||||
use embedded_hal::digital::StatefulOutputPin;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use aarch32_cpu::asm::nop;
|
||||
use core::panic::PanicInfo;
|
||||
use cortex_ar::asm::nop;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Duration, Ticker};
|
||||
use embedded_hal::digital::StatefulOutputPin;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use aarch32_cpu::asm::nop;
|
||||
use axi_uart16550::AxiUart16550;
|
||||
use axi_uartlite::AxiUartlite;
|
||||
use core::panic::PanicInfo;
|
||||
use cortex_ar::asm::nop;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Duration, Ticker};
|
||||
use embedded_hal::digital::StatefulOutputPin;
|
||||
|
||||
@@ -25,11 +25,11 @@
|
||||
#![no_main]
|
||||
extern crate alloc;
|
||||
|
||||
use aarch32_cpu::asm::nop;
|
||||
use alloc::format;
|
||||
use axi_uart16550::AxiUart16550;
|
||||
use axi_uartlite::AxiUartlite;
|
||||
use core::{cell::RefCell, panic::PanicInfo};
|
||||
use cortex_ar::asm::nop;
|
||||
use critical_section::Mutex;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Duration, Ticker};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use aarch32_cpu::asm::nop;
|
||||
use core::panic::PanicInfo;
|
||||
use cortex_ar::asm::nop;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Duration, Ticker};
|
||||
use embedded_hal::digital::StatefulOutputPin;
|
||||
|
||||
@@ -9,7 +9,7 @@ repository = "https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
cortex-ar = { version = "0.3", features = ["critical-section-single-core"] }
|
||||
aarch32-cpu = { version = "0.1", features = ["critical-section-single-core"] }
|
||||
zynq7000-rt = { path = "../zynq7000-rt" }
|
||||
zynq7000 = { path = "../zynq7000" }
|
||||
zynq7000-hal = { path = "../zynq7000-hal" }
|
||||
|
||||
@@ -9,6 +9,7 @@ MEMORY
|
||||
UNCACHED(rx): ORIGIN = 0x4000000, LENGTH = 1M
|
||||
}
|
||||
|
||||
REGION_ALIAS("VECTORS", CODE);
|
||||
REGION_ALIAS("DATA", CODE);
|
||||
|
||||
SECTIONS
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
use arbitrary_int::u6;
|
||||
use core::panic::PanicInfo;
|
||||
use cortex_ar::asm::nop;
|
||||
use aarch32_cpu::asm::nop;
|
||||
use embedded_io::Write as _;
|
||||
use log::{error, info};
|
||||
use zedboard_bsp::qspi_spansion::{self, QspiSpansionS25Fl256SLinearMode};
|
||||
@@ -178,7 +178,7 @@ pub fn main() -> ! {
|
||||
qspi_boot(spansion_lqspi, priv_tim);
|
||||
}
|
||||
loop {
|
||||
cortex_ar::asm::nop();
|
||||
aarch32_cpu::asm::nop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,10 +321,10 @@ fn qspi_boot(mut qspi: QspiSpansionS25Fl256SLinearMode, _priv_tim: priv_tim::Cpu
|
||||
|
||||
// Some clean up and preparation for jumping to the user application.
|
||||
zynq7000_hal::cache::clean_and_invalidate_data_cache();
|
||||
cortex_ar::register::TlbIAll::write();
|
||||
cortex_ar::register::BpIAll::write();
|
||||
cortex_ar::asm::dsb();
|
||||
cortex_ar::asm::isb();
|
||||
aarch32_cpu::register::TlbIAll::write();
|
||||
aarch32_cpu::register::BpIAll::write();
|
||||
aarch32_cpu::asm::dsb();
|
||||
aarch32_cpu::asm::isb();
|
||||
|
||||
let jump_func: extern "C" fn() -> ! = unsafe { core::mem::transmute(jump_addr) };
|
||||
jump_func();
|
||||
|
||||
@@ -4,7 +4,7 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
cortex-ar = { version = "0.3" }
|
||||
aarch32-cpu = { version = "0.1", features = ["critical-section-single-core"] }
|
||||
zynq7000-rt = { path = "../zynq7000-rt" }
|
||||
zynq7000 = { path = "../zynq7000" }
|
||||
zynq7000-hal = { path = "../zynq7000-hal" }
|
||||
|
||||
@@ -7,6 +7,7 @@ MEMORY
|
||||
UNCACHED(rx): ORIGIN = 0x4000000, LENGTH = 1M
|
||||
}
|
||||
|
||||
REGION_ALIAS("VECTORS", CODE)
|
||||
REGION_ALIAS("DATA", CODE);
|
||||
|
||||
SECTIONS
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use aarch32_cpu::asm::nop;
|
||||
use core::panic::PanicInfo;
|
||||
use cortex_ar::asm::nop;
|
||||
use embedded_hal::{delay::DelayNs as _, digital::StatefulOutputPin as _};
|
||||
use embedded_io::Write as _;
|
||||
use log::{error, info};
|
||||
|
||||
@@ -11,7 +11,7 @@ keywords = ["no-std", "hal", "amd", "zynq7000", "bare-metal"]
|
||||
categories = ["embedded", "no-std", "hardware-support"]
|
||||
|
||||
[dependencies]
|
||||
cortex-ar = { version = "0.3" }
|
||||
aarch32-cpu = { version = "0.1" }
|
||||
zynq7000 = { path = "../zynq7000", version = "0.1" }
|
||||
zynq7000-mmu = { path = "../zynq7000-mmu", version = "0.1" }
|
||||
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
//! L2 cache in the correct order. This module provides commonly required operations.
|
||||
use core::sync::atomic::compiler_fence;
|
||||
|
||||
use cortex_ar::{
|
||||
use aarch32_cpu::{
|
||||
asm::dsb,
|
||||
cache::{
|
||||
clean_and_invalidate_data_cache_line_to_poc, clean_data_cache_line_to_poc,
|
||||
invalidate_data_cache_line_to_poc,
|
||||
},
|
||||
};
|
||||
use zynq7000::l2_cache::{L2Cache, MmioL2Cache};
|
||||
use zynq7000::l2_cache::{MmioRegisters, Registers};
|
||||
|
||||
pub const CACHE_LINE_SIZE: usize = 32;
|
||||
|
||||
@@ -19,7 +19,7 @@ pub const CACHE_LINE_SIZE: usize = 32;
|
||||
#[error("alignment error, addresses and lengths must be aligned to 32 byte cache line length")]
|
||||
pub struct AlignmentError;
|
||||
|
||||
pub fn clean_and_invalidate_l2c_line(l2c: &mut MmioL2Cache<'static>, addr: u32) {
|
||||
pub fn clean_and_invalidate_l2c_line(l2c: &mut MmioRegisters<'static>, addr: u32) {
|
||||
l2c.write_clean_by_pa(addr);
|
||||
l2c.write_invalidate_by_pa(addr);
|
||||
}
|
||||
@@ -28,16 +28,16 @@ pub fn clean_and_invalidate_l2c_line(l2c: &mut MmioL2Cache<'static>, addr: u32)
|
||||
pub fn clean_and_invalidate_data_cache() {
|
||||
dsb();
|
||||
|
||||
cortex_ar::cache::clean_l1_data_cache::<2, 5, 8>();
|
||||
aarch32_cpu::cache::clean_l1_data_cache::<2, 5, 8>();
|
||||
dsb();
|
||||
|
||||
// Clean all ways in L2 cache.
|
||||
let mut l2c = unsafe { L2Cache::new_mmio_fixed() };
|
||||
let mut l2c = unsafe { Registers::new_mmio_fixed() };
|
||||
l2c.write_clean_invalidate_by_way(0xffff);
|
||||
while l2c.read_cache_sync().busy() {}
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
|
||||
cortex_ar::cache::clean_and_invalidate_l1_data_cache::<2, 5, 8>();
|
||||
aarch32_cpu::cache::clean_and_invalidate_l1_data_cache::<2, 5, 8>();
|
||||
dsb();
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ pub fn invalidate_data_cache_range(addr: u32, len: usize) -> Result<(), Alignmen
|
||||
}
|
||||
let mut current_addr = addr;
|
||||
let end_addr = addr.saturating_add(len as u32);
|
||||
let mut l2c = unsafe { L2Cache::new_mmio_fixed() };
|
||||
let mut l2c = unsafe { Registers::new_mmio_fixed() };
|
||||
|
||||
dsb();
|
||||
// Invalidate outer caches lines first, see chapter 3.3.10 of the L2C technical reference
|
||||
@@ -103,7 +103,7 @@ pub fn clean_and_invalidate_data_cache_range(addr: u32, len: usize) -> Result<()
|
||||
dsb();
|
||||
|
||||
// Clean and invalidates outer cache.
|
||||
let mut l2c = unsafe { L2Cache::new_mmio_fixed() };
|
||||
let mut l2c = unsafe { Registers::new_mmio_fixed() };
|
||||
current_addr = addr;
|
||||
while current_addr < end_addr {
|
||||
// ARM errate 588369 specifies that clean and invalidate need to be separate, but the
|
||||
@@ -155,7 +155,7 @@ pub fn clean_data_cache_range(addr: u32, len: usize) -> Result<(), AlignmentErro
|
||||
dsb();
|
||||
|
||||
// Clean and invalidates outer cache.
|
||||
let mut l2c = unsafe { L2Cache::new_mmio_fixed() };
|
||||
let mut l2c = unsafe { Registers::new_mmio_fixed() };
|
||||
current_addr = addr;
|
||||
while current_addr < end_addr {
|
||||
l2c.write_clean_by_pa(current_addr);
|
||||
|
||||
@@ -8,7 +8,7 @@ use arbitrary_int::{prelude::*, u6};
|
||||
pub mod pll;
|
||||
|
||||
use zynq7000::slcr::{
|
||||
ClockControl,
|
||||
ClockControlRegisters,
|
||||
clocks::{
|
||||
ClockkRatioSelect, DualCommonPeriphIoClockControl, FpgaClockControl, GigEthClockControl,
|
||||
SingleCommonPeriphIoClockControl,
|
||||
@@ -254,7 +254,7 @@ impl Clocks {
|
||||
/// It assumes that the clock already has been configured, for example by a first-stage
|
||||
/// bootloader, or the PS7 initialization script.
|
||||
pub fn new_from_regs(ps_clk_freq: Hertz) -> Result<Self, ClockReadError> {
|
||||
let mut clk_regs = unsafe { ClockControl::new_mmio_fixed() };
|
||||
let mut clk_regs = unsafe { ClockControlRegisters::new_mmio_fixed() };
|
||||
|
||||
let arm_pll_cfg = clk_regs.read_arm_pll_ctrl();
|
||||
let io_pll_cfg = clk_regs.read_io_pll_ctrl();
|
||||
@@ -505,7 +505,7 @@ impl Clocks {
|
||||
/// The reference clock will only be the RX clock in loopback mode. For the TX block,
|
||||
/// the reference clock is used if the EMIO enable bit `GEM{0,1}_CLK_CTRL[6]` is set to 0.
|
||||
pub fn calculate_gem_0_ref_clock(&self) -> Result<Hertz, DivisorZero> {
|
||||
let clk_regs = unsafe { ClockControl::new_mmio_fixed() };
|
||||
let clk_regs = unsafe { ClockControlRegisters::new_mmio_fixed() };
|
||||
self.calculate_gem_ref_clock(clk_regs.read_gem_0_clk_ctrl(), ClockModuleId::Gem0)
|
||||
}
|
||||
|
||||
@@ -518,7 +518,7 @@ impl Clocks {
|
||||
/// The reference clock will only be the RX clock in loopback mode. For the TX block,
|
||||
/// the reference clock is used if the EMIO enable bit `GEM{0,1}_CLK_CTRL[6]` is set to 0.
|
||||
pub fn calculate_gem_1_ref_clock(&self) -> Result<Hertz, DivisorZero> {
|
||||
let clk_regs = unsafe { ClockControl::new_mmio_fixed() };
|
||||
let clk_regs = unsafe { ClockControlRegisters::new_mmio_fixed() };
|
||||
self.calculate_gem_ref_clock(clk_regs.read_gem_0_clk_ctrl(), ClockModuleId::Gem1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,7 +309,7 @@ unsafe fn configure_pll_unchecked(
|
||||
boot_mode: BootMode,
|
||||
cfg: PllConfig,
|
||||
pll_type: PllType,
|
||||
slcr: &mut zynq7000::slcr::MmioSlcr<'static>,
|
||||
slcr: &mut zynq7000::slcr::MmioRegisters<'static>,
|
||||
pll_ctrl_reg: *mut zynq7000::slcr::clocks::PllControl,
|
||||
pll_cfg_reg: *mut zynq7000::slcr::clocks::PllConfig,
|
||||
) {
|
||||
@@ -346,9 +346,7 @@ unsafe fn configure_pll_unchecked(
|
||||
while ((slcr.clk_ctrl().read_pll_status().raw_value() >> pll_type.bit_offset_pll_locked())
|
||||
& 0b1)
|
||||
!= 1
|
||||
{
|
||||
cortex_ar::asm::nop();
|
||||
}
|
||||
{}
|
||||
|
||||
pll_ctrl = unsafe { core::ptr::read_volatile(pll_ctrl_reg) };
|
||||
pll_ctrl.set_bypass_force(false);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Low-level DDR configuration module.
|
||||
use arbitrary_int::{prelude::*, u2, u3, u6};
|
||||
use zynq7000::ddrc::{MmioDdrController, regs::*};
|
||||
use zynq7000::ddrc::{MmioRegisters, regs::*};
|
||||
use zynq7000::slcr::{clocks::DciClockControl, ddriob::DdriobConfig};
|
||||
|
||||
use crate::{clocks::DdrClocks, time::Hertz};
|
||||
@@ -163,10 +163,7 @@ pub unsafe fn calibrate_iob_impedance(
|
||||
val
|
||||
});
|
||||
if poll_for_done {
|
||||
while !slcr.ddriob().read_dci_status().done() {
|
||||
// Wait for the DDR IOB impedance calibration to complete.
|
||||
cortex_ar::asm::nop();
|
||||
}
|
||||
while !slcr.ddriob().read_dci_status().done() {}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -272,7 +269,7 @@ pub struct DdrcConfigSet {
|
||||
///
|
||||
/// It does NOT take care of taking the DDR controller out of reset and polling for DDR
|
||||
/// configuration completion.
|
||||
pub fn configure_ddr_config(ddrc: &mut MmioDdrController<'static>, cfg_set: &DdrcConfigSet) {
|
||||
pub fn configure_ddr_config(ddrc: &mut MmioRegisters<'static>, cfg_set: &DdrcConfigSet) {
|
||||
ddrc.write_ddrc_ctrl(cfg_set.ctrl);
|
||||
// Write all configuration registers.
|
||||
ddrc.write_two_rank_cfg(cfg_set.two_rank);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//!
|
||||
//! - [Zedboard FSBL](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/zedboard-fsbl)
|
||||
use arbitrary_int::u6;
|
||||
use zynq7000::ddrc::MmioDdrController;
|
||||
use zynq7000::ddrc::MmioRegisters;
|
||||
|
||||
use crate::{
|
||||
BootMode,
|
||||
@@ -48,7 +48,7 @@ impl DdrClockSetupConfig {
|
||||
/// This function consumes the DDRC register block once and thus provides a safe interface for DDR
|
||||
/// initialization.
|
||||
pub fn configure_ddr_for_ddr3(
|
||||
mut ddrc_regs: MmioDdrController<'static>,
|
||||
mut ddrc_regs: MmioRegisters<'static>,
|
||||
boot_mode: BootMode,
|
||||
clk_setup_cfg: DdrClockSetupConfig,
|
||||
ddriob_cfg: &DdriobConfigSet,
|
||||
@@ -89,7 +89,7 @@ pub fn configure_ddr_for_ddr3(
|
||||
let ddriob_shared = slcr.regs().ddriob_shared();
|
||||
// Wait for DDR IOB impedance calibration to complete first.
|
||||
while !ddriob_shared.read_dci_status().done() {
|
||||
cortex_ar::asm::nop();
|
||||
aarch32_cpu::asm::nop();
|
||||
}
|
||||
log::debug!("DDR IOB impedance calib done");
|
||||
|
||||
@@ -103,7 +103,7 @@ pub fn configure_ddr_for_ddr3(
|
||||
!= zynq7000::ddrc::regs::OperatingMode::NormalOperation
|
||||
{
|
||||
// Wait for the soft reset to complete.
|
||||
cortex_ar::asm::nop();
|
||||
aarch32_cpu::asm::nop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ pub fn configure_bitstream_non_secure(
|
||||
if bitstream.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let mut devcfg = unsafe { zynq7000::devcfg::DevCfg::new_mmio_fixed() };
|
||||
let mut devcfg = unsafe { zynq7000::devcfg::Registers::new_mmio_fixed() };
|
||||
devcfg.modify_control(|mut val| {
|
||||
val.set_config_access_select(zynq7000::devcfg::PlConfigAccess::ConfigAccessPort);
|
||||
val.set_access_port_select(zynq7000::devcfg::ConfigAccessPortSelect::Pcap);
|
||||
|
||||
@@ -8,11 +8,6 @@ use crate::{clocks::IoClocks, enable_amba_peripheral_clock, slcr::Slcr, time::He
|
||||
|
||||
use super::{EthernetId, PsEthernet as _};
|
||||
|
||||
pub struct EthernetLowLevel {
|
||||
id: EthernetId,
|
||||
pub regs: zynq7000::eth::MmioEthernet<'static>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Speed {
|
||||
Mbps10,
|
||||
@@ -52,7 +47,10 @@ impl ClockDivisors {
|
||||
|
||||
/// Calls [Self::calculate_for_rgmii], assuming that the IO clock is the reference clock,
|
||||
/// which is the default clock for the Ethernet module.
|
||||
pub fn calculate_for_rgmii_and_io_clock(io_clks: IoClocks, target_speed: Speed) -> (Self, u32) {
|
||||
pub fn calculate_for_rgmii_and_io_clock(
|
||||
io_clks: &IoClocks,
|
||||
target_speed: Speed,
|
||||
) -> (Self, u32) {
|
||||
Self::calculate_for_rgmii(io_clks.ref_clk(), target_speed)
|
||||
}
|
||||
|
||||
@@ -174,10 +172,19 @@ impl ClockDivSet {
|
||||
/// Ethernet low-level interface.
|
||||
///
|
||||
/// Basic building block for higher-level abstraction.
|
||||
pub struct EthernetLowLevel {
|
||||
id: EthernetId,
|
||||
/// Register block. Direct public access is allowed to allow low-level operations.
|
||||
pub regs: zynq7000::eth::MmioRegisters<'static>,
|
||||
}
|
||||
|
||||
impl EthernetLowLevel {
|
||||
/// Creates a new instance of the Ethernet low-level interface.
|
||||
///
|
||||
/// Returns [None] if the given registers block base address does not correspond to a valid
|
||||
/// Ethernet peripheral.
|
||||
#[inline]
|
||||
pub fn new(regs: zynq7000::eth::MmioEthernet<'static>) -> Option<Self> {
|
||||
pub fn new(regs: zynq7000::eth::MmioRegisters<'static>) -> Option<Self> {
|
||||
regs.id()?;
|
||||
Some(EthernetLowLevel {
|
||||
id: regs.id().unwrap(),
|
||||
@@ -196,41 +203,15 @@ impl EthernetLowLevel {
|
||||
id,
|
||||
regs: unsafe {
|
||||
match id {
|
||||
EthernetId::Eth0 => zynq7000::eth::Ethernet::new_mmio_fixed_0(),
|
||||
EthernetId::Eth1 => zynq7000::eth::Ethernet::new_mmio_fixed_1(),
|
||||
EthernetId::Eth0 => zynq7000::eth::Registers::new_mmio_fixed_0(),
|
||||
EthernetId::Eth1 => zynq7000::eth::Registers::new_mmio_fixed_1(),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self, cycles: usize) {
|
||||
let assert_reset = match self.id {
|
||||
EthernetId::Eth0 => EthernetReset::builder()
|
||||
.with_gem1_ref_rst(false)
|
||||
.with_gem0_ref_rst(true)
|
||||
.with_gem1_rx_rst(false)
|
||||
.with_gem0_rx_rst(true)
|
||||
.with_gem1_cpu1x_rst(false)
|
||||
.with_gem0_cpu1x_rst(true)
|
||||
.build(),
|
||||
EthernetId::Eth1 => EthernetReset::builder()
|
||||
.with_gem1_ref_rst(true)
|
||||
.with_gem0_ref_rst(false)
|
||||
.with_gem1_rx_rst(true)
|
||||
.with_gem0_rx_rst(false)
|
||||
.with_gem1_cpu1x_rst(true)
|
||||
.with_gem0_cpu1x_rst(false)
|
||||
.build(),
|
||||
};
|
||||
unsafe {
|
||||
Slcr::with(|regs| {
|
||||
regs.reset_ctrl().write_eth(assert_reset);
|
||||
for _ in 0..cycles {
|
||||
cortex_ar::asm::nop();
|
||||
}
|
||||
regs.reset_ctrl().write_eth(EthernetReset::DEFAULT);
|
||||
});
|
||||
}
|
||||
reset(self.id, cycles);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -383,3 +364,34 @@ impl EthernetLowLevel {
|
||||
self.id
|
||||
}
|
||||
}
|
||||
|
||||
/// Resets the Ethernet peripheral with the given ID.
|
||||
pub fn reset(id: EthernetId, cycles: usize) {
|
||||
let assert_reset = match id {
|
||||
EthernetId::Eth0 => EthernetReset::builder()
|
||||
.with_gem1_ref_rst(false)
|
||||
.with_gem0_ref_rst(true)
|
||||
.with_gem1_rx_rst(false)
|
||||
.with_gem0_rx_rst(true)
|
||||
.with_gem1_cpu1x_rst(false)
|
||||
.with_gem0_cpu1x_rst(true)
|
||||
.build(),
|
||||
EthernetId::Eth1 => EthernetReset::builder()
|
||||
.with_gem1_ref_rst(true)
|
||||
.with_gem0_ref_rst(false)
|
||||
.with_gem1_rx_rst(true)
|
||||
.with_gem0_rx_rst(false)
|
||||
.with_gem1_cpu1x_rst(true)
|
||||
.with_gem0_cpu1x_rst(false)
|
||||
.build(),
|
||||
};
|
||||
unsafe {
|
||||
Slcr::with(|regs| {
|
||||
regs.reset_ctrl().write_eth(assert_reset);
|
||||
for _ in 0..cycles {
|
||||
aarch32_cpu::asm::nop();
|
||||
}
|
||||
regs.reset_ctrl().write_eth(EthernetReset::DEFAULT);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use zynq7000::eth::{MdcClockDivisor, PhyMaintenance};
|
||||
use super::{EthernetId, ll::EthernetLowLevel};
|
||||
|
||||
pub struct Mdio {
|
||||
regs: zynq7000::eth::MmioEthernet<'static>,
|
||||
regs: zynq7000::eth::MmioRegisters<'static>,
|
||||
clause22: bool,
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ use arbitrary_int::{u2, u3};
|
||||
pub use zynq7000::eth::MdcClockDivisor;
|
||||
use zynq7000::eth::{
|
||||
BurstLength, DmaRxBufSize, GEM_0_BASE_ADDR, GEM_1_BASE_ADDR, InterruptControl, InterruptStatus,
|
||||
MmioEthernet, RxStatus, TxStatus,
|
||||
MmioRegisters, RxStatus, TxStatus,
|
||||
};
|
||||
|
||||
pub use ll::{ClockConfig, ClockDivSet, Duplex, EthernetLowLevel, Speed};
|
||||
@@ -58,18 +58,18 @@ impl EthernetId {
|
||||
/// # Safety
|
||||
///
|
||||
/// Circumvents ownership and safety guarantees of the HAL.
|
||||
pub const unsafe fn steal_regs(&self) -> zynq7000::eth::MmioEthernet<'static> {
|
||||
pub const unsafe fn steal_regs(&self) -> zynq7000::eth::MmioRegisters<'static> {
|
||||
unsafe {
|
||||
match self {
|
||||
EthernetId::Eth0 => zynq7000::eth::Ethernet::new_mmio_fixed_0(),
|
||||
EthernetId::Eth1 => zynq7000::eth::Ethernet::new_mmio_fixed_1(),
|
||||
EthernetId::Eth0 => zynq7000::eth::Registers::new_mmio_fixed_0(),
|
||||
EthernetId::Eth1 => zynq7000::eth::Registers::new_mmio_fixed_1(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clk_config_regs(
|
||||
&self,
|
||||
slcr: &mut zynq7000::slcr::MmioSlcr<'static>,
|
||||
slcr: &mut zynq7000::slcr::MmioRegisters<'static>,
|
||||
) -> (
|
||||
*mut zynq7000::slcr::clocks::GigEthClockControl,
|
||||
*mut zynq7000::slcr::clocks::GigEthRclkControl,
|
||||
@@ -88,13 +88,13 @@ impl EthernetId {
|
||||
}
|
||||
|
||||
pub trait PsEthernet {
|
||||
fn reg_block(&self) -> MmioEthernet<'static>;
|
||||
fn reg_block(&self) -> MmioRegisters<'static>;
|
||||
fn id(&self) -> Option<EthernetId>;
|
||||
}
|
||||
|
||||
impl PsEthernet for MmioEthernet<'static> {
|
||||
impl PsEthernet for MmioRegisters<'static> {
|
||||
#[inline]
|
||||
fn reg_block(&self) -> MmioEthernet<'static> {
|
||||
fn reg_block(&self) -> MmioRegisters<'static> {
|
||||
unsafe { self.clone() }
|
||||
}
|
||||
|
||||
@@ -110,42 +110,31 @@ impl PsEthernet for MmioEthernet<'static> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TxClockPin: MioPin {
|
||||
const ETH_ID: EthernetId;
|
||||
}
|
||||
pub trait TxControlPin: MioPin {
|
||||
const ETH_ID: EthernetId;
|
||||
}
|
||||
pub trait TxData0Pin: MioPin {
|
||||
const ETH_ID: EthernetId;
|
||||
}
|
||||
pub trait TxData1Pin: MioPin {
|
||||
const ETH_ID: EthernetId;
|
||||
}
|
||||
pub trait TxData2Pin: MioPin {
|
||||
const ETH_ID: EthernetId;
|
||||
}
|
||||
pub trait TxData3Pin: MioPin {
|
||||
const ETH_ID: EthernetId;
|
||||
}
|
||||
pub trait RxClockPin: MioPin {
|
||||
const ETH_ID: EthernetId;
|
||||
}
|
||||
pub trait RxControlPin: MioPin {
|
||||
const ETH_ID: EthernetId;
|
||||
}
|
||||
pub trait RxData0Pin: MioPin {
|
||||
const ETH_ID: EthernetId;
|
||||
}
|
||||
pub trait RxData1Pin: MioPin {
|
||||
const ETH_ID: EthernetId;
|
||||
}
|
||||
pub trait RxData2Pin: MioPin {
|
||||
const ETH_ID: EthernetId;
|
||||
}
|
||||
pub trait RxData3Pin: MioPin {
|
||||
const ETH_ID: EthernetId;
|
||||
}
|
||||
pub trait Eth0TxClockPin: MioPin {}
|
||||
pub trait Eth0TxControlPin: MioPin {}
|
||||
pub trait Eth0TxData0Pin: MioPin {}
|
||||
pub trait Eth0TxData1Pin: MioPin {}
|
||||
pub trait Eth0TxData2Pin: MioPin {}
|
||||
pub trait Eth0TxData3Pin: MioPin {}
|
||||
pub trait Eth0RxClockPin: MioPin {}
|
||||
pub trait Eth0RxControlPin: MioPin {}
|
||||
pub trait Eth0RxData0Pin: MioPin {}
|
||||
pub trait Eth0RxData1Pin: MioPin {}
|
||||
pub trait Eth0RxData2Pin: MioPin {}
|
||||
pub trait Eth0RxData3Pin: MioPin {}
|
||||
|
||||
pub trait Eth1TxClockPin: MioPin {}
|
||||
pub trait Eth1TxControlPin: MioPin {}
|
||||
pub trait Eth1TxData0Pin: MioPin {}
|
||||
pub trait Eth1TxData1Pin: MioPin {}
|
||||
pub trait Eth1TxData2Pin: MioPin {}
|
||||
pub trait Eth1TxData3Pin: MioPin {}
|
||||
pub trait Eth1RxClockPin: MioPin {}
|
||||
pub trait Eth1RxControlPin: MioPin {}
|
||||
pub trait Eth1RxData0Pin: MioPin {}
|
||||
pub trait Eth1RxData1Pin: MioPin {}
|
||||
pub trait Eth1RxData2Pin: MioPin {}
|
||||
pub trait Eth1RxData3Pin: MioPin {}
|
||||
|
||||
pub trait MdClockPin: MioPin {}
|
||||
pub trait MdIoPin: MioPin {}
|
||||
@@ -154,90 +143,42 @@ impl MdClockPin for Pin<Mio52> {}
|
||||
impl MdIoPin for Pin<Mio53> {}
|
||||
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl TxClockPin for Pin<Mio16> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth0;
|
||||
}
|
||||
impl Eth0TxClockPin for Pin<Mio16> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl TxControlPin for Pin<Mio21> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth0;
|
||||
}
|
||||
impl Eth0TxControlPin for Pin<Mio21> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl TxData0Pin for Pin<Mio17> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth0;
|
||||
}
|
||||
impl Eth0TxData0Pin for Pin<Mio17> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl TxData1Pin for Pin<Mio18> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth0;
|
||||
}
|
||||
impl Eth0TxData1Pin for Pin<Mio18> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl TxData2Pin for Pin<Mio19> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth0;
|
||||
}
|
||||
impl Eth0TxData2Pin for Pin<Mio19> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl TxData3Pin for Pin<Mio20> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth0;
|
||||
}
|
||||
impl Eth0TxData3Pin for Pin<Mio20> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl RxClockPin for Pin<Mio22> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth0;
|
||||
}
|
||||
impl Eth0RxClockPin for Pin<Mio22> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl RxControlPin for Pin<Mio27> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth0;
|
||||
}
|
||||
impl Eth0RxControlPin for Pin<Mio27> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl RxData0Pin for Pin<Mio23> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth0;
|
||||
}
|
||||
impl Eth0RxData0Pin for Pin<Mio23> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl RxData1Pin for Pin<Mio24> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth0;
|
||||
}
|
||||
impl Eth0RxData1Pin for Pin<Mio24> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl RxData2Pin for Pin<Mio25> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth0;
|
||||
}
|
||||
impl Eth0RxData2Pin for Pin<Mio25> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl RxData3Pin for Pin<Mio26> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth0;
|
||||
}
|
||||
impl Eth0RxData3Pin for Pin<Mio26> {}
|
||||
|
||||
impl TxClockPin for Pin<Mio28> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth1;
|
||||
}
|
||||
impl TxControlPin for Pin<Mio33> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth1;
|
||||
}
|
||||
impl TxData0Pin for Pin<Mio29> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth1;
|
||||
}
|
||||
impl TxData1Pin for Pin<Mio30> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth1;
|
||||
}
|
||||
impl TxData2Pin for Pin<Mio31> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth1;
|
||||
}
|
||||
impl TxData3Pin for Pin<Mio32> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth1;
|
||||
}
|
||||
impl RxClockPin for Pin<Mio34> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth1;
|
||||
}
|
||||
impl RxControlPin for Pin<Mio39> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth1;
|
||||
}
|
||||
impl RxData0Pin for Pin<Mio35> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth1;
|
||||
}
|
||||
impl RxData1Pin for Pin<Mio36> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth1;
|
||||
}
|
||||
impl RxData2Pin for Pin<Mio37> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth1;
|
||||
}
|
||||
impl RxData3Pin for Pin<Mio38> {
|
||||
const ETH_ID: EthernetId = EthernetId::Eth1;
|
||||
}
|
||||
impl Eth1TxClockPin for Pin<Mio28> {}
|
||||
impl Eth1TxControlPin for Pin<Mio33> {}
|
||||
impl Eth1TxData0Pin for Pin<Mio29> {}
|
||||
impl Eth1TxData1Pin for Pin<Mio30> {}
|
||||
impl Eth1TxData2Pin for Pin<Mio31> {}
|
||||
impl Eth1TxData3Pin for Pin<Mio32> {}
|
||||
impl Eth1RxClockPin for Pin<Mio34> {}
|
||||
impl Eth1RxControlPin for Pin<Mio39> {}
|
||||
impl Eth1RxData0Pin for Pin<Mio35> {}
|
||||
impl Eth1RxData1Pin for Pin<Mio36> {}
|
||||
impl Eth1RxData2Pin for Pin<Mio37> {}
|
||||
impl Eth1RxData3Pin for Pin<Mio38> {}
|
||||
|
||||
/// Calculate the CPU 1x clock divisor required to achieve a clock speed which is below
|
||||
/// 2.5 MHz, as specified by the 802.3 standard.
|
||||
@@ -329,26 +270,26 @@ const IRQ_CLEAR_ALL: InterruptStatus = InterruptStatus::builder()
|
||||
.build();
|
||||
|
||||
impl Ethernet {
|
||||
/// Creates a new Ethernet instance with the given configuration while also
|
||||
/// configuring all the necessary MIO pins.
|
||||
/// Creates a new Ethernet instance for the Ethernet 0 block with the given configuration while
|
||||
/// also configuring all the necessary MIO pins.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new_with_mio<
|
||||
TxClock: TxClockPin,
|
||||
TxControl: TxControlPin,
|
||||
TxData0: TxData0Pin,
|
||||
TxData1: TxData1Pin,
|
||||
TxData2: TxData2Pin,
|
||||
TxData3: TxData3Pin,
|
||||
RxClock: RxClockPin,
|
||||
RxControl: RxControlPin,
|
||||
RxData0: RxData0Pin,
|
||||
RxData1: RxData1Pin,
|
||||
RxData2: RxData2Pin,
|
||||
RxData3: RxData3Pin,
|
||||
pub fn new_with_mio_eth_0<
|
||||
TxClock: Eth0TxClockPin,
|
||||
TxControl: Eth0TxControlPin,
|
||||
TxData0: Eth0TxData0Pin,
|
||||
TxData1: Eth0TxData1Pin,
|
||||
TxData2: Eth0TxData2Pin,
|
||||
TxData3: Eth0TxData3Pin,
|
||||
RxClock: Eth0RxClockPin,
|
||||
RxControl: Eth0RxControlPin,
|
||||
RxData0: Eth0RxData0Pin,
|
||||
RxData1: Eth0RxData1Pin,
|
||||
RxData2: Eth0RxData2Pin,
|
||||
RxData3: Eth0RxData3Pin,
|
||||
MdClock: MdClockPin,
|
||||
MdIo: MdIoPin,
|
||||
>(
|
||||
mut ll: ll::EthernetLowLevel,
|
||||
ll: ll::EthernetLowLevel,
|
||||
config: EthernetConfig,
|
||||
tx_clk: TxClock,
|
||||
tx_ctrl: TxControl,
|
||||
@@ -357,6 +298,59 @@ impl Ethernet {
|
||||
rx_ctrl: RxControl,
|
||||
rx_data: (RxData0, RxData1, RxData2, RxData3),
|
||||
md_pins: Option<(MdClock, MdIo)>,
|
||||
) -> Self {
|
||||
Self::new_with_mio(
|
||||
ll, config, tx_clk, tx_ctrl, tx_data, rx_clk, rx_ctrl, rx_data, md_pins,
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a new Ethernet instance for the Ethernet 1 block with the given configuration while
|
||||
/// also configuring all the necessary MIO pins.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new_with_mio_eth_1<
|
||||
TxClock: Eth1TxClockPin,
|
||||
TxControl: Eth1TxControlPin,
|
||||
TxData0: Eth1TxData0Pin,
|
||||
TxData1: Eth1TxData1Pin,
|
||||
TxData2: Eth1TxData2Pin,
|
||||
TxData3: Eth1TxData3Pin,
|
||||
RxClock: Eth1RxClockPin,
|
||||
RxControl: Eth1RxControlPin,
|
||||
RxData0: Eth1RxData0Pin,
|
||||
RxData1: Eth1RxData1Pin,
|
||||
RxData2: Eth1RxData2Pin,
|
||||
RxData3: Eth1RxData3Pin,
|
||||
MdClock: MdClockPin,
|
||||
MdIo: MdIoPin,
|
||||
>(
|
||||
ll: ll::EthernetLowLevel,
|
||||
config: EthernetConfig,
|
||||
tx_clk: TxClock,
|
||||
tx_ctrl: TxControl,
|
||||
tx_data: (TxData0, TxData1, TxData2, TxData3),
|
||||
rx_clk: RxClock,
|
||||
rx_ctrl: RxControl,
|
||||
rx_data: (RxData0, RxData1, RxData2, RxData3),
|
||||
md_pins: Option<(MdClock, MdIo)>,
|
||||
) -> Self {
|
||||
Self::new_with_mio(
|
||||
ll, config, tx_clk, tx_ctrl, tx_data, rx_clk, rx_ctrl, rx_data, md_pins,
|
||||
)
|
||||
}
|
||||
|
||||
// Creates a new Ethernet instance with the given configuration while also
|
||||
// configuring all the necessary MIO pins.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn new_with_mio<MdClock: MdClockPin, MdIo: MdIoPin>(
|
||||
mut ll: ll::EthernetLowLevel,
|
||||
config: EthernetConfig,
|
||||
tx_clk: impl MioPin,
|
||||
tx_ctrl: impl MioPin,
|
||||
tx_data: (impl MioPin, impl MioPin, impl MioPin, impl MioPin),
|
||||
rx_clk: impl MioPin,
|
||||
rx_ctrl: impl MioPin,
|
||||
rx_data: (impl MioPin, impl MioPin, impl MioPin, impl MioPin),
|
||||
md_pins: Option<(MdClock, MdIo)>,
|
||||
) -> Self {
|
||||
Self::common_init(&mut ll, config.mac_address);
|
||||
let tx_mio_config = zynq7000::slcr::mio::Config::builder()
|
||||
@@ -476,7 +470,7 @@ impl Ethernet {
|
||||
});
|
||||
});
|
||||
}
|
||||
ll.configure_clock(config.clk_config_1000_mbps, true);
|
||||
ll.configure_peripheral_clock(config.clk_config_1000_mbps, true);
|
||||
let mut mdio = mdio::Mdio::new(&ll, true);
|
||||
mdio.configure_clock_div(config.mdc_clk_div);
|
||||
ll.regs.modify_net_ctrl(|mut val| {
|
||||
@@ -497,7 +491,7 @@ impl Ethernet {
|
||||
|
||||
pub fn new(mut ll: EthernetLowLevel, config: EthernetConfig) -> Self {
|
||||
Self::common_init(&mut ll, config.mac_address);
|
||||
ll.configure_clock(config.clk_config_1000_mbps, true);
|
||||
ll.configure_peripheral_clock(config.clk_config_1000_mbps, true);
|
||||
let mut mdio = mdio::Mdio::new(&ll, true);
|
||||
mdio.configure_clock_div(config.mdc_clk_div);
|
||||
Ethernet {
|
||||
@@ -599,7 +593,7 @@ impl Ethernet {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn regs(&mut self) -> &MmioEthernet<'static> {
|
||||
pub fn regs(&mut self) -> &MmioRegisters<'static> {
|
||||
&self.ll.regs
|
||||
}
|
||||
|
||||
@@ -613,7 +607,7 @@ impl Ethernet {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn regs_mut(&mut self) -> &mut MmioEthernet<'static> {
|
||||
pub fn regs_mut(&mut self) -> &mut MmioRegisters<'static> {
|
||||
&mut self.ll.regs
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,11 @@
|
||||
//! - [GTC ticks](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/examples/simple/src/bin/gtc-ticks.rs)
|
||||
use arbitrary_int::prelude::*;
|
||||
|
||||
use cortex_ar::interrupt;
|
||||
use aarch32_cpu::interrupt;
|
||||
use zynq7000::gic::{
|
||||
DistributorControlRegister, GicCpuInterface, GicDistributor, InterfaceControl,
|
||||
InterruptSignalRegister, MmioGicCpuInterface, MmioGicDistributor, PriorityRegister,
|
||||
DistributorControlRegister, GicCpuInterfaceRegisters, GicDistributorRegisters,
|
||||
InterfaceControl, InterruptSignalRegister, MmioGicCpuInterfaceRegisters,
|
||||
MmioGicDistributorRegisters, PriorityRegister,
|
||||
};
|
||||
|
||||
const SPURIOUS_INTERRUPT_ID: u32 = 1023;
|
||||
@@ -224,8 +225,8 @@ pub struct InvalidSgiInterruptId(pub usize);
|
||||
/// For the handling of the interrupts, you can use the [GicInterruptHelper] which assumes a
|
||||
/// properly configured GIC.
|
||||
pub struct GicConfigurator {
|
||||
pub gicc: MmioGicCpuInterface<'static>,
|
||||
pub gicd: MmioGicDistributor<'static>,
|
||||
pub gicc: MmioGicCpuInterfaceRegisters<'static>,
|
||||
pub gicd: MmioGicDistributorRegisters<'static>,
|
||||
}
|
||||
|
||||
impl GicConfigurator {
|
||||
@@ -233,8 +234,8 @@ impl GicConfigurator {
|
||||
/// strongly recommended initialization routines for the GIC.
|
||||
#[inline]
|
||||
pub fn new_with_init(
|
||||
gicc: MmioGicCpuInterface<'static>,
|
||||
gicd: MmioGicDistributor<'static>,
|
||||
gicc: MmioGicCpuInterfaceRegisters<'static>,
|
||||
gicd: MmioGicDistributorRegisters<'static>,
|
||||
) -> Self {
|
||||
let mut gic = GicConfigurator { gicc, gicd };
|
||||
gic.initialize();
|
||||
@@ -251,8 +252,8 @@ impl GicConfigurator {
|
||||
#[inline]
|
||||
pub unsafe fn steal() -> Self {
|
||||
GicConfigurator {
|
||||
gicc: unsafe { GicCpuInterface::new_mmio_fixed() },
|
||||
gicd: unsafe { GicDistributor::new_mmio_fixed() },
|
||||
gicc: unsafe { GicCpuInterfaceRegisters::new_mmio_fixed() },
|
||||
gicd: unsafe { GicDistributorRegisters::new_mmio_fixed() },
|
||||
}
|
||||
}
|
||||
|
||||
@@ -488,12 +489,12 @@ impl GicConfigurator {
|
||||
|
||||
/// Helper structure which should only be used inside the interrupt handler once the GIC has
|
||||
/// been configured with the [GicConfigurator].
|
||||
pub struct GicInterruptHelper(MmioGicCpuInterface<'static>);
|
||||
pub struct GicInterruptHelper(MmioGicCpuInterfaceRegisters<'static>);
|
||||
|
||||
impl GicInterruptHelper {
|
||||
/// Create the interrupt helper with the fixed GICC MMIO instance.
|
||||
pub const fn new() -> Self {
|
||||
GicInterruptHelper(unsafe { GicCpuInterface::new_mmio_fixed() })
|
||||
GicInterruptHelper(unsafe { GicCpuInterfaceRegisters::new_mmio_fixed() })
|
||||
}
|
||||
|
||||
/// Acknowledges an interrupt by reading the IAR register and returning the interrupt context
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! EMIO (Extended Multiplexed I/O) resource management module.
|
||||
use zynq7000::gpio::MmioGpio;
|
||||
use zynq7000::gpio::MmioRegisters;
|
||||
|
||||
pub use crate::gpio::PinState;
|
||||
|
||||
@@ -37,7 +37,7 @@ impl Pins {
|
||||
/// This structure is supposed to be used as a singleton. It will configure all
|
||||
/// EMIO pins as inputs. If you want to retrieve individual pins without this structure,
|
||||
/// use [EmioPin::steal] instead.
|
||||
pub fn new(mut mmio: MmioGpio) -> Self {
|
||||
pub fn new(mut mmio: MmioRegisters) -> Self {
|
||||
let mut emios = [const { None }; 64];
|
||||
// Configure all EMIO pins as inputs.
|
||||
mmio.bank_2().write_dirm(0);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Low-level GPIO access module.
|
||||
use embedded_hal::digital::PinState;
|
||||
use zynq7000::gpio::{Gpio, MaskedOutput, MmioGpio};
|
||||
use zynq7000::gpio::{MaskedOutput, MmioRegisters, Registers};
|
||||
|
||||
use crate::slcr::Slcr;
|
||||
|
||||
@@ -48,14 +48,14 @@ impl PinOffset {
|
||||
|
||||
pub struct LowLevelGpio {
|
||||
offset: PinOffset,
|
||||
regs: MmioGpio<'static>,
|
||||
regs: MmioRegisters<'static>,
|
||||
}
|
||||
|
||||
impl LowLevelGpio {
|
||||
pub fn new(offset: PinOffset) -> Self {
|
||||
Self {
|
||||
offset,
|
||||
regs: unsafe { Gpio::new_mmio_fixed() },
|
||||
regs: unsafe { Registers::new_mmio_fixed() },
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ impl LowLevelGpio {
|
||||
/// Set the MIO pin configuration with an unlocked SLCR.
|
||||
pub fn set_mio_pin_config_with_unlocked_slcr(
|
||||
&mut self,
|
||||
slcr: &mut zynq7000::slcr::MmioSlcr<'static>,
|
||||
slcr: &mut zynq7000::slcr::MmioRegisters<'static>,
|
||||
config: zynq7000::slcr::mio::Config,
|
||||
) {
|
||||
let raw_offset = self.offset.offset();
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//! also allows associating the pins, their modes and their IDs to the peripherals they are able to
|
||||
//! serve.
|
||||
use arbitrary_int::{u2, u3};
|
||||
use zynq7000::gpio::MmioGpio;
|
||||
use zynq7000::gpio::MmioRegisters;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct MuxConfig {
|
||||
@@ -291,7 +291,7 @@ pub struct Pins {
|
||||
}
|
||||
|
||||
impl Pins {
|
||||
pub const fn new(_mmio: MmioGpio) -> Self {
|
||||
pub const fn new(_mmio: MmioRegisters) -> Self {
|
||||
Self {
|
||||
mio0: unsafe { Pin::new() },
|
||||
mio1: unsafe { Pin::new() },
|
||||
|
||||
@@ -19,7 +19,7 @@ use mio::{MioPin, MuxConfig};
|
||||
use crate::gpio::ll::LowLevelGpio;
|
||||
use crate::{enable_amba_peripheral_clock, slcr::Slcr};
|
||||
pub use embedded_hal::digital::PinState;
|
||||
use zynq7000::{gpio::MmioGpio, slcr::reset::GpioClockReset};
|
||||
use zynq7000::{gpio::MmioRegisters, slcr::reset::GpioClockReset};
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("MIO pins 7 and 8 can only be output pins")]
|
||||
@@ -32,7 +32,7 @@ pub struct GpioPins {
|
||||
}
|
||||
|
||||
impl GpioPins {
|
||||
pub fn new(gpio: MmioGpio) -> Self {
|
||||
pub fn new(gpio: MmioRegisters) -> Self {
|
||||
enable_amba_peripheral_clock(crate::PeriphSelect::Gpio);
|
||||
Self {
|
||||
mio: mio::Pins::new(unsafe { gpio.clone() }),
|
||||
@@ -49,7 +49,7 @@ pub fn reset() {
|
||||
regs.reset_ctrl()
|
||||
.write_gpio(GpioClockReset::builder().with_gpio_cpu1x_rst(true).build());
|
||||
// Keep it in reset for one cycle.. not sure if this is necessary.
|
||||
cortex_ar::asm::nop();
|
||||
aarch32_cpu::asm::nop();
|
||||
regs.reset_ctrl()
|
||||
.write_gpio(GpioClockReset::builder().with_gpio_cpu1x_rst(false).build());
|
||||
});
|
||||
@@ -413,7 +413,7 @@ impl IoPeriphPin {
|
||||
/// Constructor to fully configure an IO peripheral pin with a specific MIO pin configuration.
|
||||
pub fn new_with_full_config_and_unlocked_slcr(
|
||||
pin: impl MioPin,
|
||||
slcr: &mut zynq7000::slcr::MmioSlcr<'static>,
|
||||
slcr: &mut zynq7000::slcr::MmioRegisters<'static>,
|
||||
config: zynq7000::slcr::mio::Config,
|
||||
) -> Self {
|
||||
let mut low_level = LowLevelGpio::new(PinOffset::Mio(pin.offset()));
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//!
|
||||
//! - [GTC ticks example](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/simple/src/bin/gtc-ticks.rs)
|
||||
//! - [Embassy Timer Driver](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/zynq7000-embassy/src/lib.rs)
|
||||
use zynq7000::gtc::MmioGlobalTimerCounter;
|
||||
use zynq7000::gtc::MmioRegisters;
|
||||
|
||||
use crate::{clocks::ArmClocks, time::Hertz};
|
||||
|
||||
@@ -14,7 +14,7 @@ use crate::{clocks::ArmClocks, time::Hertz};
|
||||
/// [frequency_to_ticks] function and the [embedded_hal::delay::DelayNs] implementation
|
||||
/// to work.
|
||||
pub struct GlobalTimerCounter {
|
||||
regs: MmioGlobalTimerCounter<'static>,
|
||||
regs: MmioRegisters<'static>,
|
||||
cpu_3x2x_clock: Option<Hertz>,
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ pub const fn frequency_to_ticks(clock: Hertz, frequency: Hertz) -> u32 {
|
||||
impl GlobalTimerCounter {
|
||||
/// Create a peripheral driver from a MMIO GTC block.
|
||||
#[inline]
|
||||
pub const fn new(_regs: MmioGlobalTimerCounter<'static>, clocks: &ArmClocks) -> Self {
|
||||
pub const fn new(_regs: MmioRegisters<'static>, clocks: &ArmClocks) -> Self {
|
||||
unsafe { Self::steal_fixed(Some(clocks.cpu_3x2x_clk())) }
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ impl GlobalTimerCounter {
|
||||
#[inline]
|
||||
pub const unsafe fn steal_fixed(cpu_3x2x_clk: Option<Hertz>) -> Self {
|
||||
Self {
|
||||
regs: unsafe { zynq7000::gtc::GlobalTimerCounter::new_mmio_fixed() },
|
||||
regs: unsafe { zynq7000::gtc::Registers::new_mmio_fixed() },
|
||||
cpu_3x2x_clock: cpu_3x2x_clk,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
use arbitrary_int::{u2, u3, u6};
|
||||
use embedded_hal::i2c::NoAcknowledgeSource;
|
||||
use zynq7000::{
|
||||
i2c::{Control, I2C_0_BASE_ADDR, I2C_1_BASE_ADDR, InterruptStatus, MmioI2c, TransferSize},
|
||||
i2c::{
|
||||
Control, I2C_0_BASE_ADDR, I2C_1_BASE_ADDR, InterruptStatus, MmioRegisters, TransferSize,
|
||||
},
|
||||
slcr::reset::DualClockReset,
|
||||
};
|
||||
|
||||
@@ -37,13 +39,13 @@ pub enum I2cId {
|
||||
}
|
||||
|
||||
pub trait PsI2c {
|
||||
fn reg_block(&self) -> MmioI2c<'static>;
|
||||
fn reg_block(&self) -> MmioRegisters<'static>;
|
||||
fn id(&self) -> Option<I2cId>;
|
||||
}
|
||||
|
||||
impl PsI2c for MmioI2c<'static> {
|
||||
impl PsI2c for MmioRegisters<'static> {
|
||||
#[inline]
|
||||
fn reg_block(&self) -> MmioI2c<'static> {
|
||||
fn reg_block(&self) -> MmioRegisters<'static> {
|
||||
unsafe { self.clone() }
|
||||
}
|
||||
|
||||
@@ -309,7 +311,7 @@ pub enum I2cConstructionError {
|
||||
InvalidPinConf,
|
||||
}
|
||||
pub struct I2c {
|
||||
regs: MmioI2c<'static>,
|
||||
regs: MmioRegisters<'static>,
|
||||
}
|
||||
|
||||
impl I2c {
|
||||
@@ -344,7 +346,7 @@ impl I2c {
|
||||
))
|
||||
}
|
||||
|
||||
pub fn new_generic(id: I2cId, mut regs: MmioI2c<'static>, clk_cfg: ClockConfig) -> Self {
|
||||
pub fn new_generic(id: I2cId, mut regs: MmioRegisters<'static>, clk_cfg: ClockConfig) -> Self {
|
||||
let periph_sel = match id {
|
||||
I2cId::I2c0 => crate::PeriphSelect::I2c0,
|
||||
I2cId::I2c1 => crate::PeriphSelect::I2c1,
|
||||
@@ -656,7 +658,7 @@ pub fn reset(id: I2cId) {
|
||||
// Keep it in reset for some cycles.. The TMR just mentions some small delay,
|
||||
// no idea what is meant with that.
|
||||
for _ in 0..3 {
|
||||
cortex_ar::asm::nop();
|
||||
aarch32_cpu::asm::nop();
|
||||
}
|
||||
regs.reset_ctrl().write_i2c(DualClockReset::DEFAULT);
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@ use core::sync::atomic::compiler_fence;
|
||||
use arbitrary_int::{u2, u3};
|
||||
pub use zynq7000::l2_cache::LatencyConfig;
|
||||
use zynq7000::l2_cache::{
|
||||
Associativity, AuxControl, Control, InterruptControl, MmioL2Cache, ReplacementPolicy, WaySize,
|
||||
Associativity, AuxControl, Control, InterruptControl, MmioRegisters, ReplacementPolicy, WaySize,
|
||||
};
|
||||
|
||||
use crate::slcr::Slcr;
|
||||
@@ -48,7 +48,7 @@ pub const DEFAULT_DATA_RAM_LATENCY: LatencyConfig = LatencyConfig::builder()
|
||||
pub const SLCR_L2C_CONFIG_MAGIC_VALUE: u32 = 0x00020202;
|
||||
|
||||
/// Similar to [init], but uses Xilinx/AMD defaults for the latency configurations.
|
||||
pub fn init_with_defaults(l2c_mmio: &mut MmioL2Cache<'static>) {
|
||||
pub fn init_with_defaults(l2c_mmio: &mut MmioRegisters<'static>) {
|
||||
init(l2c_mmio, DEFAULT_TAG_RAM_LATENCY, DEFAULT_DATA_RAM_LATENCY);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ pub fn init_with_defaults(l2c_mmio: &mut MmioL2Cache<'static>) {
|
||||
/// This function is based on the initialization sequence specified in the TRM p.94 and on
|
||||
/// the runtime initialization provided by Xilinx/AMD.
|
||||
pub fn init(
|
||||
l2c_mmio: &mut MmioL2Cache<'static>,
|
||||
l2c_mmio: &mut MmioRegisters<'static>,
|
||||
tag_ram_latency: LatencyConfig,
|
||||
data_ram_latency: LatencyConfig,
|
||||
) {
|
||||
|
||||
@@ -38,6 +38,7 @@ pub mod log;
|
||||
pub mod prelude;
|
||||
pub mod priv_tim;
|
||||
pub mod qspi;
|
||||
pub mod sdio;
|
||||
pub mod slcr;
|
||||
pub mod spi;
|
||||
pub mod time;
|
||||
@@ -117,7 +118,7 @@ impl BootMode {
|
||||
/// fixed SLCR block.
|
||||
pub fn new_from_regs() -> Self {
|
||||
// Safety: Only read a read-only register here.
|
||||
Self::new_with_reg(unsafe { zynq7000::slcr::Slcr::new_mmio_fixed() }.read_boot_mode())
|
||||
Self::new_with_reg(unsafe { zynq7000::slcr::Registers::new_mmio_fixed() }.read_boot_mode())
|
||||
}
|
||||
|
||||
fn new_with_reg(boot_mode_reg: BootModeRegister) -> Self {
|
||||
|
||||
@@ -20,7 +20,7 @@ pub mod uart_blocking {
|
||||
use core::cell::{Cell, RefCell, UnsafeCell};
|
||||
use embedded_io::Write as _;
|
||||
|
||||
use cortex_ar::register::Cpsr;
|
||||
use aarch32_cpu::register::Cpsr;
|
||||
use critical_section::Mutex;
|
||||
use log::{LevelFilter, Log, set_logger, set_max_level};
|
||||
|
||||
@@ -130,8 +130,8 @@ pub mod uart_blocking {
|
||||
fn log(&self, record: &log::Record) {
|
||||
if self.skip_in_isr.get() {
|
||||
match Cpsr::read().mode().unwrap() {
|
||||
cortex_ar::register::cpsr::ProcessorMode::Fiq
|
||||
| cortex_ar::register::cpsr::ProcessorMode::Irq => {
|
||||
aarch32_cpu::register::cpsr::ProcessorMode::Fiq
|
||||
| aarch32_cpu::register::cpsr::ProcessorMode::Irq => {
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
|
||||
@@ -14,7 +14,7 @@ static CORE_1_TIM_TAKEN: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
/// High-level CPU private timer driver.
|
||||
pub struct CpuPrivateTimer {
|
||||
regs: zynq7000::priv_tim::MmioCpuPrivateTimer<'static>,
|
||||
regs: zynq7000::priv_tim::MmioRegisters<'static>,
|
||||
cpu_3x2x_clock: Hertz,
|
||||
// Add this marker to explicitely opt-out of Send and Sync.
|
||||
//
|
||||
@@ -27,7 +27,7 @@ impl CpuPrivateTimer {
|
||||
///
|
||||
/// This function can only be called once for each given core.
|
||||
pub fn take(clocks: &ArmClocks) -> Option<Self> {
|
||||
let mpidr = cortex_ar::register::mpidr::Mpidr::read();
|
||||
let mpidr = aarch32_cpu::register::mpidr::Mpidr::read();
|
||||
let core = mpidr.0 & 0xff;
|
||||
if core != 0 && core != 1 {
|
||||
return None;
|
||||
@@ -49,7 +49,7 @@ impl CpuPrivateTimer {
|
||||
/// It also does not check the current core ID.
|
||||
pub fn steal(clocks: &ArmClocks) -> Self {
|
||||
Self {
|
||||
regs: unsafe { zynq7000::priv_tim::CpuPrivateTimer::new_mmio_fixed() },
|
||||
regs: unsafe { zynq7000::priv_tim::Registers::new_mmio_fixed() },
|
||||
cpu_3x2x_clock: clocks.cpu_3x2x_clk(),
|
||||
_not_send: PhantomData,
|
||||
}
|
||||
|
||||
@@ -284,15 +284,15 @@ impl ClockConfig {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct QspiLowLevel(zynq7000::qspi::MmioQspi<'static>);
|
||||
pub struct QspiLowLevel(zynq7000::qspi::MmioRegisters<'static>);
|
||||
|
||||
impl QspiLowLevel {
|
||||
#[inline]
|
||||
pub fn new(regs: zynq7000::qspi::MmioQspi<'static>) -> Self {
|
||||
pub fn new(regs: zynq7000::qspi::MmioRegisters<'static>) -> Self {
|
||||
Self(regs)
|
||||
}
|
||||
|
||||
pub fn regs(&mut self) -> &mut zynq7000::qspi::MmioQspi<'static> {
|
||||
pub fn regs(&mut self) -> &mut zynq7000::qspi::MmioRegisters<'static> {
|
||||
&mut self.0
|
||||
}
|
||||
|
||||
@@ -399,7 +399,7 @@ impl Qspi {
|
||||
Io3: Qspi0Io3Pin,
|
||||
Clock: Qspi0ClockPin,
|
||||
>(
|
||||
regs: zynq7000::qspi::MmioQspi<'static>,
|
||||
regs: zynq7000::qspi::MmioRegisters<'static>,
|
||||
clock_config: ClockConfig,
|
||||
mode: embedded_hal::spi::Mode,
|
||||
voltage: IoType,
|
||||
@@ -452,7 +452,7 @@ impl Qspi {
|
||||
Clock: Qspi0ClockPin,
|
||||
Feedback: FeedbackClockPin,
|
||||
>(
|
||||
regs: zynq7000::qspi::MmioQspi<'static>,
|
||||
regs: zynq7000::qspi::MmioRegisters<'static>,
|
||||
clock_config: ClockConfig,
|
||||
mode: embedded_hal::spi::Mode,
|
||||
voltage: IoType,
|
||||
@@ -479,7 +479,7 @@ impl Qspi {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn regs(&mut self) -> &mut zynq7000::qspi::MmioQspi<'static> {
|
||||
pub fn regs(&mut self) -> &mut zynq7000::qspi::MmioRegisters<'static> {
|
||||
&mut self.ll.0
|
||||
}
|
||||
|
||||
@@ -500,7 +500,7 @@ pub struct QspiIoMode {
|
||||
|
||||
impl QspiIoMode {
|
||||
#[inline]
|
||||
pub fn regs(&mut self) -> &mut zynq7000::qspi::MmioQspi<'static> {
|
||||
pub fn regs(&mut self) -> &mut zynq7000::qspi::MmioRegisters<'static> {
|
||||
&mut self.ll.0
|
||||
}
|
||||
|
||||
@@ -678,7 +678,7 @@ pub fn reset() {
|
||||
);
|
||||
// Keep it in reset for some cycles.
|
||||
for _ in 0..3 {
|
||||
cortex_ar::asm::nop();
|
||||
aarch32_cpu::asm::nop();
|
||||
}
|
||||
regs.reset_ctrl().write_lqspi(QspiResetControl::DEFAULT);
|
||||
});
|
||||
|
||||
452
zynq/zynq7000-hal/src/sdio.rs
Normal file
452
zynq/zynq7000-hal/src/sdio.rs
Normal file
@@ -0,0 +1,452 @@
|
||||
use arbitrary_int::{traits::Integer as _, u3, u6};
|
||||
use zynq7000::{
|
||||
sdio::{SDIO_BASE_ADDR_0, SDIO_BASE_ADDR_1, SdClockDivisor},
|
||||
slcr::{clocks::SrcSelIo, reset::DualRefAndClockReset},
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
use crate::gpio::mio::{
|
||||
Mio16, Mio17, Mio18, Mio19, Mio20, Mio21, Mio22, Mio23, Mio24, Mio25, Mio26, Mio27, Mio40,
|
||||
Mio41, Mio42, Mio43, Mio44, Mio45, Mio46, Mio47, Mio50, Mio51,
|
||||
};
|
||||
use crate::{
|
||||
clocks::{Clocks, IoClocks},
|
||||
gpio::{
|
||||
IoPeriphPin,
|
||||
mio::{
|
||||
Mio10, Mio11, Mio12, Mio13, Mio14, Mio15, Mio28, Mio29, Mio30, Mio31, Mio32, Mio33,
|
||||
Mio34, Mio35, Mio36, Mio37, Mio38, Mio39, Mio48, Mio49, MioPin, MuxConfig, Pin,
|
||||
},
|
||||
},
|
||||
slcr::Slcr,
|
||||
time::Hertz,
|
||||
};
|
||||
|
||||
pub const MUX_CONF: MuxConfig = MuxConfig::new_with_l3(u3::new(0b100));
|
||||
|
||||
pub trait Sdio0ClockPin: MioPin {}
|
||||
pub trait Sdio0CommandPin: MioPin {}
|
||||
pub trait Sdio0Data0Pin: MioPin {}
|
||||
pub trait Sdio0Data1Pin: MioPin {}
|
||||
pub trait Sdio0Data2Pin: MioPin {}
|
||||
pub trait Sdio0Data3Pin: MioPin {}
|
||||
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio0ClockPin for Pin<Mio16> {}
|
||||
impl Sdio0ClockPin for Pin<Mio28> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio0ClockPin for Pin<Mio40> {}
|
||||
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio0CommandPin for Pin<Mio17> {}
|
||||
impl Sdio0CommandPin for Pin<Mio29> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio0CommandPin for Pin<Mio41> {}
|
||||
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio0Data0Pin for Pin<Mio18> {}
|
||||
impl Sdio0Data0Pin for Pin<Mio30> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio0Data0Pin for Pin<Mio42> {}
|
||||
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio0Data1Pin for Pin<Mio19> {}
|
||||
impl Sdio0Data1Pin for Pin<Mio31> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio0Data1Pin for Pin<Mio43> {}
|
||||
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio0Data2Pin for Pin<Mio20> {}
|
||||
impl Sdio0Data2Pin for Pin<Mio32> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio0Data2Pin for Pin<Mio44> {}
|
||||
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio0Data3Pin for Pin<Mio21> {}
|
||||
impl Sdio0Data3Pin for Pin<Mio33> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio0Data3Pin for Pin<Mio45> {}
|
||||
|
||||
pub trait Sdio1ClockPin: MioPin {}
|
||||
pub trait Sdio1CommandPin: MioPin {}
|
||||
pub trait Sdio1Data0Pin: MioPin {}
|
||||
pub trait Sdio1Data1Pin: MioPin {}
|
||||
pub trait Sdio1Data2Pin: MioPin {}
|
||||
pub trait Sdio1Data3Pin: MioPin {}
|
||||
|
||||
impl Sdio1ClockPin for Pin<Mio12> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio1ClockPin for Pin<Mio24> {}
|
||||
impl Sdio1ClockPin for Pin<Mio36> {}
|
||||
impl Sdio1ClockPin for Pin<Mio48> {}
|
||||
|
||||
impl Sdio1CommandPin for Pin<Mio11> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio1CommandPin for Pin<Mio23> {}
|
||||
impl Sdio1CommandPin for Pin<Mio35> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio1CommandPin for Pin<Mio47> {}
|
||||
|
||||
impl Sdio1Data0Pin for Pin<Mio10> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio1Data0Pin for Pin<Mio22> {}
|
||||
impl Sdio1Data0Pin for Pin<Mio34> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio1Data0Pin for Pin<Mio46> {}
|
||||
|
||||
impl Sdio1Data1Pin for Pin<Mio13> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio1Data1Pin for Pin<Mio25> {}
|
||||
impl Sdio1Data1Pin for Pin<Mio37> {}
|
||||
impl Sdio1Data1Pin for Pin<Mio49> {}
|
||||
|
||||
impl Sdio1Data2Pin for Pin<Mio14> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio1Data2Pin for Pin<Mio26> {}
|
||||
impl Sdio1Data2Pin for Pin<Mio38> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio1Data2Pin for Pin<Mio50> {}
|
||||
|
||||
impl Sdio1Data2Pin for Pin<Mio15> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio1Data3Pin for Pin<Mio27> {}
|
||||
impl Sdio1Data3Pin for Pin<Mio39> {}
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
impl Sdio1Data3Pin for Pin<Mio51> {}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum SdioId {
|
||||
Sdio0,
|
||||
Sdio1,
|
||||
}
|
||||
|
||||
impl SdioId {
|
||||
/// Steal the ethernet register block for the given ethernet ID.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Circumvents ownership and safety guarantees of the HAL.
|
||||
pub const unsafe fn steal_regs(&self) -> zynq7000::sdio::MmioRegisters<'static> {
|
||||
unsafe {
|
||||
match self {
|
||||
SdioId::Sdio0 => zynq7000::sdio::Registers::new_mmio_fixed_0(),
|
||||
SdioId::Sdio1 => zynq7000::sdio::Registers::new_mmio_fixed_1(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SdioRegisters {
|
||||
fn reg_block(&self) -> zynq7000::sdio::MmioRegisters<'static>;
|
||||
fn id(&self) -> Option<SdioId>;
|
||||
}
|
||||
|
||||
impl SdioRegisters for zynq7000::sdio::MmioRegisters<'static> {
|
||||
#[inline]
|
||||
fn reg_block(&self) -> zynq7000::sdio::MmioRegisters<'static> {
|
||||
unsafe { self.clone() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn id(&self) -> Option<SdioId> {
|
||||
let base_addr = unsafe { self.ptr() } as usize;
|
||||
if base_addr == SDIO_BASE_ADDR_0 {
|
||||
return Some(SdioId::Sdio0);
|
||||
} else if base_addr == SDIO_BASE_ADDR_1 {
|
||||
return Some(SdioId::Sdio1);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SdioDivisors {
|
||||
/// Divisor which will be used during the initialization phase when ACMD41 is issued.
|
||||
///
|
||||
/// The SD card specification mentions that the clock needs to be between 100 and 400 kHz for
|
||||
/// that phase.
|
||||
pub divisor_init_phase: SdClockDivisor,
|
||||
/// Divisor for the regular data transfer phase. Common target speeds are 25 MHz or 50 MHz.
|
||||
pub divisor_normal: SdClockDivisor,
|
||||
}
|
||||
|
||||
impl SdioDivisors {
|
||||
// Calculate the SDIO clock divisors for the given SDIO reference clock and target speed.
|
||||
pub fn calculate(ref_clk: Hertz, target_speed: Hertz) -> Self {
|
||||
const INIT_CLOCK_HZ: u32 = 400_000;
|
||||
let divisor_select_from_value = |value: u32| match value {
|
||||
0..=1 => SdClockDivisor::Div1,
|
||||
2 => SdClockDivisor::Div2,
|
||||
3..=4 => SdClockDivisor::Div4,
|
||||
5..=8 => SdClockDivisor::Div8,
|
||||
9..=16 => SdClockDivisor::Div16,
|
||||
17..=32 => SdClockDivisor::Div32,
|
||||
33..=64 => SdClockDivisor::Div64,
|
||||
65..=128 => SdClockDivisor::Div128,
|
||||
129.. => SdClockDivisor::Div256,
|
||||
};
|
||||
Self {
|
||||
divisor_init_phase: divisor_select_from_value(ref_clk.raw().div_ceil(INIT_CLOCK_HZ)),
|
||||
divisor_normal: divisor_select_from_value(ref_clk.raw().div_ceil(target_speed.raw())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate divisors for a regular clock configuration which configures the IO clock as
|
||||
/// source.
|
||||
pub fn calculate_for_io_clock(io_clocks: &IoClocks, target_speed: Hertz) -> Self {
|
||||
Self::calculate(io_clocks.sdio_clk(), target_speed)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SdioClockConfig {
|
||||
/// Selects the source clock for the SDIO peripheral reference clock.
|
||||
pub src_sel: SrcSelIo,
|
||||
/// Selects the divisor which divies the source clock to create the SDIO peripheral
|
||||
/// reference clock.
|
||||
pub ref_clock_divisor: u6,
|
||||
/// The SDIO peripheral reference clock is divided again to create the SDIO clock.
|
||||
pub sdio_clock_divisors: SdioDivisors,
|
||||
}
|
||||
|
||||
impl SdioClockConfig {
|
||||
pub fn new(
|
||||
src_sel: SrcSelIo,
|
||||
ref_clock_divisor: u6,
|
||||
sdio_clock_divisors: SdioDivisors,
|
||||
) -> Self {
|
||||
Self {
|
||||
src_sel,
|
||||
ref_clock_divisor,
|
||||
sdio_clock_divisors,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn calculate_for_io_clock(
|
||||
io_clocks: &IoClocks,
|
||||
target_ref_clock: Hertz,
|
||||
target_sdio_speed: Hertz,
|
||||
) -> Option<Self> {
|
||||
let ref_clk = io_clocks.ref_clk();
|
||||
let io_ref_clock_divisor = ref_clk.raw().div_ceil(target_ref_clock.raw());
|
||||
if io_ref_clock_divisor > u6::MAX.as_u32() {
|
||||
return None;
|
||||
}
|
||||
let target_speed = ref_clk / io_ref_clock_divisor;
|
||||
|
||||
let sdio_clock_divisors = SdioDivisors::calculate(target_speed, target_sdio_speed);
|
||||
Some(Self {
|
||||
src_sel: SrcSelIo::IoPll,
|
||||
ref_clock_divisor: u6::new(io_ref_clock_divisor as u8),
|
||||
sdio_clock_divisors,
|
||||
})
|
||||
}
|
||||
}
|
||||
/// SDIO low-level interface.
|
||||
///
|
||||
/// Basic building block for higher-level abstraction.
|
||||
pub struct SdioLowLevel {
|
||||
id: SdioId,
|
||||
/// Register block. Direct public access is allowed to allow low-level operations.
|
||||
pub regs: zynq7000::sdio::MmioRegisters<'static>,
|
||||
}
|
||||
|
||||
impl SdioLowLevel {
|
||||
/// Create a new SDIO low-level interface from the given register block.
|
||||
///
|
||||
/// Returns [None] if the given registers block base address does not correspond to a valid
|
||||
/// Ethernet peripheral.
|
||||
pub fn new(regs: zynq7000::sdio::MmioRegisters<'static>) -> Option<Self> {
|
||||
let id = regs.id()?;
|
||||
Some(Self { id, regs })
|
||||
}
|
||||
|
||||
/// Common SDIO clock configuration routine which should be called once before using the SDIO.
|
||||
///
|
||||
/// This does NOT disable the clock, which should be done before changing the clock
|
||||
/// configuration. It also does NOT enable the clock.
|
||||
///
|
||||
/// It will configure the SDIO peripheral clock as well as initializing the SD clock frequency
|
||||
/// divisor based on the initial phase divider specified in the [SdioDivisors] field of the
|
||||
/// configuration.
|
||||
pub fn configure_clock(&mut self, clock_config: &SdioClockConfig) {
|
||||
unsafe {
|
||||
Slcr::with(|slcr| {
|
||||
slcr.clk_ctrl().modify_sdio_clk_ctrl(|mut val| {
|
||||
val.set_srcsel(clock_config.src_sel);
|
||||
val.set_divisor(clock_config.ref_clock_divisor);
|
||||
if self.id == SdioId::Sdio1 {
|
||||
val.set_clk_1_act(true);
|
||||
} else {
|
||||
val.set_clk_0_act(true);
|
||||
}
|
||||
val
|
||||
});
|
||||
});
|
||||
}
|
||||
self.configure_sd_clock_div_init_phase(&clock_config.sdio_clock_divisors);
|
||||
}
|
||||
|
||||
/// Configure the SD clock divisor for the initialization phase (400 kHz target clock).
|
||||
pub fn configure_sd_clock_div_init_phase(&mut self, divs: &SdioDivisors) {
|
||||
self.regs.modify_clock_timeout_sw_reset_control(|mut val| {
|
||||
val.set_sdclk_frequency_select(divs.divisor_init_phase);
|
||||
val
|
||||
});
|
||||
}
|
||||
|
||||
/// Configure the SD clock divisor for the normal phase (regular SDIO speed clock).
|
||||
pub fn configure_sd_clock_div_normal_phase(&mut self, divs: &SdioDivisors) {
|
||||
self.regs.modify_clock_timeout_sw_reset_control(|mut val| {
|
||||
val.set_sdclk_frequency_select(divs.divisor_normal);
|
||||
val
|
||||
});
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn enable_clock(&mut self) {
|
||||
self.regs.modify_clock_timeout_sw_reset_control(|mut val| {
|
||||
val.set_sd_clock_enable(true);
|
||||
val
|
||||
});
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn disable_clock(&mut self) {
|
||||
self.regs.modify_clock_timeout_sw_reset_control(|mut val| {
|
||||
val.set_sd_clock_enable(false);
|
||||
val
|
||||
});
|
||||
}
|
||||
|
||||
/// Reset the SDIO peripheral using the SLCR reset register for SDIO.
|
||||
pub fn reset(&mut self, cycles: u32) {
|
||||
reset(self.id, cycles);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Sdio {
|
||||
ll: SdioLowLevel,
|
||||
}
|
||||
|
||||
impl Sdio {
|
||||
pub fn new_for_sdio_0<
|
||||
Sdio0Clock: Sdio0ClockPin,
|
||||
Sdio0Command: Sdio0CommandPin,
|
||||
Sdio0Data0: Sdio0Data0Pin,
|
||||
Sdio0Data1: Sdio0Data1Pin,
|
||||
Sdio0Data2: Sdio0Data2Pin,
|
||||
Sdio0Data3: Sdio0Data3Pin,
|
||||
>(
|
||||
regs: zynq7000::sdio::MmioRegisters<'static>,
|
||||
clock_config: SdioClockConfig,
|
||||
clock_pin: Sdio0Clock,
|
||||
command_pin: Sdio0Command,
|
||||
data_pins: (Sdio0Data0, Sdio0Data1, Sdio0Data2, Sdio0Data3),
|
||||
) -> Option<Self> {
|
||||
let id = regs.id()?;
|
||||
if id != SdioId::Sdio1 {
|
||||
return None;
|
||||
}
|
||||
Some(Self::new(
|
||||
regs,
|
||||
clock_config,
|
||||
clock_pin,
|
||||
command_pin,
|
||||
data_pins,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn new_for_sdio_1<
|
||||
Sdio1Clock: Sdio1ClockPin,
|
||||
Sdio1Command: Sdio1CommandPin,
|
||||
Sdio1Data0: Sdio1Data0Pin,
|
||||
Sdio1Data1: Sdio1Data1Pin,
|
||||
Sdio1Data2: Sdio1Data2Pin,
|
||||
Sdio1Data3: Sdio1Data3Pin,
|
||||
>(
|
||||
regs: zynq7000::sdio::MmioRegisters<'static>,
|
||||
clock_config: SdioClockConfig,
|
||||
clock_pin: Sdio1Clock,
|
||||
command_pin: Sdio1Command,
|
||||
data_pins: (Sdio1Data0, Sdio1Data1, Sdio1Data2, Sdio1Data3),
|
||||
) -> Option<Self> {
|
||||
let id = regs.id()?;
|
||||
if id != SdioId::Sdio1 {
|
||||
return None;
|
||||
}
|
||||
Some(Self::new(
|
||||
regs,
|
||||
clock_config,
|
||||
clock_pin,
|
||||
command_pin,
|
||||
data_pins,
|
||||
))
|
||||
}
|
||||
|
||||
fn new(
|
||||
regs: zynq7000::sdio::MmioRegisters<'static>,
|
||||
clock_config: SdioClockConfig,
|
||||
clock_pin: impl MioPin,
|
||||
command_pin: impl MioPin,
|
||||
data_pins: (impl MioPin, impl MioPin, impl MioPin, impl MioPin),
|
||||
) -> Self {
|
||||
let mut ll = SdioLowLevel::new(regs).unwrap();
|
||||
Self::initialize(&mut ll, &clock_config);
|
||||
IoPeriphPin::new(clock_pin, MUX_CONF, None);
|
||||
IoPeriphPin::new(command_pin, MUX_CONF, None);
|
||||
IoPeriphPin::new(data_pins.0, MUX_CONF, None);
|
||||
IoPeriphPin::new(data_pins.1, MUX_CONF, None);
|
||||
IoPeriphPin::new(data_pins.2, MUX_CONF, None);
|
||||
IoPeriphPin::new(data_pins.3, MUX_CONF, None);
|
||||
Self { ll }
|
||||
}
|
||||
|
||||
fn initialize(ll: &mut SdioLowLevel, clock_config: &SdioClockConfig) {
|
||||
ll.reset(10);
|
||||
// TODO: SW reset for all?
|
||||
// TODO: Internal clock?
|
||||
ll.disable_clock();
|
||||
ll.configure_clock(clock_config);
|
||||
ll.enable_clock();
|
||||
|
||||
// TODO: There is probably some other configuration necessary.. the docs really are not
|
||||
// complete here..
|
||||
unsafe {}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn regs(&mut self) -> &mut zynq7000::sdio::MmioRegisters<'static> {
|
||||
&mut self.ll.regs
|
||||
}
|
||||
}
|
||||
|
||||
/// Reset the SDIO peripheral using the SLCR reset register for SDIO.
|
||||
///
|
||||
/// Please note that this function will interfere with an already configured
|
||||
/// SDIO instance.
|
||||
#[inline]
|
||||
pub fn reset(id: SdioId, cycles: u32) {
|
||||
let assert_reset = match id {
|
||||
SdioId::Sdio0 => DualRefAndClockReset::builder()
|
||||
.with_periph1_ref_rst(false)
|
||||
.with_periph0_ref_rst(true)
|
||||
.with_periph1_cpu1x_rst(false)
|
||||
.with_periph0_cpu1x_rst(true)
|
||||
.build(),
|
||||
SdioId::Sdio1 => DualRefAndClockReset::builder()
|
||||
.with_periph1_ref_rst(true)
|
||||
.with_periph0_ref_rst(false)
|
||||
.with_periph1_cpu1x_rst(true)
|
||||
.with_periph0_cpu1x_rst(false)
|
||||
.build(),
|
||||
};
|
||||
unsafe {
|
||||
Slcr::with(|regs| {
|
||||
regs.reset_ctrl().write_sdio(assert_reset);
|
||||
// Keep it in reset for a few cycle.. not sure if this is necessary.
|
||||
for _ in 0..cycles {
|
||||
aarch32_cpu::asm::nop();
|
||||
}
|
||||
regs.reset_ctrl().write_sdio(DualRefAndClockReset::DEFAULT);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
//! # System Level Control Register (SLCR) module
|
||||
use zynq7000::slcr::MmioSlcr;
|
||||
use zynq7000::slcr::MmioRegisters;
|
||||
|
||||
pub const LOCK_KEY: u32 = 0x767B;
|
||||
pub const UNLOCK_KEY: u32 = 0xDF0D;
|
||||
|
||||
pub struct Slcr(zynq7000::slcr::MmioSlcr<'static>);
|
||||
pub struct Slcr(zynq7000::slcr::MmioRegisters<'static>);
|
||||
|
||||
impl Slcr {
|
||||
/// Modify the SLCR register.
|
||||
@@ -14,15 +14,15 @@ impl Slcr {
|
||||
/// This method unsafely steals the SLCR MMIO block and then calls a user provided function
|
||||
/// with the [SLCR MMIO][MmioSlcr] block as an input argument. It is the user's responsibility
|
||||
/// that the SLCR is not used concurrently in a way which leads to data races.
|
||||
pub unsafe fn with<F: FnOnce(&mut MmioSlcr<'static>)>(f: F) {
|
||||
let mut slcr = unsafe { zynq7000::slcr::Slcr::new_mmio_fixed() };
|
||||
pub unsafe fn with<F: FnOnce(&mut MmioRegisters<'static>)>(f: F) {
|
||||
let mut slcr = unsafe { zynq7000::slcr::Registers::new_mmio_fixed() };
|
||||
slcr.write_unlock(UNLOCK_KEY);
|
||||
f(&mut slcr);
|
||||
slcr.write_lock(LOCK_KEY);
|
||||
}
|
||||
|
||||
/// Create a new SLCR peripheral wrapper.
|
||||
pub fn new(slcr: zynq7000::slcr::MmioSlcr<'static>) -> Self {
|
||||
pub fn new(slcr: zynq7000::slcr::MmioRegisters<'static>) -> Self {
|
||||
Self(slcr)
|
||||
}
|
||||
|
||||
@@ -34,13 +34,13 @@ impl Slcr {
|
||||
/// responsibility that these wrappers are not used concurrently in a way which leads to
|
||||
/// data races.
|
||||
pub unsafe fn steal() -> Self {
|
||||
Self::new(unsafe { zynq7000::slcr::Slcr::new_mmio_fixed() })
|
||||
Self::new(unsafe { zynq7000::slcr::Registers::new_mmio_fixed() })
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the SLCR MMIO block.
|
||||
///
|
||||
/// The MMIO block will not be unlocked. However, the registers can still be read.
|
||||
pub fn regs(&self) -> &MmioSlcr<'static> {
|
||||
pub fn regs(&self) -> &MmioRegisters<'static> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ impl Slcr {
|
||||
/// This method unlocks the SLCR registers and then calls a user provided function
|
||||
/// with the [SLCR MMIO][MmioSlcr] block as an input argument. This allows the user
|
||||
/// to safely modify the SLCR registers. The SLCR will be locked afte the operation.
|
||||
pub fn modify<F: FnMut(&mut MmioSlcr)>(&mut self, mut f: F) {
|
||||
pub fn modify<F: FnMut(&mut MmioRegisters)>(&mut self, mut f: F) {
|
||||
self.0.write_unlock(UNLOCK_KEY);
|
||||
f(&mut self.0);
|
||||
self.0.write_lock(LOCK_KEY);
|
||||
|
||||
@@ -25,8 +25,8 @@ pub use embedded_hal::spi::Mode;
|
||||
use embedded_hal::spi::SpiBus as _;
|
||||
use zynq7000::slcr::reset::DualRefAndClockReset;
|
||||
use zynq7000::spi::{
|
||||
BaudDivSel, DelayControl, FifoWrite, InterruptControl, InterruptMask, InterruptStatus, MmioSpi,
|
||||
SPI_0_BASE_ADDR, SPI_1_BASE_ADDR,
|
||||
BaudDivSel, DelayControl, FifoWrite, InterruptControl, InterruptMask, InterruptStatus,
|
||||
MmioRegisters, SPI_0_BASE_ADDR, SPI_1_BASE_ADDR,
|
||||
};
|
||||
|
||||
pub const FIFO_DEPTH: usize = 128;
|
||||
@@ -42,13 +42,13 @@ pub enum SpiId {
|
||||
}
|
||||
|
||||
pub trait PsSpi {
|
||||
fn reg_block(&self) -> MmioSpi<'static>;
|
||||
fn reg_block(&self) -> MmioRegisters<'static>;
|
||||
fn id(&self) -> Option<SpiId>;
|
||||
}
|
||||
|
||||
impl PsSpi for MmioSpi<'static> {
|
||||
impl PsSpi for MmioRegisters<'static> {
|
||||
#[inline]
|
||||
fn reg_block(&self) -> MmioSpi<'static> {
|
||||
fn reg_block(&self) -> MmioRegisters<'static> {
|
||||
unsafe { self.clone() }
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ impl Config {
|
||||
/// Thin re-usable low-level helper to interface with the SPI.
|
||||
pub struct SpiLowLevel {
|
||||
id: SpiId,
|
||||
regs: zynq7000::spi::MmioSpi<'static>,
|
||||
regs: zynq7000::spi::MmioRegisters<'static>,
|
||||
}
|
||||
|
||||
impl SpiLowLevel {
|
||||
@@ -406,8 +406,8 @@ impl SpiLowLevel {
|
||||
pub unsafe fn steal(id: SpiId) -> Self {
|
||||
let regs = unsafe {
|
||||
match id {
|
||||
SpiId::Spi0 => zynq7000::spi::Spi::new_mmio_fixed_0(),
|
||||
SpiId::Spi1 => zynq7000::spi::Spi::new_mmio_fixed_1(),
|
||||
SpiId::Spi0 => zynq7000::spi::Registers::new_mmio_fixed_0(),
|
||||
SpiId::Spi1 => zynq7000::spi::Registers::new_mmio_fixed_1(),
|
||||
}
|
||||
};
|
||||
Self { id, regs }
|
||||
@@ -808,7 +808,7 @@ impl Spi {
|
||||
|
||||
pub fn new_generic_unchecked(
|
||||
id: SpiId,
|
||||
regs: MmioSpi<'static>,
|
||||
regs: MmioRegisters<'static>,
|
||||
clocks: &IoClocks,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
@@ -863,7 +863,7 @@ impl Spi {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn regs(&mut self) -> &mut MmioSpi<'static> {
|
||||
pub fn regs(&mut self) -> &mut MmioRegisters<'static> {
|
||||
&mut self.inner.regs
|
||||
}
|
||||
|
||||
@@ -1119,7 +1119,7 @@ pub fn reset(id: SpiId) {
|
||||
// Keep it in reset for some cycles.. The TMR just mentions some small delay,
|
||||
// no idea what is meant with that.
|
||||
for _ in 0..3 {
|
||||
cortex_ar::asm::nop();
|
||||
aarch32_cpu::asm::nop();
|
||||
}
|
||||
regs.reset_ctrl().write_spi(DualRefAndClockReset::DEFAULT);
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
use core::convert::Infallible;
|
||||
|
||||
use arbitrary_int::{prelude::*, u3, u4};
|
||||
use zynq7000::ttc::{MmioTtc, TTC_0_BASE_ADDR, TTC_1_BASE_ADDR};
|
||||
use zynq7000::ttc::{MmioRegisters, TTC_0_BASE_ADDR, TTC_1_BASE_ADDR};
|
||||
|
||||
#[cfg(not(feature = "7z010-7z007s-clg225"))]
|
||||
use crate::gpio::mio::{Mio16, Mio17, Mio18, Mio19, Mio40, Mio41, Mio42, Mio43};
|
||||
@@ -37,13 +37,13 @@ pub enum ChannelId {
|
||||
}
|
||||
|
||||
pub trait PsTtc {
|
||||
fn reg_block(&self) -> MmioTtc<'static>;
|
||||
fn reg_block(&self) -> MmioRegisters<'static>;
|
||||
fn id(&self) -> Option<TtcId>;
|
||||
}
|
||||
|
||||
impl PsTtc for MmioTtc<'static> {
|
||||
impl PsTtc for MmioRegisters<'static> {
|
||||
#[inline]
|
||||
fn reg_block(&self) -> MmioTtc<'static> {
|
||||
fn reg_block(&self) -> MmioRegisters<'static> {
|
||||
unsafe { self.clone() }
|
||||
}
|
||||
|
||||
@@ -152,12 +152,12 @@ impl Ttc {
|
||||
}
|
||||
|
||||
pub struct TtcChannel {
|
||||
regs: MmioTtc<'static>,
|
||||
regs: MmioRegisters<'static>,
|
||||
id: ChannelId,
|
||||
}
|
||||
|
||||
impl TtcChannel {
|
||||
pub fn regs_mut(&mut self) -> &mut MmioTtc<'static> {
|
||||
pub fn regs_mut(&mut self) -> &mut MmioRegisters<'static> {
|
||||
&mut self.regs
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ use libm::round;
|
||||
use zynq7000::{
|
||||
slcr::reset::DualRefAndClockReset,
|
||||
uart::{
|
||||
BaudRateDivisor, Baudgen, ChMode, ClockSelect, FifoTrigger, InterruptControl, MmioUart,
|
||||
Mode, UART_0_BASE, UART_1_BASE,
|
||||
BaudRateDivisor, Baudgen, ChMode, ClockSelect, FifoTrigger, InterruptControl,
|
||||
MmioRegisters, Mode, UART_0_BASE, UART_1_BASE,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -60,13 +60,13 @@ pub enum UartId {
|
||||
}
|
||||
|
||||
pub trait PsUart {
|
||||
fn reg_block(&self) -> MmioUart<'static>;
|
||||
fn reg_block(&self) -> MmioRegisters<'static>;
|
||||
fn uart_id(&self) -> Option<UartId>;
|
||||
}
|
||||
|
||||
impl PsUart for MmioUart<'static> {
|
||||
impl PsUart for MmioRegisters<'static> {
|
||||
#[inline]
|
||||
fn reg_block(&self) -> MmioUart<'static> {
|
||||
fn reg_block(&self) -> MmioRegisters<'static> {
|
||||
unsafe { self.clone() }
|
||||
}
|
||||
|
||||
@@ -87,10 +87,10 @@ impl UartId {
|
||||
/// # Safety
|
||||
///
|
||||
/// Circumvents ownership and safety guarantees by the HAL.
|
||||
pub const unsafe fn regs(&self) -> MmioUart<'static> {
|
||||
pub const unsafe fn regs(&self) -> MmioRegisters<'static> {
|
||||
match self {
|
||||
UartId::Uart0 => unsafe { zynq7000::uart::Uart::new_mmio_fixed_0() },
|
||||
UartId::Uart1 => unsafe { zynq7000::uart::Uart::new_mmio_fixed_1() },
|
||||
UartId::Uart0 => unsafe { zynq7000::uart::Registers::new_mmio_fixed_0() },
|
||||
UartId::Uart1 => unsafe { zynq7000::uart::Registers::new_mmio_fixed_1() },
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -469,7 +469,7 @@ impl Uart {
|
||||
/// It does not do any pin checks and resource control. It is recommended to use the other
|
||||
/// constructors instead.
|
||||
pub fn new_generic_unchecked(
|
||||
mut reg_block: MmioUart<'static>,
|
||||
mut reg_block: MmioRegisters<'static>,
|
||||
uart_id: UartId,
|
||||
cfg: Config,
|
||||
) -> Uart {
|
||||
@@ -558,7 +558,7 @@ impl Uart {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn regs(&mut self) -> &mut MmioUart<'static> {
|
||||
pub const fn regs(&mut self) -> &mut MmioRegisters<'static> {
|
||||
&mut self.rx.regs
|
||||
}
|
||||
|
||||
@@ -645,7 +645,7 @@ pub fn reset(id: UartId) {
|
||||
Slcr::with(|regs| {
|
||||
regs.reset_ctrl().write_uart(assert_reset);
|
||||
// Keep it in reset for one cycle.. not sure if this is necessary.
|
||||
cortex_ar::asm::nop();
|
||||
aarch32_cpu::asm::nop();
|
||||
regs.reset_ctrl().write_uart(DualRefAndClockReset::DEFAULT);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use core::convert::Infallible;
|
||||
|
||||
use arbitrary_int::prelude::*;
|
||||
use zynq7000::uart::{InterruptControl, InterruptStatus, MmioUart};
|
||||
use zynq7000::uart::{InterruptControl, InterruptStatus, MmioRegisters};
|
||||
|
||||
use super::FIFO_DEPTH;
|
||||
|
||||
pub struct Rx {
|
||||
pub(crate) regs: MmioUart<'static>,
|
||||
pub(crate) regs: MmioRegisters<'static>,
|
||||
}
|
||||
// TODO: Remove once this is impelemnted for MmioUart
|
||||
unsafe impl Send for Rx {}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use core::convert::Infallible;
|
||||
|
||||
use zynq7000::uart::{Fifo, InterruptControl, InterruptStatus, MmioUart};
|
||||
use zynq7000::uart::{Fifo, InterruptControl, InterruptStatus, MmioRegisters};
|
||||
|
||||
use super::UartId;
|
||||
|
||||
pub struct Tx {
|
||||
pub(crate) regs: MmioUart<'static>,
|
||||
pub(crate) regs: MmioRegisters<'static>,
|
||||
pub(crate) idx: UartId,
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ impl Tx {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn regs(&mut self) -> &mut MmioUart<'static> {
|
||||
pub const fn regs(&mut self) -> &mut MmioRegisters<'static> {
|
||||
&mut self.regs
|
||||
}
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ categories = ["embedded", "no-std", "hardware-support"]
|
||||
|
||||
[dependencies]
|
||||
thiserror = { version = "2", default-features = false }
|
||||
cortex-ar = { version = "0.3" }
|
||||
aarch32-cpu = { version = "0.1" }
|
||||
|
||||
[build-dependencies]
|
||||
arm-targets = { version = "0.3" }
|
||||
arm-targets = { version = "0.4" }
|
||||
|
||||
[features]
|
||||
tools = []
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
#![no_std]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
use core::cell::UnsafeCell;
|
||||
use cortex_ar::mmu::L1Section;
|
||||
use aarch32_cpu::mmu::L1Section;
|
||||
#[cfg(all(not(feature = "tools"), arm_profile = "a"))]
|
||||
use cortex_ar::{
|
||||
use aarch32_cpu::{
|
||||
asm::{dsb, isb},
|
||||
cache::clean_and_invalidate_l1_data_cache,
|
||||
mmu::SectionAttributes,
|
||||
register::{BpIAll, TlbIAll},
|
||||
};
|
||||
use core::cell::UnsafeCell;
|
||||
|
||||
pub const NUM_L1_PAGE_TABLE_ENTRIES: usize = 4096;
|
||||
|
||||
|
||||
@@ -11,17 +11,17 @@ keywords = ["no-std", "rt", "cortex-a", "amd", "zynq7000"]
|
||||
categories = ["embedded", "no-std", "hardware-support"]
|
||||
|
||||
[dependencies]
|
||||
cortex-a-rt = { version = "0.1", optional = true, features = ["vfp-dp"] }
|
||||
cortex-ar = { version = "0.3" }
|
||||
aarch32-rt = { version = "0.1", optional = true, features = ["fpu-d32"] }
|
||||
aarch32-cpu = { version = "0.1" }
|
||||
arbitrary-int = "2"
|
||||
zynq7000-mmu = { path = "../zynq7000-mmu", version = "0.1" }
|
||||
|
||||
[build-dependencies]
|
||||
arm-targets = { version = "0.3" }
|
||||
arm-targets = { version = "0.4" }
|
||||
|
||||
[features]
|
||||
default = ["rt"]
|
||||
rt = ["dep:cortex-a-rt"]
|
||||
rt = ["dep:aarch32-rt"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["armv7a-none-eabihf"]
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#![no_std]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#[cfg(all(feature = "rt", arm_profile = "a"))]
|
||||
pub use cortex_a_rt::*;
|
||||
pub use aarch32_rt::*;
|
||||
|
||||
#[cfg(feature = "rt")]
|
||||
use zynq7000_mmu::L1TableWrapper;
|
||||
|
||||
@@ -84,10 +84,10 @@ pub mod segments {
|
||||
}
|
||||
|
||||
pub mod section_attrs {
|
||||
use arbitrary_int::u4;
|
||||
use cortex_ar::mmu::{
|
||||
use aarch32_cpu::mmu::{
|
||||
AccessPermissions, CacheableMemoryAttribute, MemoryRegionAttributes, SectionAttributes,
|
||||
};
|
||||
use arbitrary_int::u4;
|
||||
|
||||
pub const DEFAULT_DOMAIN: u4 = u4::new(0b0000);
|
||||
// DDR is in different domain, but all domains are set as manager domains during run-time
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! This file was auto-generated by table-gen.rs
|
||||
use crate::mmu::section_attrs;
|
||||
use cortex_ar::mmu::L1Section;
|
||||
use aarch32_cpu::mmu::L1Section;
|
||||
use zynq7000_mmu::L1Table;
|
||||
|
||||
/// MMU Level 1 Page table.
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
//! but does NOT provide the L2 cache initialization.
|
||||
//!
|
||||
//! The boot routine includes stack, MMU and .bss/.data section initialization.
|
||||
use cortex_a_rt as _;
|
||||
use cortex_ar::register::{Cpsr, cpsr::ProcessorMode};
|
||||
use aarch32_cpu::register::{Cpsr, cpsr::ProcessorMode};
|
||||
use aarch32_rt as _;
|
||||
|
||||
// Start-up code for Armv7-A
|
||||
//
|
||||
@@ -16,17 +16,6 @@ core::arch::global_asm!(
|
||||
.set PSS_L2CC_BASE_ADDR, 0xF8F02000
|
||||
.set PSS_SLCR_BASE_ADDR, 0xF8000000
|
||||
|
||||
.set RESERVED, 0x0fffff00
|
||||
.set LRemap, 0xFE00000F /* set the base address of the peripheral block as not shared */
|
||||
.set L2CCWay, (PSS_L2CC_BASE_ADDR + 0x077C) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CACHE_INVLD_WAY_OFFSET)*/
|
||||
.set L2CCSync, (PSS_L2CC_BASE_ADDR + 0x0730) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CACHE_SYNC_OFFSET)*/
|
||||
.set L2CCCrtl, (PSS_L2CC_BASE_ADDR + 0x0100) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CNTRL_OFFSET)*/
|
||||
.set L2CCAuxCrtl, (PSS_L2CC_BASE_ADDR + 0x0104) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_AUX_CNTRL_OFFSET)*/
|
||||
.set L2CCTAGLatReg, (PSS_L2CC_BASE_ADDR + 0x0108) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_TAG_RAM_CNTRL_OFFSET)*/
|
||||
.set L2CCDataLatReg, (PSS_L2CC_BASE_ADDR + 0x010C) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_DATA_RAM_CNTRL_OFFSET)*/
|
||||
.set L2CCIntClear, (PSS_L2CC_BASE_ADDR + 0x0220) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_IAR_OFFSET)*/
|
||||
.set L2CCIntRaw, (PSS_L2CC_BASE_ADDR + 0x021C) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_ISR_OFFSET)*/
|
||||
|
||||
.set SLCRlockReg, (PSS_SLCR_BASE_ADDR + 0x04) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_LOCK_OFFSET)*/
|
||||
.set SLCRUnlockReg, (PSS_SLCR_BASE_ADDR + 0x08) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_UNLOCK_OFFSET)*/
|
||||
.set SLCRL2cRamReg, (PSS_SLCR_BASE_ADDR + 0xA1C) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_L2C_RAM_OFFSET)*/
|
||||
@@ -36,12 +25,6 @@ core::arch::global_asm!(
|
||||
.set CRValMmuCac, 0b01000000000101 /* Enable IDC, and MMU */
|
||||
.set CRValHiVectorAddr, 0b10000000000000 /* Set the Vector address to high, 0xFFFF0000 */
|
||||
|
||||
.set L2CCAuxControl, 0x72360000 /* Enable all prefetching, Cache replacement policy, Parity enable,
|
||||
Event monitor bus enable and Way Size (64 KB) */
|
||||
.set L2CCControl, 0x01 /* Enable L2CC */
|
||||
.set L2CCTAGLatency, 0x0111 /* latency for TAG RAM */
|
||||
.set L2CCDataLatency, 0x0121 /* latency for DATA RAM */
|
||||
|
||||
.set SLCRlockKey, 0x767B /* SLCR lock key */
|
||||
.set SLCRUnlockKey, 0xDF0D /* SLCR unlock key */
|
||||
.set SLCRL2cRamConfig, 0x00020202 /* SLCR L2C ram configuration */
|
||||
|
||||
@@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
# [unreleased]
|
||||
|
||||
- Renamed all register blocks to `Registers` to subblocks to `<Subblock>Registers`
|
||||
- Added SDIO registers
|
||||
|
||||
# [v0.1.1] 2025-10-09
|
||||
|
||||
Documentation fix
|
||||
|
||||
@@ -728,7 +728,7 @@ use regs::*;
|
||||
/// DDR controller register access.
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct DdrController {
|
||||
pub struct Registers {
|
||||
ddrc_ctrl: DdrcControl,
|
||||
two_rank_cfg: TwoRankConfig,
|
||||
hpr_queue_ctrl: LprHprQueueControl,
|
||||
@@ -871,9 +871,9 @@ pub struct DdrController {
|
||||
lpddr_ctrl_3: LpddrControl3,
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<DdrController>(), 0x2B8);
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Registers>(), 0x2B8);
|
||||
|
||||
impl DdrController {
|
||||
impl Registers {
|
||||
/// Create a new DDR MMIO instance for the DDR controller at address [DDRC_BASE_ADDR].
|
||||
///
|
||||
/// # Safety
|
||||
@@ -881,7 +881,7 @@ impl DdrController {
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub const unsafe fn new_mmio_fixed() -> MmioDdrController<'static> {
|
||||
pub const unsafe fn new_mmio_fixed() -> MmioRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(DDRC_BASE_ADDR) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ pub struct Status {
|
||||
/// Device configuration register access.
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct DevCfg {
|
||||
pub struct Registers {
|
||||
control: Control,
|
||||
lock: Lock,
|
||||
config: Config,
|
||||
@@ -284,12 +284,12 @@ pub struct DevCfg {
|
||||
|
||||
// Included here but not exposed to avoid providing multiple references to the same peripheral.
|
||||
// Exposed in [crate::xadc].
|
||||
_xadc: crate::xadc::XAdc,
|
||||
_xadc: crate::xadc::Registers,
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<DevCfg>(), 0x11C);
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Registers>(), 0x11C);
|
||||
|
||||
impl DevCfg {
|
||||
impl Registers {
|
||||
/// Create a new DevCfg MMIO instance for for device configuration peripheral at address
|
||||
/// [DEVCFG_BASE_ADDR].
|
||||
///
|
||||
@@ -298,7 +298,7 @@ impl DevCfg {
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub unsafe fn new_mmio_fixed() -> MmioDevCfg<'static> {
|
||||
pub unsafe fn new_mmio_fixed() -> MmioRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(DEVCFG_BASE_ADDR) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,7 +421,7 @@ pub struct MatchRegister {
|
||||
/// Gigabit Ethernet Controller (GEM) register access.
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct Ethernet {
|
||||
pub struct Registers {
|
||||
net_ctrl: NetworkControl,
|
||||
net_cfg: NetworkConfig,
|
||||
#[mmio(PureRead)]
|
||||
@@ -475,7 +475,7 @@ pub struct Ethernet {
|
||||
design_cfg_5: u32,
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Ethernet>(), 0x294);
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Registers>(), 0x294);
|
||||
|
||||
/// Ethernet statistics registers
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
@@ -571,7 +571,7 @@ pub struct Statistics {
|
||||
rx_udp_checksum_errors: u32,
|
||||
}
|
||||
|
||||
impl Ethernet {
|
||||
impl Registers {
|
||||
/// Create a new Gigabit Ethernet MMIO instance for GEM 0 at address [GEM_0_BASE_ADDR].
|
||||
///
|
||||
/// # Safety
|
||||
@@ -579,7 +579,7 @@ impl Ethernet {
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub const unsafe fn new_mmio_fixed_0() -> MmioEthernet<'static> {
|
||||
pub const unsafe fn new_mmio_fixed_0() -> MmioRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(GEM_0_BASE_ADDR) }
|
||||
}
|
||||
|
||||
@@ -590,7 +590,7 @@ impl Ethernet {
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub const unsafe fn new_mmio_fixed_1() -> MmioEthernet<'static> {
|
||||
pub const unsafe fn new_mmio_fixed_1() -> MmioRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(GEM_1_BASE_ADDR) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ pub type Typer = TypeRegister;
|
||||
/// GIC Distributor registers.
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C, align(8))]
|
||||
pub struct GicDistributor {
|
||||
pub struct GicDistributorRegisters {
|
||||
/// Distributor Control Register
|
||||
pub dcr: DistributorControlRegister,
|
||||
/// Interrupt Controller Type Register
|
||||
@@ -109,9 +109,9 @@ pub struct GicDistributor {
|
||||
pub cidr: [u32; 4],
|
||||
}
|
||||
|
||||
const_assert_eq!(core::mem::size_of::<GicDistributor>(), 0x1000);
|
||||
const_assert_eq!(core::mem::size_of::<GicDistributorRegisters>(), 0x1000);
|
||||
|
||||
impl GicDistributor {
|
||||
impl GicDistributorRegisters {
|
||||
/// Create a new Global Interrupt Controller Distributor MMIO instance at the fixed address of
|
||||
/// the processing system.
|
||||
///
|
||||
@@ -121,7 +121,7 @@ impl GicDistributor {
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
#[inline]
|
||||
pub const unsafe fn new_mmio_fixed() -> MmioGicDistributor<'static> {
|
||||
pub const unsafe fn new_mmio_fixed() -> MmioGicDistributorRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(GICD_BASE_ADDR) }
|
||||
}
|
||||
}
|
||||
@@ -160,7 +160,7 @@ pub struct InterruptSignalRegister {
|
||||
/// GIC CPU interface registers.
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C, align(8))]
|
||||
pub struct GicCpuInterface {
|
||||
pub struct GicCpuInterfaceRegisters {
|
||||
/// CPU Interface Control Register (ICR).
|
||||
pub icr: InterfaceControl,
|
||||
/// Interrupt Priority Mask Register.
|
||||
@@ -183,9 +183,9 @@ pub struct GicCpuInterface {
|
||||
pub iidr: u32,
|
||||
}
|
||||
|
||||
const_assert_eq!(core::mem::size_of::<GicCpuInterface>(), 0x100);
|
||||
const_assert_eq!(core::mem::size_of::<GicCpuInterfaceRegisters>(), 0x100);
|
||||
|
||||
impl GicCpuInterface {
|
||||
impl GicCpuInterfaceRegisters {
|
||||
/// Create a new Global Interrupt Controller CPU MMIO instance at the fixed address of the
|
||||
/// processing system.
|
||||
///
|
||||
@@ -195,7 +195,7 @@ impl GicCpuInterface {
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
#[inline]
|
||||
pub const unsafe fn new_mmio_fixed() -> MmioGicCpuInterface<'static> {
|
||||
pub const unsafe fn new_mmio_fixed() -> MmioGicCpuInterfaceRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(GICC_BASE_ADDR) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ pub struct MaskedOutput {
|
||||
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct BankControl {
|
||||
pub struct BankControlRegisters {
|
||||
/// Direction mode
|
||||
dirm: u32,
|
||||
/// Output enable
|
||||
@@ -38,7 +38,7 @@ pub struct BankControl {
|
||||
/// GPIO register access.
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct Gpio {
|
||||
pub struct Registers {
|
||||
/// Maskable output data (GPIO bank 0, MIO, lower 16 bits)
|
||||
masked_out_0_lsw: MaskedOutput,
|
||||
/// Maskable output data (GPIO bank 0, MIO, upper 16 bits)
|
||||
@@ -85,27 +85,27 @@ pub struct Gpio {
|
||||
_reserved_2: [u32; 101],
|
||||
|
||||
#[mmio(Inner)]
|
||||
bank_0: BankControl,
|
||||
bank_0: BankControlRegisters,
|
||||
|
||||
_reserved_3: [u32; 7],
|
||||
|
||||
#[mmio(Inner)]
|
||||
bank_1: BankControl,
|
||||
bank_1: BankControlRegisters,
|
||||
|
||||
_reserved_4: [u32; 7],
|
||||
|
||||
#[mmio(Inner)]
|
||||
bank_2: BankControl,
|
||||
bank_2: BankControlRegisters,
|
||||
|
||||
_reserved_5: [u32; 7],
|
||||
|
||||
#[mmio(Inner)]
|
||||
bank_3: BankControl,
|
||||
bank_3: BankControlRegisters,
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Gpio>(), 0x2E8);
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Registers>(), 0x2E8);
|
||||
|
||||
impl Gpio {
|
||||
impl Registers {
|
||||
/// Create a new XGPIOPS GPIO MMIO instance.
|
||||
///
|
||||
/// # Safety
|
||||
@@ -113,9 +113,9 @@ impl Gpio {
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub const unsafe fn new_mmio_fixed() -> MmioGpio<'static> {
|
||||
MmioGpio {
|
||||
ptr: 0xE000A000 as *mut Gpio,
|
||||
pub const unsafe fn new_mmio_fixed() -> MmioRegisters<'static> {
|
||||
MmioRegisters {
|
||||
ptr: 0xE000A000 as *mut Registers,
|
||||
phantom: core::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ pub struct InterruptStatus {
|
||||
/// Global timer counter register access.
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct GlobalTimerCounter {
|
||||
pub struct Registers {
|
||||
/// Count register 0, lower 32 bits
|
||||
count_lower: u32,
|
||||
/// Count register 1, upper 32 bits
|
||||
@@ -43,9 +43,9 @@ pub struct GlobalTimerCounter {
|
||||
auto_increment: u32,
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<GlobalTimerCounter>(), 0x1C);
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Registers>(), 0x1C);
|
||||
|
||||
impl GlobalTimerCounter {
|
||||
impl Registers {
|
||||
/// Create a new GTC MMIO instance at the fixed base address.
|
||||
///
|
||||
/// # Safety
|
||||
@@ -54,7 +54,7 @@ impl GlobalTimerCounter {
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
#[inline]
|
||||
pub const unsafe fn new_mmio_fixed() -> MmioGlobalTimerCounter<'static> {
|
||||
unsafe { GlobalTimerCounter::new_mmio_at(GTC_BASE_ADDR) }
|
||||
pub const unsafe fn new_mmio_fixed() -> MmioRegisters<'static> {
|
||||
unsafe { Registers::new_mmio_at(GTC_BASE_ADDR) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ pub struct TransferSize {
|
||||
/// I2C register access.
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct I2c {
|
||||
pub struct Registers {
|
||||
cr: Control,
|
||||
#[mmio(PureRead)]
|
||||
sr: Status,
|
||||
@@ -179,9 +179,9 @@ pub struct I2c {
|
||||
idr: InterruptControl,
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<I2c>(), 0x2C);
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Registers>(), 0x2C);
|
||||
|
||||
impl I2c {
|
||||
impl Registers {
|
||||
/// Create a new I2C MMIO instance for I2C0 at address [I2C_0_BASE_ADDR].
|
||||
///
|
||||
/// # Safety
|
||||
@@ -189,7 +189,7 @@ impl I2c {
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub const unsafe fn new_mmio_fixed_0() -> MmioI2c<'static> {
|
||||
pub const unsafe fn new_mmio_fixed_0() -> MmioRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(I2C_0_BASE_ADDR) }
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ impl I2c {
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub const unsafe fn new_mmio_fixed_1() -> MmioI2c<'static> {
|
||||
pub const unsafe fn new_mmio_fixed_1() -> MmioRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(I2C_1_BASE_ADDR) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ pub struct InterruptControl {
|
||||
/// L2 Cache register access.
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct L2Cache {
|
||||
pub struct Registers {
|
||||
#[mmio(PureRead)]
|
||||
cache_id: CacheId,
|
||||
#[mmio(PureRead)]
|
||||
@@ -273,9 +273,9 @@ pub struct L2Cache {
|
||||
power_control: u32,
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<L2Cache>(), 0xF84);
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Registers>(), 0xF84);
|
||||
|
||||
impl L2Cache {
|
||||
impl Registers {
|
||||
/// Create a new L2C MMIO instance for for L2 Cache at address [L2C_BASE_ADDR].
|
||||
///
|
||||
/// # Safety
|
||||
@@ -283,7 +283,7 @@ impl L2Cache {
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub const unsafe fn new_mmio_fixed() -> MmioL2Cache<'static> {
|
||||
pub const unsafe fn new_mmio_fixed() -> MmioRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(L2C_BASE_ADDR) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ pub mod l2_cache;
|
||||
pub mod mpcore;
|
||||
pub mod priv_tim;
|
||||
pub mod qspi;
|
||||
pub mod sdio;
|
||||
pub mod slcr;
|
||||
pub mod spi;
|
||||
pub mod ttc;
|
||||
@@ -43,26 +44,28 @@ static PERIPHERALS_TAKEN: AtomicBool = AtomicBool::new(false);
|
||||
/// The [`svd2rust` documentation](https://docs.rs/svd2rust/latest/svd2rust/#peripheral-api)
|
||||
/// provides some more information about this.
|
||||
pub struct Peripherals {
|
||||
pub gicc: gic::MmioGicCpuInterface<'static>,
|
||||
pub gicd: gic::MmioGicDistributor<'static>,
|
||||
pub l2c: l2_cache::MmioL2Cache<'static>,
|
||||
pub ddrc: ddrc::MmioDdrController<'static>,
|
||||
pub uart_0: uart::MmioUart<'static>,
|
||||
pub uart_1: uart::MmioUart<'static>,
|
||||
pub spi_0: spi::MmioSpi<'static>,
|
||||
pub spi_1: spi::MmioSpi<'static>,
|
||||
pub i2c_0: i2c::MmioI2c<'static>,
|
||||
pub i2c_1: i2c::MmioI2c<'static>,
|
||||
pub gtc: gtc::MmioGlobalTimerCounter<'static>,
|
||||
pub gpio: gpio::MmioGpio<'static>,
|
||||
pub slcr: slcr::MmioSlcr<'static>,
|
||||
pub ttc_0: ttc::MmioTtc<'static>,
|
||||
pub ttc_1: ttc::MmioTtc<'static>,
|
||||
pub eth_0: eth::MmioEthernet<'static>,
|
||||
pub eth_1: eth::MmioEthernet<'static>,
|
||||
pub qspi: qspi::MmioQspi<'static>,
|
||||
pub devcfg: devcfg::MmioDevCfg<'static>,
|
||||
pub xadc: xadc::MmioXAdc<'static>,
|
||||
pub gicc: gic::MmioGicCpuInterfaceRegisters<'static>,
|
||||
pub gicd: gic::MmioGicDistributorRegisters<'static>,
|
||||
pub l2c: l2_cache::MmioRegisters<'static>,
|
||||
pub ddrc: ddrc::MmioRegisters<'static>,
|
||||
pub uart_0: uart::MmioRegisters<'static>,
|
||||
pub uart_1: uart::MmioRegisters<'static>,
|
||||
pub spi_0: spi::MmioRegisters<'static>,
|
||||
pub spi_1: spi::MmioRegisters<'static>,
|
||||
pub i2c_0: i2c::MmioRegisters<'static>,
|
||||
pub i2c_1: i2c::MmioRegisters<'static>,
|
||||
pub gtc: gtc::MmioRegisters<'static>,
|
||||
pub gpio: gpio::MmioRegisters<'static>,
|
||||
pub slcr: slcr::MmioRegisters<'static>,
|
||||
pub ttc_0: ttc::MmioRegisters<'static>,
|
||||
pub ttc_1: ttc::MmioRegisters<'static>,
|
||||
pub eth_0: eth::MmioRegisters<'static>,
|
||||
pub eth_1: eth::MmioRegisters<'static>,
|
||||
pub qspi: qspi::MmioRegisters<'static>,
|
||||
pub devcfg: devcfg::MmioRegisters<'static>,
|
||||
pub xadc: xadc::MmioRegisters<'static>,
|
||||
pub sdio_0: sdio::MmioRegisters<'static>,
|
||||
pub sdio_1: sdio::MmioRegisters<'static>,
|
||||
}
|
||||
|
||||
impl Peripherals {
|
||||
@@ -83,26 +86,28 @@ impl Peripherals {
|
||||
pub unsafe fn steal() -> Self {
|
||||
unsafe {
|
||||
Self {
|
||||
gicc: gic::GicCpuInterface::new_mmio_fixed(),
|
||||
gicd: gic::GicDistributor::new_mmio_fixed(),
|
||||
l2c: l2_cache::L2Cache::new_mmio_fixed(),
|
||||
ddrc: ddrc::DdrController::new_mmio_fixed(),
|
||||
uart_0: uart::Uart::new_mmio_fixed_0(),
|
||||
uart_1: uart::Uart::new_mmio_fixed_1(),
|
||||
gtc: gtc::GlobalTimerCounter::new_mmio_fixed(),
|
||||
gpio: gpio::Gpio::new_mmio_fixed(),
|
||||
slcr: slcr::Slcr::new_mmio_fixed(),
|
||||
spi_0: spi::Spi::new_mmio_fixed_0(),
|
||||
spi_1: spi::Spi::new_mmio_fixed_1(),
|
||||
i2c_0: i2c::I2c::new_mmio_fixed_0(),
|
||||
i2c_1: i2c::I2c::new_mmio_fixed_1(),
|
||||
ttc_0: ttc::Ttc::new_mmio_fixed_0(),
|
||||
ttc_1: ttc::Ttc::new_mmio_fixed_1(),
|
||||
eth_0: eth::Ethernet::new_mmio_fixed_0(),
|
||||
eth_1: eth::Ethernet::new_mmio_fixed_1(),
|
||||
qspi: qspi::Qspi::new_mmio_fixed(),
|
||||
devcfg: devcfg::DevCfg::new_mmio_fixed(),
|
||||
xadc: xadc::XAdc::new_mmio_fixed(),
|
||||
gicc: gic::GicCpuInterfaceRegisters::new_mmio_fixed(),
|
||||
gicd: gic::GicDistributorRegisters::new_mmio_fixed(),
|
||||
l2c: l2_cache::Registers::new_mmio_fixed(),
|
||||
ddrc: ddrc::Registers::new_mmio_fixed(),
|
||||
uart_0: uart::Registers::new_mmio_fixed_0(),
|
||||
uart_1: uart::Registers::new_mmio_fixed_1(),
|
||||
gtc: gtc::Registers::new_mmio_fixed(),
|
||||
gpio: gpio::Registers::new_mmio_fixed(),
|
||||
slcr: slcr::Registers::new_mmio_fixed(),
|
||||
spi_0: spi::Registers::new_mmio_fixed_0(),
|
||||
spi_1: spi::Registers::new_mmio_fixed_1(),
|
||||
i2c_0: i2c::Registers::new_mmio_fixed_0(),
|
||||
i2c_1: i2c::Registers::new_mmio_fixed_1(),
|
||||
ttc_0: ttc::Registers::new_mmio_fixed_0(),
|
||||
ttc_1: ttc::Registers::new_mmio_fixed_1(),
|
||||
eth_0: eth::Registers::new_mmio_fixed_0(),
|
||||
eth_1: eth::Registers::new_mmio_fixed_1(),
|
||||
qspi: qspi::Registers::new_mmio_fixed(),
|
||||
devcfg: devcfg::Registers::new_mmio_fixed(),
|
||||
xadc: xadc::Registers::new_mmio_fixed(),
|
||||
sdio_0: sdio::Registers::new_mmio_fixed_0(),
|
||||
sdio_1: sdio::Registers::new_mmio_fixed_1(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,11 @@
|
||||
use static_assertions::const_assert_eq;
|
||||
|
||||
use crate::{
|
||||
gic::{GicCpuInterface, GicDistributor, MmioGicCpuInterface, MmioGicDistributor},
|
||||
gtc::{GlobalTimerCounter, MmioGlobalTimerCounter},
|
||||
gic::{
|
||||
GicCpuInterfaceRegisters, GicDistributorRegisters, MmioGicCpuInterfaceRegisters,
|
||||
MmioGicDistributorRegisters,
|
||||
},
|
||||
gtc::{MmioRegisters, Registers},
|
||||
};
|
||||
|
||||
pub const MPCORE_BASE_ADDR: usize = 0xF8F0_0000;
|
||||
@@ -54,10 +57,10 @@ pub struct MpCore {
|
||||
_reserved_0: [u32; 0x2A],
|
||||
|
||||
#[mmio(Inner)]
|
||||
gicc: GicCpuInterface,
|
||||
gicc: GicCpuInterfaceRegisters,
|
||||
|
||||
#[mmio(Inner)]
|
||||
gt: GlobalTimerCounter,
|
||||
gt: Registers,
|
||||
|
||||
_reserved_1: [u32; 0xF9],
|
||||
|
||||
@@ -78,7 +81,7 @@ pub struct MpCore {
|
||||
_reserved_3: [u32; 0x272],
|
||||
|
||||
#[mmio(Inner)]
|
||||
gicd: GicDistributor,
|
||||
gicd: GicDistributorRegisters,
|
||||
}
|
||||
|
||||
const_assert_eq!(core::mem::size_of::<MpCore>(), 0x2000);
|
||||
|
||||
@@ -24,14 +24,14 @@ pub struct InterruptStatus {
|
||||
/// CPU private timer register access.
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct CpuPrivateTimer {
|
||||
pub struct Registers {
|
||||
reload: u32,
|
||||
counter: u32,
|
||||
control: Control,
|
||||
interrupt_status: InterruptStatus,
|
||||
}
|
||||
|
||||
impl CpuPrivateTimer {
|
||||
impl Registers {
|
||||
/// Create a new CPU Private Timer MMIO instance at the fixed base address.
|
||||
///
|
||||
/// # Safety
|
||||
@@ -43,7 +43,7 @@ impl CpuPrivateTimer {
|
||||
/// It should also be noted that the calls to this MMIO structure are private for each CPU
|
||||
/// core, which might lead to unexpected results when using this in a SMP system.
|
||||
#[inline]
|
||||
pub const unsafe fn new_mmio_fixed() -> MmioCpuPrivateTimer<'static> {
|
||||
unsafe { CpuPrivateTimer::new_mmio_at(CPU_PRIV_TIM_BASE_ADDR) }
|
||||
pub const unsafe fn new_mmio_fixed() -> MmioRegisters<'static> {
|
||||
unsafe { Registers::new_mmio_at(CPU_PRIV_TIM_BASE_ADDR) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ pub struct LinearQspiStatus {
|
||||
/// QSPI register access.
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct Qspi {
|
||||
pub struct Registers {
|
||||
config: Config,
|
||||
interrupt_status: InterruptStatus,
|
||||
#[mmio(Write)]
|
||||
@@ -265,9 +265,9 @@ pub struct Qspi {
|
||||
module_id: u32,
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Qspi>(), 0x100);
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Registers>(), 0x100);
|
||||
|
||||
impl Qspi {
|
||||
impl Registers {
|
||||
/// Create a new QSPI MMIO instance for for QSPI controller at address [QSPI_BASE_ADDR].
|
||||
///
|
||||
/// # Safety
|
||||
@@ -275,7 +275,7 @@ impl Qspi {
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub const unsafe fn new_mmio_fixed() -> MmioQspi<'static> {
|
||||
pub const unsafe fn new_mmio_fixed() -> MmioRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(QSPI_BASE_ADDR) }
|
||||
}
|
||||
}
|
||||
|
||||
457
zynq/zynq7000/src/sdio.rs
Normal file
457
zynq/zynq7000/src/sdio.rs
Normal file
@@ -0,0 +1,457 @@
|
||||
use arbitrary_int::{u2, u4, u6, u12};
|
||||
|
||||
pub const SDIO_BASE_ADDR_0: usize = 0xE010_0000;
|
||||
pub const SDIO_BASE_ADDR_1: usize = 0xE010_1000;
|
||||
|
||||
#[bitbybit::bitenum(u3, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum BufferSize {
|
||||
_4kB = 0b000,
|
||||
_8kB = 0b001,
|
||||
_16kB = 0b010,
|
||||
_32kB = 0b011,
|
||||
_64kB = 0b100,
|
||||
_128kB = 0b101,
|
||||
_256kB = 0b110,
|
||||
_512kB = 0b111,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32, debug)]
|
||||
pub struct BlockParams {
|
||||
#[bits(16..=31, rw)]
|
||||
blocks_count: u16,
|
||||
#[bits(12..=14, rw)]
|
||||
buffer_size: BufferSize,
|
||||
#[bits(0..=11, rw)]
|
||||
block_size: u12,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u2, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum CommandType {
|
||||
Normal = 0b00,
|
||||
Suspend = 0b01,
|
||||
Resume = 0b10,
|
||||
Abort = 0b11,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u2, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum ResponseLength {
|
||||
NoResponse = 0b00,
|
||||
ResponseLength136 = 0b01,
|
||||
ResponseLength48 = 0b10,
|
||||
ResponseLength48Check = 0b11,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum BlockSelect {
|
||||
SingleBlock = 0,
|
||||
MultiBlock = 1,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum TransferDirection {
|
||||
/// Host to card.
|
||||
Write = 0,
|
||||
/// Card to host.
|
||||
Read = 1,
|
||||
}
|
||||
#[bitbybit::bitfield(u32, debug)]
|
||||
pub struct TransferModeAndCommand {
|
||||
/// Set to command number (CMD0-63, ACMD0-63)
|
||||
#[bits(24..=29, rw)]
|
||||
command_index: u6,
|
||||
#[bits(22..=23, rw)]
|
||||
command_type: CommandType,
|
||||
/// Set to [false] for the following:
|
||||
///
|
||||
/// 1. Commands using only CMD line (ex. CMD52).
|
||||
/// 2. Commands with no data transfer but using busy signal on DAT\[0\].
|
||||
/// 3. Resume Command.
|
||||
#[bit(21, rw)]
|
||||
data_is_present: bool,
|
||||
/// When 1, the host controller checks the index field in the response to see if it has the
|
||||
/// same value as the command index.
|
||||
#[bit(20, rw)]
|
||||
command_index_check_enable: bool,
|
||||
/// When 1, the host controller checks the CRC field in the response.
|
||||
#[bit(18, rw)]
|
||||
command_crc_check_enable: bool,
|
||||
#[bits(16..=17, rw)]
|
||||
response_type_select: u2,
|
||||
#[bit(5, rw)]
|
||||
multi_single_block_select: BlockSelect,
|
||||
#[bit(4, rw)]
|
||||
data_transfer_direction: TransferDirection,
|
||||
/// Multiple block transfers for memory require CMD12 to stop the transaction. When this bit is
|
||||
/// 1, the host controller issues CMD12 automatically when completing the last block tranfer.
|
||||
#[bit(2, rw)]
|
||||
auto_cmd12_enable: bool,
|
||||
/// Enable block count register, which is only relevant for multiple block transfers.
|
||||
#[bit(1, rw)]
|
||||
block_count_enable: bool,
|
||||
#[bit(0, rw)]
|
||||
dma_enable: bool,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32, debug)]
|
||||
pub struct PresentState {
|
||||
#[bit(24, r)]
|
||||
cmd_line_signal_level: bool,
|
||||
#[bits(20..=23, r)]
|
||||
data_line_signal_level: u4,
|
||||
/// The Write Protect Switch is supported for memory and combo cards. This bit reflects the
|
||||
/// inversion of the SDx_WP pin.
|
||||
#[bit(19, r)]
|
||||
write_protect_switch_level: bool,
|
||||
/// This bit reflects the inverse value of the SDx_CDn pin.
|
||||
#[bit(18, r)]
|
||||
card_detect_pin_level: bool,
|
||||
/// This bit is used for testing. If it is 0, the Card Detect Pin Level is not stable. If this
|
||||
/// bit is set to 1, it means the Card Detect Pin Level is stable. The Software Reset For All
|
||||
/// in the Software Reset Register shall not affect this bit.
|
||||
#[bit(17, r)]
|
||||
card_state_stable: bool,
|
||||
/// This bit indicates whether a card has been inserted. Changing from 0 to 1 generates a Card
|
||||
/// Insertion interrupt in the Normal Interrupt Status register and changing from 1 to 0
|
||||
/// generates a Card Removal Interrupt in the Normal Interrupt Status register. The Software
|
||||
/// Reset For All in the Software Reset register shall not affect this bit. If a Card is
|
||||
/// removed while its power is on and its clock is oscillating, the HC shall clear SD Bus Power
|
||||
/// in the Power Control register and SD Clock Enable in the Clock control register. In
|
||||
/// addition the HD should clear the HC by the Software Reset For All in Software register. The
|
||||
/// card detect is active regardless of the SD Bus Power.
|
||||
#[bit(16, r)]
|
||||
card_inserted: bool,
|
||||
/// This status is used for non-DMA read transfers. This read only flag indicates that valid
|
||||
/// data exists in the host side buffer status. If this bit is 1, readable data exists in the
|
||||
/// buffer. A change of this bit from 1 to 0 occurs when all the block data is read from the
|
||||
/// buffer. A change of this bit from 0 to 1 occurs when all the block data is ready in the
|
||||
/// buffer and generates the Buffer Read Ready Interrupt.
|
||||
#[bit(11, r)]
|
||||
buffer_readable: bool,
|
||||
/// This status is used for non-DMA write transfers. This read only flag indicates if space is
|
||||
/// available for write data. If this bit is 1, data can be written to the buffer. A change of
|
||||
/// this bit from 1 to 0 occurs when all the block data is written to the buffer. A change of
|
||||
/// this bit from 0 to 1 occurs when top of block data can be written to the buffer and
|
||||
/// generates the Buffer Write Ready Interrupt.
|
||||
#[bit(10, r)]
|
||||
buffer_writable: bool,
|
||||
/// This status is used for detecting completion of a read transfer. This bit is set to 1 for
|
||||
/// either of the following conditions:
|
||||
///
|
||||
/// 1. After the end bit of the read command
|
||||
/// 2. When writing a 1 to continue Request in the Block Gap Control register to restart a read
|
||||
/// transfer.
|
||||
///
|
||||
/// This bit is cleared to 0 for either of the following conditions:
|
||||
///
|
||||
/// 1. When the last data block as specified by block length is transferred to the system.
|
||||
/// 2. When all valid data blocks have been transferred to the system and no current block
|
||||
/// transfers are being sent as a result of the Stop At Block Gap Request set to 1. A transfer
|
||||
/// complete interrupt is generated when this bit changes to 0.
|
||||
#[bit(9, r)]
|
||||
read_transfer_active: bool,
|
||||
/// This status indicates a write transfer is active. If this bit is 0, it means no valid write
|
||||
/// data exists in the HC. This bit is set in either of the following cases: 1. After the end
|
||||
/// bit of the write command. 2. When writing a 1 to Continue Request in the Block Gap Control
|
||||
/// register to restart a write transfer.
|
||||
///
|
||||
/// This bit is cleared in either of the following cases:
|
||||
///
|
||||
/// 1. After getting the CRC status of the last data block as specified by the transfer count
|
||||
/// (Single or Multiple)
|
||||
/// 2. After getting a CRC status of any block where data transmission is about to be stopped
|
||||
/// by a Stop At Block Gap Request.
|
||||
///
|
||||
/// During a write transaction, a Block Gap Event interrupt is generated when this bit is
|
||||
/// changed to 0, as a result of the Stop At Block Gap Request being set. This status is useful
|
||||
/// for the HD in determining when to issue commands during write busy.
|
||||
#[bit(8, r)]
|
||||
write_transfer_active: bool,
|
||||
#[bit(2, r)]
|
||||
dat_line_active: bool,
|
||||
/// This status bit is generated if either the DAT Line Active or the Read transfer Active is
|
||||
/// set to 1. If this bit is 0, it indicates the HC can issue the next SD command. Commands
|
||||
/// with busy signal belong to Command Inhibit (DAT) (ex. R1b, R5b type). Changing from 1 to 0
|
||||
/// generates a Transfer Complete interrupt in the Normal interrupt status register.
|
||||
#[bit(1, r)]
|
||||
command_inhibit_dat: bool,
|
||||
/// 0 indicates the CMD line is not in use and the host controller can issue a SD command
|
||||
/// using the CMD line. This bit is set immediately after the Command register (00Fh) is
|
||||
/// written. This bit is cleared when the command response is received. Even if the Command
|
||||
/// Inhibit (DAT) is set to 1, Commands using only the CMD line can be issued if this bit is 0.
|
||||
/// Changing from 1 to 0 generates a Command complete interrupt in the Normal Interrupt Status
|
||||
/// register. If the HC cannot issue the command because of a command conflict error or because
|
||||
/// of Command Not Issued By Auto CMD12 Error, this bit shall remain 1 and the Command Complete
|
||||
/// is not set. Status issuing Auto CMD12 is not read from this bit.
|
||||
#[bit(0, r)]
|
||||
command_inhibit_cmd: bool,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum DataTransferWidth {
|
||||
_1bit = 0,
|
||||
_4bit = 1,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u2, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum DmaSelect {
|
||||
Sdma = 0b00,
|
||||
Adma1_32bits = 0b01,
|
||||
Adma2_32bits = 0b10,
|
||||
Adma2_64bits = 0b11,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u3, exhaustive = false)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum SdBusVoltageSelect {
|
||||
_1_8V = 0b101,
|
||||
_3_0V = 0b110,
|
||||
_3_3V = 0b111,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32, debug)]
|
||||
pub struct HostPowerBlockgapWakeupControl {
|
||||
#[bit(26, rw)]
|
||||
wakeup_event_enable_on_sd_card_removal: bool,
|
||||
#[bit(25, rw)]
|
||||
wakeup_event_enable_on_sd_card_insertion: bool,
|
||||
#[bit(24, rw)]
|
||||
wakeup_event_enable_on_card_interrupt: bool,
|
||||
#[bit(19, rw)]
|
||||
interrupt_at_block_gap: bool,
|
||||
#[bit(18, rw)]
|
||||
read_wait_control: bool,
|
||||
#[bit(17, rw)]
|
||||
continue_request: bool,
|
||||
#[bit(16, rw)]
|
||||
stop_as_block_gap_request: bool,
|
||||
#[bits(9..=11, rw)]
|
||||
sd_bus_voltage_select: Option<SdBusVoltageSelect>,
|
||||
#[bit(8, rw)]
|
||||
sd_bus_power: bool,
|
||||
#[bit(7, rw)]
|
||||
card_detect_signal_detection: bool,
|
||||
#[bit(6, rw)]
|
||||
card_detetect_test_level: bool,
|
||||
#[bits(3..=4, rw)]
|
||||
dma_select: DmaSelect,
|
||||
#[bit(2, rw)]
|
||||
high_speed_enable: bool,
|
||||
#[bit(1, rw)]
|
||||
data_transfer_width: DataTransferWidth,
|
||||
#[bit(0, rw)]
|
||||
led_control: bool,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u8, exhaustive = false)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum SdClockDivisor {
|
||||
Div256 = 0x80,
|
||||
Div128 = 0x40,
|
||||
Div64 = 0x20,
|
||||
Div32 = 0x10,
|
||||
Div16 = 0x08,
|
||||
Div8 = 0x04,
|
||||
Div4 = 0x02,
|
||||
Div2 = 0x01,
|
||||
Div1 = 0x00,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32, debug)]
|
||||
pub struct ClockAndTimeoutAndSwResetControl {
|
||||
#[bit(26, rw)]
|
||||
software_reset_for_dat_line: bool,
|
||||
#[bit(25, rw)]
|
||||
software_reset_for_cmd_line: bool,
|
||||
#[bit(24, rw)]
|
||||
software_reset_for_all: bool,
|
||||
/// Interval: TMCLK * 2^(13 + register value)
|
||||
///
|
||||
/// 0b1111 is reserved.
|
||||
#[bits(16..=19, rw)]
|
||||
data_timeout_counter_value: u4,
|
||||
#[bits(8..=15, rw)]
|
||||
sdclk_frequency_select: Option<SdClockDivisor>,
|
||||
#[bit(2, rw)]
|
||||
sd_clock_enable: bool,
|
||||
#[bit(1, r)]
|
||||
internal_clock_stable: bool,
|
||||
#[bit(0, rw)]
|
||||
internal_clock_enable: bool,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32, debug)]
|
||||
pub struct InterruptStatus {
|
||||
#[bit(29, rw)]
|
||||
ceata_error_status: bool,
|
||||
#[bit(28, rw)]
|
||||
target_response_error: bool,
|
||||
#[bit(25, rw)]
|
||||
adma_error: bool,
|
||||
#[bit(24, rw)]
|
||||
auto_cmd12_error: bool,
|
||||
#[bit(23, rw)]
|
||||
current_limit_error: bool,
|
||||
#[bit(22, rw)]
|
||||
data_end_bit_error: bool,
|
||||
#[bit(21, rw)]
|
||||
data_crc_error: bool,
|
||||
#[bit(20, rw)]
|
||||
data_timeout_error: bool,
|
||||
#[bit(19, rw)]
|
||||
command_index_error: bool,
|
||||
#[bit(18, rw)]
|
||||
command_end_bit_error: bool,
|
||||
#[bit(17, rw)]
|
||||
command_crc_error: bool,
|
||||
#[bit(16, rw)]
|
||||
command_timeout_error: bool,
|
||||
#[bit(15, r)]
|
||||
error_interrupt: bool,
|
||||
#[bit(10, rw)]
|
||||
boot_terminate: bool,
|
||||
#[bit(9, rw)]
|
||||
boot_ack_recv: bool,
|
||||
#[bit(8, r)]
|
||||
card_interrupt: bool,
|
||||
#[bit(7, rw)]
|
||||
card_removal: bool,
|
||||
#[bit(6, rw)]
|
||||
card_insertion: bool,
|
||||
#[bit(5, rw)]
|
||||
buffer_read_ready: bool,
|
||||
#[bit(4, rw)]
|
||||
buffer_write_ready: bool,
|
||||
#[bit(3, rw)]
|
||||
dma_interrupt: bool,
|
||||
#[bit(2, rw)]
|
||||
blockgap_event: bool,
|
||||
#[bit(1, rw)]
|
||||
transfer_complete: bool,
|
||||
#[bit(0, rw)]
|
||||
command_complete: bool,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32, debug)]
|
||||
pub struct InterruptMask {
|
||||
#[bit(29, rw)]
|
||||
ceata_error_status: bool,
|
||||
#[bit(28, rw)]
|
||||
target_response_error: bool,
|
||||
#[bit(25, rw)]
|
||||
adma_error: bool,
|
||||
#[bit(24, rw)]
|
||||
auto_cmd12_error: bool,
|
||||
#[bit(23, rw)]
|
||||
current_limit_error: bool,
|
||||
#[bit(22, rw)]
|
||||
data_end_bit_error: bool,
|
||||
#[bit(21, rw)]
|
||||
data_crc_error: bool,
|
||||
#[bit(20, rw)]
|
||||
data_timeout_error: bool,
|
||||
#[bit(19, rw)]
|
||||
command_index_error: bool,
|
||||
#[bit(18, rw)]
|
||||
command_end_bit_error: bool,
|
||||
#[bit(17, rw)]
|
||||
command_crc_error: bool,
|
||||
#[bit(16, rw)]
|
||||
command_timeout_error: bool,
|
||||
#[bit(15, rw)]
|
||||
error_interrupt: bool,
|
||||
#[bit(10, rw)]
|
||||
boot_terminate: bool,
|
||||
#[bit(9, rw)]
|
||||
boot_ack_recv: bool,
|
||||
#[bit(8, rw)]
|
||||
card_interrupt: bool,
|
||||
#[bit(7, rw)]
|
||||
card_removal: bool,
|
||||
#[bit(6, rw)]
|
||||
card_insertion: bool,
|
||||
#[bit(5, rw)]
|
||||
buffer_read_ready: bool,
|
||||
#[bit(4, rw)]
|
||||
buffer_write_ready: bool,
|
||||
#[bit(3, rw)]
|
||||
dma_interrupt: bool,
|
||||
#[bit(2, rw)]
|
||||
blockgap_event: bool,
|
||||
#[bit(1, rw)]
|
||||
transfer_complete: bool,
|
||||
#[bit(0, rw)]
|
||||
command_complete: bool,
|
||||
}
|
||||
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct Registers {
|
||||
sdma_system_addr: u32,
|
||||
block_params: u32,
|
||||
/// Bit 39-8 of Command-Format.
|
||||
argument: u32,
|
||||
transfer_mode_and_command: TransferModeAndCommand,
|
||||
#[mmio(PureRead)]
|
||||
responses: [u32; 4],
|
||||
buffer_data_port: u32,
|
||||
#[mmio(PureRead)]
|
||||
present_state: PresentState,
|
||||
host_power_blockgap_wakeup_control: HostPowerBlockgapWakeupControl,
|
||||
clock_timeout_sw_reset_control: ClockAndTimeoutAndSwResetControl,
|
||||
interrupt_status: InterruptStatus,
|
||||
interrupt_status_enable: InterruptMask,
|
||||
interrupt_signal_enable: InterruptMask,
|
||||
#[mmio(PureRead)]
|
||||
auto_cmd12_error_status: u32,
|
||||
#[mmio(PureRead)]
|
||||
capabilities: u32,
|
||||
_reserved_0: u32,
|
||||
#[mmio(PureRead)]
|
||||
maximum_current_capabilities: u32,
|
||||
_reserved_1: u32,
|
||||
force_event_register: u32,
|
||||
adma_error_status: u32,
|
||||
adma_system_address: u32,
|
||||
_reserved_2: u32,
|
||||
boot_timeout_control: u32,
|
||||
debug_selection: u32,
|
||||
_reserved_3: [u32; 0x22],
|
||||
spi_interrupt_support: u32,
|
||||
_reserved_4: [u32; 0x2],
|
||||
slot_interrupt_status_host_controll_version: u32,
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Registers>(), 0x100);
|
||||
|
||||
impl Registers {
|
||||
/// Create a new SDIO MMIO instance for SDIO 0 at address [SDIO_BASE_ADDR_0].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
#[inline]
|
||||
pub const unsafe fn new_mmio_fixed_0() -> MmioRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(SDIO_BASE_ADDR_0) }
|
||||
}
|
||||
|
||||
/// Create a new SDIO MMIO instance for SDIO 1 at address [SDIO_BASE_ADDR_1].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
#[inline]
|
||||
pub const unsafe fn new_mmio_fixed_1() -> MmioRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(SDIO_BASE_ADDR_1) }
|
||||
}
|
||||
}
|
||||
@@ -110,14 +110,14 @@ pub struct FpgaClockControl {
|
||||
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct FpgaClockControlBlock {
|
||||
pub struct FpgaClockControlRegisters {
|
||||
ctrl: FpgaClockControl,
|
||||
thr_ctrl: u32,
|
||||
thr_cnt: u32,
|
||||
thr_status: u32,
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<FpgaClockControlBlock>(), 0x10);
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<FpgaClockControlRegisters>(), 0x10);
|
||||
|
||||
#[bitbybit::bitenum(u2, exhaustive = true)]
|
||||
#[derive(Debug)]
|
||||
@@ -359,7 +359,7 @@ pub struct AperClockControl {
|
||||
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct ClockControl {
|
||||
pub struct ClockControlRegisters {
|
||||
arm_pll_ctrl: PllControl,
|
||||
ddr_pll_ctrl: PllControl,
|
||||
io_pll_ctrl: PllControl,
|
||||
@@ -391,18 +391,18 @@ pub struct ClockControl {
|
||||
pcap_clk_ctrl: SingleCommonPeriphIoClockControl,
|
||||
topsw_clk_ctrl: u32,
|
||||
#[mmio(Inner)]
|
||||
fpga_0_clk_ctrl: FpgaClockControlBlock,
|
||||
fpga_0_clk_ctrl: FpgaClockControlRegisters,
|
||||
#[mmio(Inner)]
|
||||
fpga_1_clk_ctrl: FpgaClockControlBlock,
|
||||
fpga_1_clk_ctrl: FpgaClockControlRegisters,
|
||||
#[mmio(Inner)]
|
||||
fpga_2_clk_ctrl: FpgaClockControlBlock,
|
||||
fpga_2_clk_ctrl: FpgaClockControlRegisters,
|
||||
#[mmio(Inner)]
|
||||
fpga_3_clk_ctrl: FpgaClockControlBlock,
|
||||
fpga_3_clk_ctrl: FpgaClockControlRegisters,
|
||||
_gap1: [u32; 5],
|
||||
clk_621_true: ClockRatioSelectReg,
|
||||
}
|
||||
|
||||
impl ClockControl {
|
||||
impl ClockControlRegisters {
|
||||
/// Create a new handle to this peripheral.
|
||||
///
|
||||
/// Writing to this register requires unlocking the SLCR registers first.
|
||||
@@ -411,9 +411,9 @@ impl ClockControl {
|
||||
///
|
||||
/// If you create multiple instances of this handle at the same time, you are responsible for
|
||||
/// ensuring that there are no read-modify-write races on any of the registers.
|
||||
pub unsafe fn new_mmio_fixed() -> MmioClockControl<'static> {
|
||||
pub unsafe fn new_mmio_fixed() -> MmioClockControlRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(SLCR_BASE_ADDR + CLOCK_CONTROL_OFFSET) }
|
||||
}
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<ClockControl>(), 0xC8);
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<ClockControlRegisters>(), 0xC8);
|
||||
|
||||
@@ -106,7 +106,7 @@ pub struct DdriobConfig {
|
||||
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct DdrIoB {
|
||||
pub struct DdrIobRegisters {
|
||||
ddriob_addr0: DdriobConfig,
|
||||
ddriob_addr1: DdriobConfig,
|
||||
ddriob_data0: DdriobConfig,
|
||||
@@ -123,7 +123,7 @@ pub struct DdrIoB {
|
||||
dci_status: DciStatus,
|
||||
}
|
||||
|
||||
impl DdrIoB {
|
||||
impl DdrIobRegisters {
|
||||
/// Create a new handle to this peripheral.
|
||||
///
|
||||
/// Writing to this register requires unlocking the SLCR registers first.
|
||||
@@ -132,9 +132,9 @@ impl DdrIoB {
|
||||
///
|
||||
/// If you create multiple instances of this handle at the same time, you are responsible for
|
||||
/// ensuring that there are no read-modify-write races on any of the registers.
|
||||
pub unsafe fn new_mmio_fixed() -> MmioDdrIoB<'static> {
|
||||
pub unsafe fn new_mmio_fixed() -> MmioDdrIobRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(super::SLCR_BASE_ADDR + super::DDRIOB_OFFSET) }
|
||||
}
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<DdrIoB>(), 0x38);
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<DdrIobRegisters>(), 0x38);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//!
|
||||
//! Writing any of these registers required unlocking the SLCR first.
|
||||
use arbitrary_int::u4;
|
||||
pub use clocks::{ClockControl, MmioClockControl};
|
||||
pub use clocks::{ClockControlRegisters, MmioClockControlRegisters};
|
||||
pub use reset::{MmioResetControl, ResetControl};
|
||||
|
||||
const SLCR_BASE_ADDR: usize = 0xF8000000;
|
||||
@@ -94,7 +94,7 @@ pub struct LevelShifterRegister {
|
||||
/// System Level Control Registers access.
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct Slcr {
|
||||
pub struct Registers {
|
||||
/// Secure configuration lock.
|
||||
scl: u32,
|
||||
/// SLCR write protection lock
|
||||
@@ -107,7 +107,7 @@ pub struct Slcr {
|
||||
_gap0: [u32; 0x3C],
|
||||
|
||||
#[mmio(Inner)]
|
||||
clk_ctrl: ClockControl,
|
||||
clk_ctrl: ClockControlRegisters,
|
||||
|
||||
_gap1: [u32; 0x0E],
|
||||
|
||||
@@ -180,12 +180,12 @@ pub struct Slcr {
|
||||
gpiob: GpiobRegisters,
|
||||
|
||||
#[mmio(Inner)]
|
||||
ddriob: ddriob::DdrIoB,
|
||||
ddriob: ddriob::DdrIobRegisters,
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Slcr>(), 0xB78);
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Registers>(), 0xB78);
|
||||
|
||||
impl Slcr {
|
||||
impl Registers {
|
||||
/// Create a new handle to this peripheral.
|
||||
///
|
||||
/// Writing to this register requires unlocking the SLCR registers first.
|
||||
@@ -194,7 +194,7 @@ impl Slcr {
|
||||
///
|
||||
/// If you create multiple instances of this handle at the same time, you are responsible for
|
||||
/// ensuring that there are no read-modify-write races on any of the registers.
|
||||
pub unsafe fn new_mmio_fixed() -> MmioSlcr<'static> {
|
||||
pub unsafe fn new_mmio_fixed() -> MmioRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(SLCR_BASE_ADDR) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ impl BaudDivSel {
|
||||
|
||||
// TODO: Use bitbybit debug support as soon as it was added.
|
||||
#[bitbybit::bitfield(u32, default = 0x0)]
|
||||
#[derive(Debug)]
|
||||
pub struct Config {
|
||||
#[bit(17, rw)]
|
||||
modefail_gen_en: bool,
|
||||
@@ -181,7 +180,7 @@ pub struct DelayControl {
|
||||
/// SPI register access.
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct Spi {
|
||||
pub struct Registers {
|
||||
cr: Config,
|
||||
#[mmio(PureRead, Write)]
|
||||
isr: InterruptStatus,
|
||||
@@ -209,9 +208,9 @@ pub struct Spi {
|
||||
mod_id: u32,
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Spi>(), 0x100);
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Registers>(), 0x100);
|
||||
|
||||
impl Spi {
|
||||
impl Registers {
|
||||
/// Create a new SPI MMIO instance for SPI0 at address [SPI_0_BASE_ADDR].
|
||||
///
|
||||
/// # Safety
|
||||
@@ -219,7 +218,7 @@ impl Spi {
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub const unsafe fn new_mmio_fixed_0() -> MmioSpi<'static> {
|
||||
pub const unsafe fn new_mmio_fixed_0() -> MmioRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(SPI_0_BASE_ADDR) }
|
||||
}
|
||||
|
||||
@@ -230,7 +229,7 @@ impl Spi {
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub const unsafe fn new_mmio_fixed_1() -> MmioSpi<'static> {
|
||||
pub const unsafe fn new_mmio_fixed_1() -> MmioRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(SPI_1_BASE_ADDR) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ pub struct EventCount {
|
||||
/// Triple-timer counter register access.
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct Ttc {
|
||||
pub struct Registers {
|
||||
clk_cntr: [ClockControl; 3],
|
||||
cnt_ctrl: [CounterControl; 3],
|
||||
#[mmio(PureRead)]
|
||||
@@ -162,9 +162,9 @@ pub struct Ttc {
|
||||
event_reg: [EventCount; 3],
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Ttc>(), 0x84);
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Registers>(), 0x84);
|
||||
|
||||
impl Ttc {
|
||||
impl Registers {
|
||||
/// Create a new TTC MMIO instance for TTC0 at address [TTC_0_BASE_ADDR].
|
||||
///
|
||||
/// # Safety
|
||||
@@ -172,7 +172,7 @@ impl Ttc {
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub const unsafe fn new_mmio_fixed_0() -> MmioTtc<'static> {
|
||||
pub const unsafe fn new_mmio_fixed_0() -> MmioRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(TTC_0_BASE_ADDR) }
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ impl Ttc {
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub const unsafe fn new_mmio_fixed_1() -> MmioTtc<'static> {
|
||||
pub const unsafe fn new_mmio_fixed_1() -> MmioRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(TTC_1_BASE_ADDR) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ impl InterruptStatus {
|
||||
/// UART register access.
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct Uart {
|
||||
pub struct Registers {
|
||||
/// Control Register
|
||||
cr: Control,
|
||||
/// Mode register
|
||||
@@ -325,9 +325,9 @@ pub struct Uart {
|
||||
tx_fifo_trigger: FifoTrigger,
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Uart>(), 0x48);
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Registers>(), 0x48);
|
||||
|
||||
impl Uart {
|
||||
impl Registers {
|
||||
/// Create a new UART MMIO instance for uart0 at address 0xE000_0000.
|
||||
///
|
||||
/// # Safety
|
||||
@@ -335,7 +335,7 @@ impl Uart {
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub const unsafe fn new_mmio_fixed_0() -> MmioUart<'static> {
|
||||
pub const unsafe fn new_mmio_fixed_0() -> MmioRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(UART_0_BASE) }
|
||||
}
|
||||
|
||||
@@ -346,7 +346,7 @@ impl Uart {
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub const unsafe fn new_mmio_fixed_1() -> MmioUart<'static> {
|
||||
pub const unsafe fn new_mmio_fixed_1() -> MmioRegisters<'static> {
|
||||
unsafe { Self::new_mmio_at(UART_1_BASE) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ pub const XADC_BASE_ADDR: usize = 0xF8007100;
|
||||
/// XADC register access.
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct XAdc {
|
||||
pub struct Registers {
|
||||
config: u32,
|
||||
interrupt_status: u32,
|
||||
interrupt_mask: u32,
|
||||
@@ -13,7 +13,7 @@ pub struct XAdc {
|
||||
misc_control: u32,
|
||||
}
|
||||
|
||||
impl XAdc {
|
||||
impl Registers {
|
||||
/// Create a new XADC MMIO instance for for device configuration peripheral at address
|
||||
/// [XADC_BASE_ADDR].
|
||||
///
|
||||
@@ -22,9 +22,9 @@ impl XAdc {
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub unsafe fn new_mmio_fixed() -> MmioXAdc<'static> {
|
||||
unsafe { XAdc::new_mmio_at(XADC_BASE_ADDR) }
|
||||
pub unsafe fn new_mmio_fixed() -> MmioRegisters<'static> {
|
||||
unsafe { Registers::new_mmio_at(XADC_BASE_ADDR) }
|
||||
}
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<XAdc>(), 0x1C);
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Registers>(), 0x1C);
|
||||
|
||||
Reference in New Issue
Block a user