12 Commits

Author SHA1 Message Date
Robin Mueller
337b00a442 continue sdio
Some checks failed
ci / Check build (push) Has been cancelled
ci / Check formatting (push) Has been cancelled
ci / Check Documentation Build (push) Has been cancelled
ci / Clippy (push) Has been cancelled
ci / Check build (pull_request) Has been cancelled
ci / Check formatting (pull_request) Has been cancelled
ci / Check Documentation Build (pull_request) Has been cancelled
ci / Clippy (pull_request) Has been cancelled
2025-11-03 11:46:30 +01:00
Robin Mueller
848e2113a0 continue with SDIO 2025-11-02 19:40:13 +01:00
Robin Mueller
82296ecc79 continue SDIO 2025-11-02 19:40:13 +01:00
Robin Mueller
3533faa7cc continue 2025-11-02 19:40:13 +01:00
Robin Mueller
5235eb422d add SDIO support 2025-11-02 19:40:13 +01:00
Robin Mueller
0d227e7f68 rename register blocks 2025-11-02 19:40:11 +01:00
0aa86cd085 Merge pull request 'replaced cortex-ar and cortex-a-rt by aarch32-rt and aarch32-cpu' (#22) from updated-rt-cpu-crate-name into main
Some checks failed
ci / Check build (push) Has been cancelled
ci / Check formatting (push) Has been cancelled
ci / Check Documentation Build (push) Has been cancelled
ci / Clippy (push) Has been cancelled
Reviewed-on: #22
2025-11-02 19:37:58 +01:00
Robin Mueller
a8339153c4 replaced cortex-ar and cortex-a-rt by aarch32-rt and aarch32-cpu
Some checks failed
ci / Check build (push) Has been cancelled
ci / Check formatting (push) Has been cancelled
ci / Check Documentation Build (push) Has been cancelled
ci / Clippy (push) Has been cancelled
ci / Check build (pull_request) Has been cancelled
ci / Check formatting (pull_request) Has been cancelled
ci / Check Documentation Build (pull_request) Has been cancelled
ci / Clippy (pull_request) Has been cancelled
2025-11-02 19:35:11 +01:00
b394da69f3 Merge pull request 'imrpoved ethernet mio typing check' (#20) from improve-eth-typing-checks into main
Some checks failed
ci / Check build (push) Has been cancelled
ci / Check formatting (push) Has been cancelled
ci / Check Documentation Build (push) Has been cancelled
ci / Clippy (push) Has been cancelled
Reviewed-on: #20
2025-10-27 23:15:43 +01:00
Robin Mueller
064f99ddea improved ethernet mio typing check
Some checks failed
ci / Check build (pull_request) Has been cancelled
ci / Check formatting (pull_request) Has been cancelled
ci / Check Documentation Build (pull_request) Has been cancelled
ci / Clippy (pull_request) Has been cancelled
ci / Check build (push) Has been cancelled
ci / Check formatting (push) Has been cancelled
ci / Check Documentation Build (push) Has been cancelled
ci / Clippy (push) Has been cancelled
2025-10-27 23:13:43 +01:00
2e1efd154d Merge pull request 'rename register blocks' (#19) from rename-registers into main
Some checks failed
ci / Check build (push) Has been cancelled
ci / Check formatting (push) Has been cancelled
ci / Check Documentation Build (push) Has been cancelled
ci / Clippy (push) Has been cancelled
Reviewed-on: #19
2025-10-27 23:12:43 +01:00
Robin Mueller
c53b6ae2bb rename register blocks
Some checks failed
ci / Check build (push) Has been cancelled
ci / Check formatting (push) Has been cancelled
ci / Check Documentation Build (push) Has been cancelled
ci / Clippy (push) Has been cancelled
2025-10-27 11:26:25 +01:00
87 changed files with 1481 additions and 631 deletions

View File

@@ -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
View File

@@ -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",
]

View File

@@ -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",
]}

View File

@@ -7,6 +7,7 @@ MEMORY
UNCACHED(rx): ORIGIN = 0x4000000, LENGTH = 1M
}
REGION_ALIAS("VECTORS", CODE);
REGION_ALIAS("DATA", CODE);
SECTIONS

View File

@@ -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};

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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(

View File

@@ -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;

View File

@@ -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" }

View File

@@ -7,6 +7,7 @@ MEMORY
UNCACHED(rx): ORIGIN = 0x4000000, LENGTH = 1M
}
REGION_ALIAS("VECTORS", CODE);
REGION_ALIAS("DATA", CODE);
SECTIONS

View File

@@ -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 {

View File

@@ -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};

View File

@@ -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};

View File

@@ -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();
}
}

View File

@@ -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" }

View File

@@ -7,6 +7,7 @@ MEMORY
UNCACHED(rx): ORIGIN = 0x4000000, LENGTH = 1M
}
REGION_ALIAS("VECTORS", CODE);
REGION_ALIAS("DATA", CODE);
SECTIONS

View File

@@ -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,

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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};

View File

@@ -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;

View File

@@ -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" }

View File

@@ -9,6 +9,7 @@ MEMORY
UNCACHED(rx): ORIGIN = 0x4000000, LENGTH = 1M
}
REGION_ALIAS("VECTORS", CODE);
REGION_ALIAS("DATA", CODE);
SECTIONS

View File

@@ -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();

View File

@@ -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" }

View File

@@ -7,6 +7,7 @@ MEMORY
UNCACHED(rx): ORIGIN = 0x4000000, LENGTH = 1M
}
REGION_ALIAS("VECTORS", CODE)
REGION_ALIAS("DATA", CODE);
SECTIONS

View File

@@ -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};

View File

@@ -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" }

View File

@@ -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);

View File

@@ -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)
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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();
}
}

View File

@@ -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);

View File

@@ -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);
});
}
}

View File

@@ -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,
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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();

View File

@@ -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() },

View File

@@ -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()));

View File

@@ -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,
}
}

View File

@@ -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);
});

View File

@@ -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,
) {

View File

@@ -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 {

View File

@@ -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;
}
_ => {}

View File

@@ -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,
}

View File

@@ -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);
});

View 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);
});
}
}

View File

@@ -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);

View File

@@ -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);
});

View File

@@ -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
}

View File

@@ -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);
});
}

View File

@@ -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 {}

View File

@@ -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
}

View File

@@ -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 = []

View File

@@ -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;

View File

@@ -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"]

View File

@@ -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;

View File

@@ -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

View File

@@ -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.

View File

@@ -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 */

View File

@@ -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

View File

@@ -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) }
}
}

View File

@@ -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) }
}
}

View File

@@ -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) }
}
}

View File

@@ -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) }
}
}

View File

@@ -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,
}
}

View File

@@ -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) }
}
}

View File

@@ -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) }
}
}

View File

@@ -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) }
}
}

View File

@@ -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(),
}
}
}

View File

@@ -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);

View File

@@ -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) }
}
}

View File

@@ -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
View 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) }
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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) }
}
}

View File

@@ -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) }
}
}

View File

@@ -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) }
}
}

View File

@@ -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) }
}
}

View File

@@ -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);