diff --git a/.cargo/config.toml.template b/.cargo/config.toml.template index a2dd61b..5092f1a 100644 --- a/.cargo/config.toml.template +++ b/.cargo/config.toml.template @@ -1,24 +1,3 @@ -[target.armv7a-none-eabihf] -runner = "./scripts/runner.sh" - -rustflags = [ - "-Ctarget-cpu=cortex-a9", - "-Ctarget-feature=+vfp3", - "-Ctarget-feature=+neon", - "-Clink-arg=-Tlink.x", - # If this is not enabled, debugging / stepping can become problematic. - "-Cforce-frame-pointers=yes", - # Can be useful for debugging. - # "-Clink-args=-Map=app.map" -] - -# Tier 3 target, so no pre-compiled artifacts included. -[unstable] -build-std = ["core", "alloc"] - -[build] -target = "armv7a-none-eabihf" - [env] # The following two env variables need to be set for the supplied runner.sh script to work. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 46698e7..900e867 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,41 +7,69 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - uses: extractions/setup-just@v3 - uses: dtolnay/rust-toolchain@nightly with: components: rust-src - # Copy config file for rustflags and to build core/alloc. - - run: cp .cargo/def-config.toml .cargo/config.toml - - run: cargo check --target armv7a-none-eabihf -p zynq7000 - - run: cargo check --target armv7a-none-eabihf -p zynq7000-rt + - run: just check zynq + + - uses: dtolnay/rust-toolchain@stable + - run: just check tools + - run: just check zynq7000-boot-image + + build: + name: Check build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: extractions/setup-just@v3 + + - uses: dtolnay/rust-toolchain@nightly + with: + components: rust-src + - run: just build zynq + + - uses: dtolnay/rust-toolchain@stable + - run: just build tools + - run: just build zynq7000-boot-image fmt: name: Check formatting runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@nightly + - uses: extractions/setup-just@v3 + - uses: dtolnay/rust-toolchain@stable with: components: rustfmt - - run: cargo fmt --all -- --check + - run: just fmt zynq + - run: just fmt tools + - run: just fmt zynq7000-boot-image docs: name: Check Documentation Build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - uses: extractions/setup-just@v3 - uses: dtolnay/rust-toolchain@nightly - - run: RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options" cargo +nightly doc -p zynq7000-rt --all-features - - run: RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options" cargo +nightly doc -p zynq7000 --all-features + with: + components: rust-src + - run: just docs-zynq clippy: name: Clippy runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - uses: extractions/setup-just@v3 - uses: dtolnay/rust-toolchain@nightly with: components: clippy, rust-src - # Copy config file for rustflags and to build core/alloc. - - run: cp .cargo/def-config.toml .cargo/config.toml - - run: cargo clippy --target armv7a-none-eabihf -- -D warnings + - run: just clippy zynq + + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - run: just clippy tools + - run: just clippy zynq7000-boot-image diff --git a/.gitignore b/.gitignore index cad995a..a2e6b44 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ -/target +target + /app.map /xsct-output.log /.vscode diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index 5c9db71..0000000 --- a/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[workspace] -resolver = "3" -members = [ - "zynq7000-rt", - "zynq7000", - "zynq7000-hal", - "zynq7000-embassy", - "examples/simple", - "examples/embassy", - "examples/zedboard", - "zynq-mmu", - "zedboard-fsbl", - "zedboard-bsp", - "zynq-boot-image", "zedboard-qspi-flasher", -] - -exclude = [ - "zynq-boot-image/tester", -] - -# cargo build/run --release -[profile.release] -codegen-units = 1 -debug = 2 -debug-assertions = false # <- -incremental = false -lto = true -opt-level = 3 # <- -overflow-checks = false # <- - -[profile.small] -inherits = "release" -opt-level = "z" diff --git a/README.md b/README.md index 373294b..4b6e89e 100644 --- a/README.md +++ b/README.md @@ -6,17 +6,23 @@ family of SoCs. # List of crates -This workspace contains the following crates: +This project contains the following crates: + +## Zynq Workspace + +This workspace contains libraries and application which can only be run on the target system. - The [`zynq7000-rt`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq7000-rt) run-time crate containing basic low-level startup code necessary to boot a Rust app on the Zynq7000. - The [`zynq7000`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq7000) PAC - crate containing basic low-level register definition. + crate containing basic low-level register definitions. +- The [`zynq7000-mmu`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq7000-hal) + crate containing common MMU abstractions used by both the HAL and the run-time crate. - The [`zynq7000-hal`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq7000-hal) HAL crate containing higher-level abstractions on top of the PAC register crate. - The [`zynq7000-embassy`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq7000-embassy) - crate containing support for running the embassy-rs RTOS. + crate containing support for running the embassy-rs asynchronous run-time. It also contains the following helper crates: @@ -25,13 +31,21 @@ It also contains the following helper crates: This folder also contains dedicated example applications using the [`embassy`](https://github.com/embassy-rs/embassy) native Rust RTOS. -The [`zedboard-fpga-design`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zedboard-fpga-design) -folder contains a sample FPGA design and block design which was used in -some of the provided software examples. The project was created with Vivado version 2024.1. -The folder contains a README with all the steps required to load this project from a TCL script. +## Other libraries and tools + +- The [`zedboard-fpga-design`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zedboard-fpga-design) + folder contains a sample FPGA design and block design which was used in some of the provided software examples. The project was created with Vivado version 2024.1. + The folder contains a README with all the steps required to load this project from a TCL script. +- The [`zynq7000-boot-image`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq7000-boot-image) + library contains generic helpers to interface with the AMD + [boot binary](https://docs.amd.com/r/en-US/ug1283-bootgen-user-guide). +- The [`tools/zynq7000-ps7init-extract`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/tools/zynq7000-ps7init-extract) + tool allows extracting configuration from the AMD generated `ps7init.tcl` file which contains + static configuration parameters for DDR initialization. # Using the `.cargo/config.toml` file +This is mostly relevant for development directly inside this repostiory. Use the following command to have a starting `config.toml` file ```sh diff --git a/justfile b/justfile index a761458..e61ca86 100644 --- a/justfile +++ b/justfile @@ -1,3 +1,35 @@ +all: check-all build-all clean-all fmt-all clippy-all docs-zynq + +check-all: (check "zynq") (check "tools") (check "zynq7000-boot-image") +clean-all: (clean "zynq") (clean "tools") (clean "zynq7000-boot-image") +build-all: build-zynq (build "tools") (build "zynq7000-boot-image") +fmt-all: (fmt "zynq") (fmt "tools") (fmt "zynq7000-boot-image") +clippy-all: (clippy "zynq") (clippy "tools") (clippy "zynq7000-boot-image") + +check target: + cd {{target}} && cargo check + +build target: + cd {{target}} && cargo build + +build-zynq: (build "zynq") + cd "zynq/zedboard-fsbl" && cargo build --release + +clean target: + cd {{target}} && cargo clean + +fmt target: + cd {{target}} && cargo +stable fmt --all -- --check + +clippy target: + cd {{target}} && cargo clippy -- -D warnings + +[working-directory: 'zynq'] +docs-zynq: + RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options" cargo +nightly doc -p zynq7000 + RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options" cargo +nightly doc -p zynq7000-hal --features alloc + RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options" cargo +nightly doc -p zynq7000-mmu + RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options" cargo +nightly doc -p zynq7000-rt [working-directory: 'zynq-boot-image/staging'] bootgen: diff --git a/tools/Cargo.lock b/tools/Cargo.lock new file mode 100644 index 0000000..69d3d27 --- /dev/null +++ b/tools/Cargo.lock @@ -0,0 +1,312 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys", +] + +[[package]] +name = "arbitrary-int" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "825297538d77367557b912770ca3083f778a196054b3ee63b22673c4a3cae0a5" + +[[package]] +name = "arbitrary-int" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c858caffa49edfc4ecc45a4bec37abd3e88041a2903816f10f990b7b41abc281" + +[[package]] +name = "bitbybit" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec187a89ab07e209270175faf9e07ceb2755d984954e58a2296e325ddece2762" +dependencies = [ + "arbitrary-int 1.3.0", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "boot-image-test" +version = "0.1.0" +dependencies = [ + "clap", + "zynq7000-boot-image", +] + +[[package]] +name = "clap" +version = "4.5.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "zynq7000-boot-image" +version = "0.1.0" +dependencies = [ + "arbitrary-int 2.0.0", + "bitbybit", + "thiserror", +] + +[[package]] +name = "zynq7000-ps7init-extract" +version = "0.1.0" +dependencies = [ + "clap", +] diff --git a/tools/Cargo.toml b/tools/Cargo.toml new file mode 100644 index 0000000..c07381e --- /dev/null +++ b/tools/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] +resolver = "3" +members = [ + "boot-image-test", + "zynq7000-ps7init-extract", +] diff --git a/zynq-boot-image/tester/.gitignore b/tools/boot-image-test/.gitignore similarity index 100% rename from zynq-boot-image/tester/.gitignore rename to tools/boot-image-test/.gitignore diff --git a/zynq-boot-image/tester/Cargo.lock b/tools/boot-image-test/Cargo.lock similarity index 100% rename from zynq-boot-image/tester/Cargo.lock rename to tools/boot-image-test/Cargo.lock diff --git a/tools/boot-image-test/Cargo.toml b/tools/boot-image-test/Cargo.toml new file mode 100644 index 0000000..cdca892 --- /dev/null +++ b/tools/boot-image-test/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "boot-image-test" +version = "0.1.0" +edition = "2024" + +[dependencies] +zynq7000-boot-image= { path = "../../zynq7000-boot-image" } +clap = { version = "4", features = ["derive"] } diff --git a/zynq-boot-image/tester/src/main.rs b/tools/boot-image-test/src/main.rs similarity index 98% rename from zynq-boot-image/tester/src/main.rs rename to tools/boot-image-test/src/main.rs index bff0c55..c793ef5 100644 --- a/zynq-boot-image/tester/src/main.rs +++ b/tools/boot-image-test/src/main.rs @@ -2,7 +2,7 @@ use std::{io::Read, path::Path}; use clap::Parser as _; -use zynq_boot_image::{BootHeader, FIXED_BOOT_HEADER_SIZE}; +use zynq7000_boot_image::{BootHeader, FIXED_BOOT_HEADER_SIZE}; #[derive(clap::Parser, Debug)] #[command(version, about)] diff --git a/tools/zynq7000-ps7init-extract/Cargo.lock b/tools/zynq7000-ps7init-extract/Cargo.lock new file mode 100644 index 0000000..074b1ff --- /dev/null +++ b/tools/zynq7000-ps7init-extract/Cargo.lock @@ -0,0 +1,251 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys", +] + +[[package]] +name = "clap" +version = "4.5.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "zynq7000-ps7init-extract" +version = "0.1.0" +dependencies = [ + "clap", +] diff --git a/zynq-boot-image/tester/Cargo.toml b/tools/zynq7000-ps7init-extract/Cargo.toml similarity index 63% rename from zynq-boot-image/tester/Cargo.toml rename to tools/zynq7000-ps7init-extract/Cargo.toml index 4cc3de7..bc72fdc 100644 --- a/zynq-boot-image/tester/Cargo.toml +++ b/tools/zynq7000-ps7init-extract/Cargo.toml @@ -1,10 +1,7 @@ -[workspace] - [package] -name = "tester" +name = "zynq7000-ps7init-extract" version = "0.1.0" edition = "2024" [dependencies] -zynq-boot-image= { path = ".." } clap = { version = "4", features = ["derive"] } diff --git a/tools/zynq7000-ps7init-extract/src/main.rs b/tools/zynq7000-ps7init-extract/src/main.rs new file mode 100644 index 0000000..3bef838 --- /dev/null +++ b/tools/zynq7000-ps7init-extract/src/main.rs @@ -0,0 +1,20 @@ +use std::path::Path; + +use clap::Parser as _; + +#[derive(clap::Parser, Debug)] +#[command(version, about)] +pub struct Cli { + /// Path to ps7init.tcl file. + #[arg(short, long)] + path: String, +} + +fn main() { + let cli = Cli::parse(); + let ps7init_tcl = Path::new(&cli.path); + if !ps7init_tcl.exists() { + eprintln!("File not found: {}", ps7init_tcl.display()); + std::process::exit(1); + } +} diff --git a/zedboard-fpga-design/README.md b/zedboard-fpga-design/README.md index 2e4d5f6..2533876 100644 --- a/zedboard-fpga-design/README.md +++ b/zedboard-fpga-design/README.md @@ -38,3 +38,25 @@ vivado zedboard-rust.xpr You can perform all the steps specified in the Vivado GUI as well using `Execute TCL script` and `Load Project`. + +# Generating the SDT folder from a hardware description + +You can generate a hardware description by building the block design by using `Generate Bitstream` +inside the Vivado GUI and then exporting the hardware description via +`File -> Export -> Export Hardware`. This allows to generate a `*.xsa` file which describes the +hardware. + +After that, you can generate the SDT output folder which contains various useful files like +the `ps7_init.tcl` script. The provided ` sdtgen.tcl` and `stdgen.py` script simplify this process. + +For example, the following command generates the SDT output folder inside a folder +named `sdt_out` for a hardware description files `zedboard-rust/zedboard-rust.xsa`, +assuming that the Vitis tool suite is installed at `/tools/Xilinx/Vitis/2024.1`: + +```sh +export AMD_TOOLS="/tools/Xilinx/Vitis/2024.1" +./sdtgen.py -x ./zedboard-rust/zedboard-rust.xsa +``` + +Run `stdgen.py -h` for more information and configuration options. The `stdgen.py` is a helper +script which will invoke `sdtgen.tcl` to generate the SDT. diff --git a/zynq-mmu/Cargo.toml b/zynq-mmu/Cargo.toml deleted file mode 100644 index 7bf07b0..0000000 --- a/zynq-mmu/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "zynq-mmu" -description = "Zynq MMU structures" -version = "0.1.0" -edition = "2024" - -[dependencies] -thiserror = { version = "2", default-features = false } -cortex-ar = { version = "0.2", git = "https://github.com/rust-embedded/cortex-ar.git", branch = "bump-arbitrary-int" } - -[features] -tools = [] diff --git a/zynq/.cargo/config.toml b/zynq/.cargo/config.toml new file mode 100644 index 0000000..15ce3b2 --- /dev/null +++ b/zynq/.cargo/config.toml @@ -0,0 +1,18 @@ +[target.armv7a-none-eabihf] +rustflags = [ + "-Ctarget-cpu=cortex-a9", + "-Ctarget-feature=+vfp3", + "-Ctarget-feature=+neon", + "-Clink-arg=-Tlink.x", + # If this is not enabled, debugging / stepping can become problematic. + "-Cforce-frame-pointers=yes", + # Can be useful for debugging. + # "-Clink-args=-Map=app.map" +] + +# Tier 3 target, so no pre-compiled artifacts included. +[unstable] +build-std = ["core", "alloc"] + +[build] +target = "armv7a-none-eabihf" diff --git a/zynq/.gitignore b/zynq/.gitignore new file mode 100644 index 0000000..03314f7 --- /dev/null +++ b/zynq/.gitignore @@ -0,0 +1 @@ +Cargo.lock diff --git a/zynq/Cargo.toml b/zynq/Cargo.toml new file mode 100644 index 0000000..9101e86 --- /dev/null +++ b/zynq/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +resolver = "3" +members = [ + "zynq7000-rt", + "zynq7000-mmu", + "zynq7000", + "zynq7000-hal", + "zynq7000-embassy", + + "examples/simple", + "examples/embassy", + "examples/zedboard", + + "zedboard-bsp", + "zedboard-qspi-flasher", +] + +exclude = [ + # Exclude, can not be built with debug optimization level, too large. + "zedboard-fsbl", +] diff --git a/examples/embassy/Cargo.toml b/zynq/examples/embassy/Cargo.toml similarity index 62% rename from examples/embassy/Cargo.toml rename to zynq/examples/embassy/Cargo.toml index c17151b..f32f638 100644 --- a/examples/embassy/Cargo.toml +++ b/zynq/examples/embassy/Cargo.toml @@ -11,7 +11,7 @@ keywords = ["no-std", "arm", "cortex-a", "amd", "zynq7000"] categories = ["embedded", "no-std", "hardware-support"] [dependencies] -cortex-ar = { version = "0.2", git = "https://github.com/rust-embedded/cortex-ar.git", rev = "79dba7000d2090d13823bfb783d9d64be8b778d2", features = ["critical-section-single-core"] } +cortex-ar = { version = "0.3", features = ["critical-section-single-core"] } zynq7000-rt = { path = "../../zynq7000-rt" } zynq7000 = { path = "../../zynq7000" } zynq7000-hal = { path = "../../zynq7000-hal" } @@ -20,19 +20,35 @@ dht-sensor = { git = "https://github.com/michaelbeaumont/dht-sensor.git", rev = static_cell = "2" critical-section = "1" heapless = "0.9" -embedded-io = "0.6" +embedded-io = "0.7" embedded-hal = "1" fugit = "0.3" log = "0.4" -embassy-executor = { git = "https://github.com/us-irs/embassy.git", branch = "cortex-ar-update", features = [ +embassy-executor = { git = "https://github.com/embassy-rs/embassy.git", features = [ "arch-cortex-ar", "executor-thread", ]} # TODO: Remove generic-queue-16 feature as soon as upstream executor is used again. embassy-time = { version = "0.5", features = ["tick-hz-1_000_000", "generic-queue-16"] } -[profile.release] +# cargo build/run +[profile.dev] +# default is opt-level = '0', but that makes very +# verbose machine code +opt-level = 's' +# trade compile speed for slightly better optimisations codegen-units = 1 -debug = true -lto = true + +# cargo build/run --release +[profile.release] +# default is opt-level = '3', but that makes quite +# verbose machine code +opt-level = 's' +# trade compile speed for slightly better optimisations +codegen-units = 1 +# Use Link Time Optimisations to further inline things across +# crates +lto = 'fat' +# Leave the debug symbols in (default is no debug info) +debug = 2 diff --git a/examples/embassy/build.rs b/zynq/examples/embassy/build.rs similarity index 100% rename from examples/embassy/build.rs rename to zynq/examples/embassy/build.rs diff --git a/examples/embassy/memory.x b/zynq/examples/embassy/memory.x similarity index 100% rename from examples/embassy/memory.x rename to zynq/examples/embassy/memory.x diff --git a/examples/embassy/src/bin/dht22-open-drain-pins.rs b/zynq/examples/embassy/src/bin/dht22-open-drain-pins.rs similarity index 100% rename from examples/embassy/src/bin/dht22-open-drain-pins.rs rename to zynq/examples/embassy/src/bin/dht22-open-drain-pins.rs diff --git a/examples/embassy/src/bin/logger-non-blocking.rs b/zynq/examples/embassy/src/bin/logger-non-blocking.rs similarity index 99% rename from examples/embassy/src/bin/logger-non-blocking.rs rename to zynq/examples/embassy/src/bin/logger-non-blocking.rs index 3c09354..1fd3eac 100644 --- a/examples/embassy/src/bin/logger-non-blocking.rs +++ b/zynq/examples/embassy/src/bin/logger-non-blocking.rs @@ -79,7 +79,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 { diff --git a/examples/embassy/src/bin/pwm.rs b/zynq/examples/embassy/src/bin/pwm.rs similarity index 100% rename from examples/embassy/src/bin/pwm.rs rename to zynq/examples/embassy/src/bin/pwm.rs diff --git a/examples/embassy/src/main.rs b/zynq/examples/embassy/src/main.rs similarity index 97% rename from examples/embassy/src/main.rs rename to zynq/examples/embassy/src/main.rs index afbdfe4..1047373 100644 --- a/examples/embassy/src/main.rs +++ b/zynq/examples/embassy/src/main.rs @@ -8,7 +8,7 @@ use embassy_time::{Duration, Ticker}; use embedded_hal::digital::StatefulOutputPin; use embedded_io::Write; use log::{error, info}; -use zynq7000_hal::{clocks, gic, gpio, gtc, time::Hertz, uart, BootMode, InteruptConfig}; +use zynq7000_hal::{BootMode, InteruptConfig, clocks, gic, gpio, gtc, time::Hertz, uart}; use zynq7000_rt as _; diff --git a/examples/simple/Cargo.toml b/zynq/examples/simple/Cargo.toml similarity index 74% rename from examples/simple/Cargo.toml rename to zynq/examples/simple/Cargo.toml index 64354b6..fdec76d 100644 --- a/examples/simple/Cargo.toml +++ b/zynq/examples/simple/Cargo.toml @@ -9,11 +9,11 @@ repository = "https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs" license = "MIT OR Apache-2.0" [dependencies] -cortex-ar = { version = "0.2", git = "https://github.com/rust-embedded/cortex-ar.git", rev = "79dba7000d2090d13823bfb783d9d64be8b778d2", features = ["critical-section-single-core"] } +cortex-ar = "0.3" zynq7000-rt = { path = "../../zynq7000-rt" } zynq7000 = { path = "../../zynq7000" } zynq7000-hal = { path = "../../zynq7000-hal" } -embedded-io = "0.6" +embedded-io = "0.7" embedded-hal = "1" fugit = "0.3" log = "0.4" diff --git a/examples/simple/build.rs b/zynq/examples/simple/build.rs similarity index 100% rename from examples/simple/build.rs rename to zynq/examples/simple/build.rs diff --git a/examples/simple/memory.x b/zynq/examples/simple/memory.x similarity index 100% rename from examples/simple/memory.x rename to zynq/examples/simple/memory.x diff --git a/examples/simple/src/bin/gtc-ticks.rs b/zynq/examples/simple/src/bin/gtc-ticks.rs similarity index 100% rename from examples/simple/src/bin/gtc-ticks.rs rename to zynq/examples/simple/src/bin/gtc-ticks.rs diff --git a/examples/simple/src/bin/logger.rs b/zynq/examples/simple/src/bin/logger.rs similarity index 100% rename from examples/simple/src/bin/logger.rs rename to zynq/examples/simple/src/bin/logger.rs diff --git a/examples/simple/src/main.rs b/zynq/examples/simple/src/main.rs similarity index 100% rename from examples/simple/src/main.rs rename to zynq/examples/simple/src/main.rs diff --git a/examples/zedboard/Cargo.toml b/zynq/examples/zedboard/Cargo.toml similarity index 90% rename from examples/zedboard/Cargo.toml rename to zynq/examples/zedboard/Cargo.toml index 279562c..34cd460 100644 --- a/examples/zedboard/Cargo.toml +++ b/zynq/examples/zedboard/Cargo.toml @@ -11,7 +11,7 @@ keywords = ["no-std", "arm", "cortex-a", "amd", "zynq7000"] categories = ["embedded", "no-std", "hardware-support"] [dependencies] -cortex-ar = { version = "0.2", git = "https://github.com/rust-embedded/cortex-ar.git", rev = "79dba7000d2090d13823bfb783d9d64be8b778d2", features = ["critical-section-single-core"] } +cortex-ar = "0.3" zynq7000-rt = { path = "../../zynq7000-rt" } zynq7000 = { path = "../../zynq7000" } zynq7000-hal = { path = "../../zynq7000-hal" } @@ -19,7 +19,7 @@ zynq7000-embassy = { path = "../../zynq7000-embassy" } zedboard-bsp = { path = "../../zedboard-bsp" } num_enum = { version = "0.7", default-features = false } l3gd20 = { git = "https://github.com/us-irs/l3gd20.git", branch = "add-async-if" } -embedded-io = "0.6" +embedded-io = "0.7" bitbybit = "1.4" arbitrary-int = "2" embedded-io-async = "0.6" diff --git a/examples/zedboard/build.rs b/zynq/examples/zedboard/build.rs similarity index 100% rename from examples/zedboard/build.rs rename to zynq/examples/zedboard/build.rs diff --git a/examples/zedboard/memory.x b/zynq/examples/zedboard/memory.x similarity index 100% rename from examples/zedboard/memory.x rename to zynq/examples/zedboard/memory.x diff --git a/examples/zedboard/src/bin/ethernet.rs b/zynq/examples/zedboard/src/bin/ethernet.rs similarity index 100% rename from examples/zedboard/src/bin/ethernet.rs rename to zynq/examples/zedboard/src/bin/ethernet.rs diff --git a/examples/zedboard/src/bin/l3gd20h-i2c-mio.rs b/zynq/examples/zedboard/src/bin/l3gd20h-i2c-mio.rs similarity index 100% rename from examples/zedboard/src/bin/l3gd20h-i2c-mio.rs rename to zynq/examples/zedboard/src/bin/l3gd20h-i2c-mio.rs diff --git a/examples/zedboard/src/bin/l3gd20h-spi-mio.rs b/zynq/examples/zedboard/src/bin/l3gd20h-spi-mio.rs similarity index 100% rename from examples/zedboard/src/bin/l3gd20h-spi-mio.rs rename to zynq/examples/zedboard/src/bin/l3gd20h-spi-mio.rs diff --git a/examples/zedboard/src/bin/qspi.rs b/zynq/examples/zedboard/src/bin/qspi.rs similarity index 98% rename from examples/zedboard/src/bin/qspi.rs rename to zynq/examples/zedboard/src/bin/qspi.rs index 7c1e30f..89fd2e8 100644 --- a/examples/zedboard/src/bin/qspi.rs +++ b/zynq/examples/zedboard/src/bin/qspi.rs @@ -10,7 +10,7 @@ use embedded_io::Write; use log::{error, info}; use zedboard::PS_CLOCK_FREQUENCY; use zedboard_bsp::qspi_spansion; -use zynq7000_hal::{clocks, gic, gpio, gtc, prelude::*, qspi, uart, BootMode}; +use zynq7000_hal::{BootMode, clocks, gic, gpio, gtc, prelude::*, qspi, uart}; use zynq7000_rt as _; diff --git a/examples/zedboard/src/bin/uart-blocking.rs b/zynq/examples/zedboard/src/bin/uart-blocking.rs similarity index 100% rename from examples/zedboard/src/bin/uart-blocking.rs rename to zynq/examples/zedboard/src/bin/uart-blocking.rs diff --git a/examples/zedboard/src/bin/uart-non-blocking.rs b/zynq/examples/zedboard/src/bin/uart-non-blocking.rs similarity index 100% rename from examples/zedboard/src/bin/uart-non-blocking.rs rename to zynq/examples/zedboard/src/bin/uart-non-blocking.rs diff --git a/examples/zedboard/src/lib.rs b/zynq/examples/zedboard/src/lib.rs similarity index 100% rename from examples/zedboard/src/lib.rs rename to zynq/examples/zedboard/src/lib.rs diff --git a/examples/zedboard/src/main.rs b/zynq/examples/zedboard/src/main.rs similarity index 98% rename from examples/zedboard/src/main.rs rename to zynq/examples/zedboard/src/main.rs index b08c435..59c4962 100644 --- a/examples/zedboard/src/main.rs +++ b/zynq/examples/zedboard/src/main.rs @@ -9,7 +9,7 @@ use embedded_hal::digital::StatefulOutputPin; use embedded_io::Write; use log::{error, info}; use zedboard::PS_CLOCK_FREQUENCY; -use zynq7000_hal::{clocks, gic, gpio, gtc, uart, BootMode}; +use zynq7000_hal::{BootMode, clocks, gic, gpio, gtc, uart}; use zynq7000_rt as _; diff --git a/gdb.gdb b/zynq/gdb.gdb similarity index 100% rename from gdb.gdb rename to zynq/gdb.gdb diff --git a/rust-toolchain.toml b/zynq/rust-toolchain.toml similarity index 60% rename from rust-toolchain.toml rename to zynq/rust-toolchain.toml index 0e3c7a9..5d56faf 100644 --- a/rust-toolchain.toml +++ b/zynq/rust-toolchain.toml @@ -1,3 +1,2 @@ [toolchain] -# channel = "stable" channel = "nightly" diff --git a/zedboard-bsp/Cargo.toml b/zynq/zedboard-bsp/Cargo.toml similarity index 100% rename from zedboard-bsp/Cargo.toml rename to zynq/zedboard-bsp/Cargo.toml diff --git a/zedboard-bsp/src/lib.rs b/zynq/zedboard-bsp/src/lib.rs similarity index 100% rename from zedboard-bsp/src/lib.rs rename to zynq/zedboard-bsp/src/lib.rs diff --git a/zedboard-bsp/src/phy_marvell.rs b/zynq/zedboard-bsp/src/phy_marvell.rs similarity index 100% rename from zedboard-bsp/src/phy_marvell.rs rename to zynq/zedboard-bsp/src/phy_marvell.rs diff --git a/zedboard-bsp/src/qspi_spansion.rs b/zynq/zedboard-bsp/src/qspi_spansion.rs similarity index 91% rename from zedboard-bsp/src/qspi_spansion.rs rename to zynq/zedboard-bsp/src/qspi_spansion.rs index 31258d6..9eafd3b 100644 --- a/zedboard-bsp/src/qspi_spansion.rs +++ b/zynq/zedboard-bsp/src/qspi_spansion.rs @@ -64,6 +64,8 @@ pub enum SectorArchictecture { Hybrid = 0x01, } +pub const PAGE_SIZE: usize = 256; + #[derive(Debug, Clone, Copy)] pub struct BaseDeviceId { manufacturer_id: u8, @@ -221,6 +223,8 @@ pub enum ProgramPageError { ProgrammingErrorBitSet, #[error("address error: {0}")] Addr(#[from] AddrError), + #[error("data is larger than page size {PAGE_SIZE}")] + DataLargerThanPage, } pub struct QspiSpansionS25Fl256SIoMode(RefCell); @@ -428,14 +432,17 @@ impl QspiSpansionS25Fl256SIoMode { /// This function also takes care of enabling writes before programming the page. /// This function will block until the operation has completed. /// - /// TODO: Allow smaller write size - pub fn program_page(&mut self, addr: u32, data: &[u8; 256]) -> Result<(), ProgramPageError> { + /// The data length max not exceed the page size [PAGE_SIZE]. + pub fn program_page(&mut self, addr: u32, data: &[u8]) -> Result<(), ProgramPageError> { if addr + data.len() as u32 > u24::MAX.as_u32() { return Err(AddrError::OutOfRange.into()); } if !addr.is_multiple_of(0x100) { return Err(AddrError::Alignment.into()); } + if data.len() > PAGE_SIZE { + return Err(ProgramPageError::DataLargerThanPage); + } self.write_enable(); let qspi = self.0.get_mut(); let mut transfer = qspi.transfer_guard(); @@ -448,8 +455,9 @@ impl QspiSpansionS25Fl256SIoMode { transfer.write_word_txd_00(u32::from_ne_bytes(raw_word)); let mut read_index: u32 = 0; let mut current_byte_index = 0; + let fifo_writes = data.len().div_ceil(4); // Fill the FIFO until it is full. - for _ in 0..FIFO_DEPTH - 1 { + for _ in 0..core::cmp::min(fifo_writes, FIFO_DEPTH - 1) { transfer.write_word_txd_00(u32::from_ne_bytes( data[current_byte_index..current_byte_index + 4] .try_into() @@ -470,25 +478,38 @@ impl QspiSpansionS25Fl256SIoMode { } }; - // Immediately fill the FIFO again with the remaining 8 bytes. - wait_for_tx_slot(&mut transfer); + while current_byte_index < data.len() { + // Immediately fill the FIFO again with the remaining 8 bytes. + wait_for_tx_slot(&mut transfer); - transfer.write_word_txd_00(u32::from_ne_bytes( - data[current_byte_index..current_byte_index + 4] - .try_into() - .unwrap(), - )); - current_byte_index += 4; + let word = match core::cmp::min(4, data.len() - current_byte_index) { + 1 => { + let mut bytes = [0; 4]; + bytes[0] = data[current_byte_index]; + u32::from_ne_bytes(bytes) + } + 2 => { + let mut bytes = [0; 4]; + bytes[0..2].copy_from_slice(&data[current_byte_index..current_byte_index + 2]); + u32::from_ne_bytes(bytes) + } + 3 => { + let mut bytes = [0; 4]; + bytes[0..3].copy_from_slice(&data[current_byte_index..current_byte_index + 3]); + u32::from_ne_bytes(bytes) + } + 4 => u32::from_ne_bytes( + data[current_byte_index..current_byte_index + 4] + .try_into() + .unwrap(), + ), + _ => unreachable!(), + }; + transfer.write_word_txd_00(word); + current_byte_index += 4; + } - wait_for_tx_slot(&mut transfer); - - transfer.write_word_txd_00(u32::from_ne_bytes( - data[current_byte_index..current_byte_index + 4] - .try_into() - .unwrap(), - )); - - while read_index < 256 { + while read_index < data.len() as u32 { if transfer.read_status().rx_above_threshold() { transfer.read_rx_data(); read_index = read_index.wrapping_add(4); @@ -528,11 +549,7 @@ impl QspiSpansionS25Fl256SIoMode { if dummy_byte { bytes_to_write += 1; } - let fifo_writes = if bytes_to_write.is_multiple_of(4) { - bytes_to_write / 4 - } else { - (bytes_to_write / 4) + 1 - }; + let fifo_writes = bytes_to_write.div_ceil(4); // Fill the FIFO until it is full or all 0 bytes have been written. for _ in 0..core::cmp::min(fifo_writes, FIFO_DEPTH - 1) { transfer.write_word_txd_00(0); diff --git a/zedboard-fsbl/Cargo.toml b/zynq/zedboard-fsbl/Cargo.toml similarity index 70% rename from zedboard-fsbl/Cargo.toml rename to zynq/zedboard-fsbl/Cargo.toml index 00a44e2..6065e88 100644 --- a/zedboard-fsbl/Cargo.toml +++ b/zynq/zedboard-fsbl/Cargo.toml @@ -9,13 +9,13 @@ repository = "https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs" license = "MIT OR Apache-2.0" [dependencies] -cortex-ar = { version = "0.2", git = "https://github.com/rust-embedded/cortex-ar.git", rev = "79dba7000d2090d13823bfb783d9d64be8b778d2", features = ["critical-section-single-core"] } +cortex-ar = { version = "0.3", features = ["critical-section-single-core"] } zynq7000-rt = { path = "../zynq7000-rt" } zynq7000 = { path = "../zynq7000" } zynq7000-hal = { path = "../zynq7000-hal" } +zynq7000-boot-image = { path = "../../zynq7000-boot-image" } zedboard-bsp = { path = "../zedboard-bsp" } -zynq-boot-image = { path = "../zynq-boot-image" } -embedded-io = "0.6" +embedded-io = "0.7" embedded-hal = "1" fugit = "0.3" log = "0.4" diff --git a/zedboard-fsbl/build.rs b/zynq/zedboard-fsbl/build.rs similarity index 100% rename from zedboard-fsbl/build.rs rename to zynq/zedboard-fsbl/build.rs diff --git a/zedboard-fsbl/memory.x b/zynq/zedboard-fsbl/memory.x similarity index 100% rename from zedboard-fsbl/memory.x rename to zynq/zedboard-fsbl/memory.x diff --git a/zedboard-fsbl/src/ddr_cfg.rs b/zynq/zedboard-fsbl/src/ddr_cfg.rs similarity index 100% rename from zedboard-fsbl/src/ddr_cfg.rs rename to zynq/zedboard-fsbl/src/ddr_cfg.rs diff --git a/zedboard-fsbl/src/main.rs b/zynq/zedboard-fsbl/src/main.rs similarity index 52% rename from zedboard-fsbl/src/main.rs rename to zynq/zedboard-fsbl/src/main.rs index a7e1d68..f985315 100644 --- a/zedboard-fsbl/src/main.rs +++ b/zynq/zedboard-fsbl/src/main.rs @@ -8,7 +8,8 @@ use cortex_ar::asm::nop; use embedded_io::Write as _; use log::{error, info}; use zedboard_bsp::qspi_spansion::{self, QspiSpansionS25Fl256SLinearMode}; -use zynq_boot_image::DestinationDevice; +use zynq7000_boot_image::DestinationDevice; +use zynq7000_hal::priv_tim; use zynq7000_hal::{ BootMode, clocks::{ @@ -16,9 +17,9 @@ use zynq7000_hal::{ pll::{PllConfig, configure_arm_pll, configure_io_pll}, }, ddr::{DdrClockSetupConfig, configure_ddr_for_ddr3, memtest}, - gic, gpio, l2_cache, + devcfg, gic, gpio, l2_cache, prelude::*, - qspi, + qspi::{self, QSPI_START_ADDRESS}, time::Hertz, uart::{ClockConfig, Config, Uart}, }; @@ -80,35 +81,37 @@ pub fn main() -> ! { PllConfig::new_from_target_clock(PS_CLK, IO_CLK).unwrap(), ); - let mut dp = zynq7000::Peripherals::take().unwrap(); + let mut periphs = zynq7000::Peripherals::take().unwrap(); // Clock was already initialized by PS7 Init TCL script or FSBL, we just read it. let clocks = Clocks::new_from_regs(PS_CLK).unwrap(); - let gpio_pins = gpio::GpioPins::new(dp.gpio); + let gpio_pins = gpio::GpioPins::new(periphs.gpio); let mio_pins = gpio_pins.mio; // Set up the UART, we are logging with it. let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200) .unwrap() .0; - let mut uart = Uart::new_with_mio( - dp.uart_1, + let mut logger_uart = Uart::new_with_mio( + periphs.uart_1, Config::new_with_clk_config(uart_clk_config), (mio_pins.mio48, mio_pins.mio49), ) .unwrap(); - uart.write_all(b"-- Zedboard Rust FSBL --\n\r").unwrap(); + logger_uart + .write_all(b"-- Zedboard Rust FSBL --\n\r") + .unwrap(); // Safety: We are not multi-threaded yet. unsafe { zynq7000_hal::log::uart_blocking::init_unsafe_single_core( - uart, + logger_uart, log::LevelFilter::Trace, false, ) }; // Set up the global interrupt controller. - let mut gic = gic::GicConfigurator::new_with_init(dp.gicc, dp.gicd); + let mut gic = gic::GicConfigurator::new_with_init(periphs.gicc, periphs.gicd); gic.enable_all_interrupts(); gic.set_all_spi_interrupt_targets_cpu0(); gic.enable(); @@ -117,7 +120,7 @@ pub fn main() -> ! { info!("Configuring DDR.."); configure_ddr_for_ddr3( - dp.ddrc, + periphs.ddrc, boot_mode, DdrClockSetupConfig { ps_clk: PS_CLK, @@ -132,9 +135,11 @@ pub fn main() -> ! { info!("L2 cache init.."); // Set up the L2 cache now that the DDR is in normal operation mode. - l2_cache::init_with_defaults(&mut dp.l2c); + l2_cache::init_with_defaults(&mut periphs.l2c); info!("L2 cache init done."); + let priv_tim = priv_tim::CpuPrivateTimer::take(clocks.arm_clocks()).unwrap(); + if PERFORM_DDR_MEMTEST { let ddr_base_addr = 0x100000; info!("performing DDR memory test.."); @@ -154,7 +159,7 @@ pub fn main() -> ! { ) .expect("QSPI clock calculation failed"); let qspi = qspi::Qspi::new_single_qspi_with_feedback( - dp.qspi, + periphs.qspi, qspi_clock_config, embedded_hal::spi::MODE_0, qspi::IoType::LvCmos33, @@ -168,19 +173,19 @@ pub fn main() -> ! { let spansion_qspi = qspi_spansion::QspiSpansionS25Fl256SIoMode::new(qspi_io_mode, true); let spansion_lqspi = spansion_qspi.into_linear_addressed(qspi_spansion::QSPI_DEV_COMBINATION_REV_F.into()); - qspi_boot(spansion_lqspi); + qspi_boot(spansion_lqspi, priv_tim); } loop { cortex_ar::asm::nop(); } } -fn qspi_boot(mut qspi: QspiSpansionS25Fl256SLinearMode) -> ! { +fn qspi_boot(mut qspi: QspiSpansionS25Fl256SLinearMode, _priv_tim: priv_tim::CpuPrivateTimer) -> ! { let boot_bin_base_addr = ELF_BASE_ADDR + BOOT_BIN_STAGING_OFFSET; let mut boot_header_slice = unsafe { core::slice::from_raw_parts_mut( boot_bin_base_addr as *mut u8, - zynq_boot_image::FIXED_BOOT_HEADER_SIZE, + zynq7000_boot_image::FIXED_BOOT_HEADER_SIZE, ) }; let read_guard = qspi.read_guard(); @@ -189,12 +194,12 @@ fn qspi_boot(mut qspi: QspiSpansionS25Fl256SLinearMode) -> ! { core::ptr::copy_nonoverlapping( QspiSpansionS25Fl256SLinearMode::BASE_ADDR as *mut u8, boot_header_slice.as_mut_ptr(), - zynq_boot_image::FIXED_BOOT_HEADER_SIZE, + zynq7000_boot_image::FIXED_BOOT_HEADER_SIZE, ); } drop(read_guard); - let boot_header = zynq_boot_image::BootHeader::new(boot_header_slice).unwrap(); + let boot_header = zynq7000_boot_image::BootHeader::new(boot_header_slice).unwrap(); let fsbl_offset = boot_header.source_offset(); boot_header_slice = unsafe { core::slice::from_raw_parts_mut(boot_bin_base_addr as *mut u8, fsbl_offset) }; @@ -203,45 +208,126 @@ fn qspi_boot(mut qspi: QspiSpansionS25Fl256SLinearMode) -> ! { let read_guard = qspi.read_guard(); unsafe { core::ptr::copy_nonoverlapping( - (QspiSpansionS25Fl256SLinearMode::BASE_ADDR + zynq_boot_image::FIXED_BOOT_HEADER_SIZE) - as *mut u8, - boot_header_slice[zynq_boot_image::FIXED_BOOT_HEADER_SIZE..].as_mut_ptr(), - fsbl_offset - zynq_boot_image::FIXED_BOOT_HEADER_SIZE, + (QspiSpansionS25Fl256SLinearMode::BASE_ADDR + + zynq7000_boot_image::FIXED_BOOT_HEADER_SIZE) as *mut u8, + boot_header_slice[zynq7000_boot_image::FIXED_BOOT_HEADER_SIZE..].as_mut_ptr(), + fsbl_offset - zynq7000_boot_image::FIXED_BOOT_HEADER_SIZE, ); } drop(read_guard); - let boot_header = zynq_boot_image::BootHeader::new_unchecked(boot_header_slice); + let boot_header = zynq7000_boot_image::BootHeader::new_unchecked(boot_header_slice); let mut name_buf: [u8; 256] = [0; 256]; - for image_header in boot_header.image_header_iterator().unwrap() { + let mut opt_jump_addr = None; + for (index, image_header) in boot_header.image_header_iterator().unwrap().enumerate() { let name = image_header.image_name(&mut name_buf).unwrap(); - for partition in image_header + if index == 0 { + if !name.contains("fsbl") { + log::warn!("first image name did not contain FSBL string"); + } + // Skip the FSBL. It is probably currently running, and we do not want to re-flash it, + // which would also lead to a self-overwrite. + log::info!("skipping FSBL image"); + continue; + } + + let _read_guard = qspi.read_guard(); + + for (partition_index, partition) in image_header .partition_header_iterator(boot_header_slice) .unwrap() + .enumerate() { let section_attrs = partition.section_attributes(); - if let Ok(dest_dev) = section_attrs.destination_device() { - match dest_dev { - DestinationDevice::Pl => { - info!("Loading image '{name}' to PL (FPGA).."); - // TODO: Load the bitstream. + if section_attrs.destination_device().is_err() { + log::error!( + "invalid destination device ID {}", + section_attrs.destination_device().unwrap_err() + ); + continue; + } + let dest_dev = section_attrs.destination_device().unwrap(); + match dest_dev { + DestinationDevice::Pl => { + info!("Loading image '{name}' to PL (FPGA).."); + // Load the bitstream directly from linear mapped QSPI memory. + let boot_bin_slice = unsafe { + core::slice::from_raw_parts( + (QSPI_START_ADDRESS + + partition + .data_offset() + .expect("invalid PL partition data offset")) + as *const _, + partition.total_partition_length().unwrap(), + ) + }; + // The DMA will read from the linear mapped QSPI directly, so it + // has to be configured for reads using the guard! + devcfg::configure_bitstream_non_secure(true, boot_bin_slice) + .expect("unexpected unaligned address"); + log::info!("loaded bitstream successfully"); + } + DestinationDevice::Ps => { + // Load the bitstream directly from linear mapped QSPI memory. + let load_addr = partition.destination_load_address(); + if load_addr < 0x10_0000 { + panic!("invalid load address which is not located in DDR memory"); } - DestinationDevice::Ps => { - // TODO: Load the binary into DDR. Jump at lowest load address after all - // partitions were parsed. - } - _ => { - error!("Unsupported destination device {dest_dev:?}"); - continue; + log::info!( + "Loading partition {partition_index} for '{name}' to PS with load address {load_addr}.." + ); + + let source_slice = unsafe { + core::slice::from_raw_parts( + (QSPI_START_ADDRESS + + partition + .data_offset() + .expect("invalid PS partition data offset")) + as *const _, + partition.total_partition_length().unwrap(), + ) + }; + let target_slice = unsafe { + core::slice::from_raw_parts_mut( + load_addr as *mut u8, + partition.total_partition_length().unwrap(), + ) + }; + + // Copy from the linear mapped QSPI to DDR, + target_slice.copy_from_slice(source_slice); + + match &mut opt_jump_addr { + Some(current) => *current = core::cmp::min(*current, load_addr), + None => opt_jump_addr = Some(load_addr), } + log::info!("load success"); + } + _ => { + error!("Unsupported destination device {dest_dev:?}"); + continue; } } } } - loop { - cortex_ar::asm::nop(); + match opt_jump_addr { + Some(jump_addr) => { + log::info!("jumping to address {}", jump_addr); + zynq7000_hal::log::uart_blocking::flush(); + + // 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(); + + let jump_func: extern "C" fn() -> ! = unsafe { core::mem::transmute(jump_addr) }; + jump_func(); + } + None => panic!("did not find application elf to boot inside boot binary!"), } } diff --git a/zedboard-qspi-flasher/Cargo.toml b/zynq/zedboard-qspi-flasher/Cargo.toml similarity index 69% rename from zedboard-qspi-flasher/Cargo.toml rename to zynq/zedboard-qspi-flasher/Cargo.toml index 77d7669..11eb7ab 100644 --- a/zedboard-qspi-flasher/Cargo.toml +++ b/zynq/zedboard-qspi-flasher/Cargo.toml @@ -4,11 +4,13 @@ version = "0.1.0" edition = "2024" [dependencies] -cortex-ar = { version = "0.2", git = "https://github.com/rust-embedded/cortex-ar.git", branch = "main" } +cortex-ar = { version = "0.3" } zynq7000-rt = { path = "../zynq7000-rt" } zynq7000 = { path = "../zynq7000" } zynq7000-hal = { path = "../zynq7000-hal" } +zynq7000-boot-image = { path = "../../zynq7000-boot-image" } zedboard-bsp = { path = "../zedboard-bsp" } -embedded-io = "0.6" +embedded-io = "0.7" embedded-hal = "1" log = "0.4" +libm = "0.2" diff --git a/zynq/zedboard-qspi-flasher/build.rs b/zynq/zedboard-qspi-flasher/build.rs new file mode 100644 index 0000000..d534cc3 --- /dev/null +++ b/zynq/zedboard-qspi-flasher/build.rs @@ -0,0 +1,31 @@ +//! This build script copies the `memory.x` file from the crate root into +//! a directory where the linker can always find it at build time. +//! For many projects this is optional, as the linker always searches the +//! project root directory -- wherever `Cargo.toml` is. However, if you +//! are using a workspace or have a more complicated build setup, this +//! build script becomes required. Additionally, by requesting that +//! Cargo re-run the build script whenever `memory.x` is changed, +//! updating `memory.x` ensures a rebuild of the application with the +//! new memory settings. + +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + // Put `memory.x` in our output directory and ensure it's + // on the linker search path. + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + + // By default, Cargo will re-run a build script whenever + // any file in the project changes. By specifying `memory.x` + // here, we ensure the build script is only re-run when + // `memory.x` is changed. + println!("cargo:rerun-if-changed=memory.x"); +} diff --git a/zynq/zedboard-qspi-flasher/memory.x b/zynq/zedboard-qspi-flasher/memory.x new file mode 100644 index 0000000..11faa59 --- /dev/null +++ b/zynq/zedboard-qspi-flasher/memory.x @@ -0,0 +1,22 @@ +MEMORY +{ + /* Zedboard: 512 MB DDR3. Only use 63 MB for now, should be plenty for a bare-metal app. + Leave 1 MB of memory which will be configured as uncached device memory by the MMU. This is + recommended for something like DMA descriptors. */ + CODE(rx) : ORIGIN = 0x00100000, LENGTH = 63M + UNCACHED(rx): ORIGIN = 0x4000000, LENGTH = 1M +} + +REGION_ALIAS("DATA", CODE); + +SECTIONS +{ + /* Uncached memory */ + .uncached (NOLOAD) : ALIGN(4) { + . = ALIGN(4); + _sbss_uncached = .; + *(.uncached .uncached.*); + . = ALIGN(4); + _ebss_uncached = .; + } > UNCACHED +} diff --git a/zynq/zedboard-qspi-flasher/qspi-flasher.tcl b/zynq/zedboard-qspi-flasher/qspi-flasher.tcl new file mode 100644 index 0000000..5c49727 --- /dev/null +++ b/zynq/zedboard-qspi-flasher/qspi-flasher.tcl @@ -0,0 +1,151 @@ +if {[info exists env(ip_address_hw_server)]} { + set ip $env(ip_address_hw_server) +} else { + set ip "localhost" +} + +# absolute directory that contains *this* script +set script_dir [file dirname [info script]] + +# Defaults +set boot_bin_addr 0x10000000 +set boot_bin_size_addr 0x900000 +set init_tcl "" +set bin "" +set bitstream "" + +# Usage helper +proc usage {} { + puts "Usage: xsct qspi-flasher.tcl \[-b|--bin \]" + puts "Options:" + puts " -b, --bin Path to boot binary to flash" + puts " -h, --help Show this help" +} + +# Compact, robust parser +set expecting "" +set endopts 0 +foreach arg $argv { + # If previous option expects a value, take this arg + if {$expecting ne ""} { + set $expecting $arg + set expecting "" + continue + } + + # Option handling (until we see --) + if {!$endopts && [string match "-*" $arg]} { + if {$arg eq "--"} { set endopts 1; continue } + if {$arg eq "-h" || $arg eq "--help"} { usage; exit 0 } + if {$arg eq "-b" || $arg eq "--bin"} { set expecting bin; continue } + puts "error: unknown option: $arg"; usage; exit 1 + } + + # Positional: expect only + if {$init_tcl eq ""} { + set init_tcl $arg + } else { + puts "error: unexpected positional argument: $arg" + usage + exit 1 + } +} + +# Check that QSPI flasher app exists. +set flasher_app [file join $script_dir .. target armv7a-none-eabihf release zedboard-qspi-flasher] +if {![file exists $flasher_app]} { + error "QSPI flasher application not found at path: $flasher_app" +} +set flasher_app [file normalize $flasher_app] + +# Validate required init script +if {$init_tcl eq ""} { + puts "error: missing required first argument pointing to initialization TCL script" + usage + exit 1 +} +if {![file exists $init_tcl]} { + puts "error: the PS init tcl script '$init_tcl' does not exist" + exit 1 +} + +# Resolve app: CLI takes precedence over env(APP) +if {$bin ne ""} { + if {![file exists $bin]} { + puts "error: the boot binary file '$bin' does not exist" + exit 1 + } +} elseif {[info exists env(BOOTBIN)]} { + if {[file exists $env(BOOTBIN)]} { + set bin $env(BOOTBIN) + } else { + puts "warning: BOOTBIN environment variable is set but file does not exist: $env(BOOTBIN)" + } +} + +if {$bin eq ""} { + puts "error: boot.bin binary required" + usage + exit 1 +} + +# Validate bitstream if provided +if {$bitstream ne "" && ![file exists $bitstream]} { + puts "error: the bitstream file '$bitstream' does not exist" + exit 1 +} + +puts "Hardware server IP address: $ip" +connect -url tcp:$ip:3121 + +set devices [targets] + +set apu_line [string trim [targets -nocase -filter {name =~ "APU"}]] +set arm_core_0_line [string trim [targets -nocase -filter {name =~ "ARM Cortex-A9 MPCore #0"}]] +set fpga_line [string trim [targets -nocase -filter {name =~ "xc7z020"}]] + +set apu_device_num [string index $apu_line 0] +set arm_core_0_num [string index $arm_core_0_line 0] +set fpga_device_num [string index $fpga_line 0] + +puts "Select ps target with number: $apu_device_num" + +# Select the target +target $apu_device_num + +# Resetting the target involved problems when an image is stored on the flash. +# It has turned out that it is not essential to reset the system before loading +# the software components into the device. +puts "Reset target" +# TODO: Make the reset optional/configurable via input argument. +# Reset the target +rst + +puts "Set ps target with device number: $arm_core_0_num" +targets $arm_core_0_num + +puts "Initialize processing system" +# Init processing system +source $init_tcl + +ps7_init +ps7_post_config + +puts "Set arm core 0 target with number: $arm_core_0_num" +target $arm_core_0_num + +puts "Download boot.bin $bin to target DDR at address $boot_bin_addr" +dow -data $bin $boot_bin_addr + +# Write boot.bin binary size to specific address. +set boot_bin_size [file size $bin] +puts "Writing boot.bin size $boot_bin_size to target DDR at address $boot_bin_size_addr" +mwr ${boot_bin_size_addr} ${boot_bin_size} + +puts "Flashing QSPI flasher app" +dow $flasher_app + +puts "Starting QSPI flasher app" +con + +puts "Success" diff --git a/zedboard-qspi-flasher/src/main.rs b/zynq/zedboard-qspi-flasher/src/main.rs similarity index 50% rename from zedboard-qspi-flasher/src/main.rs rename to zynq/zedboard-qspi-flasher/src/main.rs index e43c3f7..eff2638 100644 --- a/zedboard-qspi-flasher/src/main.rs +++ b/zynq/zedboard-qspi-flasher/src/main.rs @@ -7,10 +7,11 @@ 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::info; +use log::{error, info}; use zedboard_bsp::qspi_spansion; +use zynq7000_boot_image::BootHeader; use zynq7000_hal::{ - clocks, gpio, prelude::*, priv_tim, qspi, time::Hertz, uart, BootMode, LevelShifterConfig, + BootMode, LevelShifterConfig, clocks, gpio, prelude::*, priv_tim, qspi, time::Hertz, uart, }; use zynq7000_rt as _; @@ -19,6 +20,15 @@ use zynq7000_rt as _; // Not required for the PAC mode, is required for clean delays in HAL mode. const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_333); +// TODO: Make this configurable somehow? +const BOOT_BIN_BASE_ADDR: usize = 0x1000_0000; +const BOOT_BIN_SIZE_ADDR: usize = 0x900_000; + +// Maximum of 16 MB is allowed for now. +const MAX_BOOT_BIN_SIZE: usize = 16 * 1024 * 1024; + +const VERIFY_PROGRAMMING: bool = true; + #[allow(dead_code)] const QSPI_DEV_COMBINATION: qspi::QspiDeviceCombination = qspi::QspiDeviceCombination { vendor: qspi::QspiVendor::WinbondAndSpansion, @@ -67,7 +77,7 @@ pub fn main() -> ! { unsafe { zynq7000_hal::log::uart_blocking::init_unsafe_single_core( uart, - log::LevelFilter::Trace, + log::LevelFilter::Info, false, ) }; @@ -96,7 +106,83 @@ pub fn main() -> ! { let qspi_io_mode = qspi.into_io_mode(false); - let _spansion_qspi = qspi_spansion::QspiSpansionS25Fl256SIoMode::new(qspi_io_mode, true); + let mut spansion_qspi = qspi_spansion::QspiSpansionS25Fl256SIoMode::new(qspi_io_mode, true); + + let mut boot_bin_slice = unsafe { + core::slice::from_raw_parts(BOOT_BIN_BASE_ADDR as *const _, BootHeader::FIXED_SIZED_PART) + }; + // This perform some basic validity checks. + let _boot_header = BootHeader::new(&boot_bin_slice[0..BootHeader::FIXED_SIZED_PART]) + .expect("failed to parse boot header"); + let boot_bin_size = + unsafe { core::ptr::read_volatile(BOOT_BIN_SIZE_ADDR as *const u32) as usize }; + if boot_bin_size == 0 || boot_bin_size > MAX_BOOT_BIN_SIZE { + panic!( + "boot binary size read at address {:#x} is invalid: found {}, must be in range [0, {}]", + BOOT_BIN_SIZE_ADDR, boot_bin_size, MAX_BOOT_BIN_SIZE + ); + } + boot_bin_slice = + unsafe { core::slice::from_raw_parts(BOOT_BIN_BASE_ADDR as *const _, boot_bin_size) }; + info!( + "flashing boot binary with {} bytes to QSPI address 0x0", + boot_bin_size + ); + + let mut current_addr = 0; + let mut read_buf = [0u8; 256]; + let mut next_checkpoint = 0.05; + while current_addr < boot_bin_size { + if current_addr % 0x10000 == 0 { + log::debug!("Erasing sector at address {:#x}", current_addr); + match spansion_qspi.erase_sector(current_addr as u32) { + Ok(()) => {} + Err(e) => { + error!( + "failed to erase sector at address {:#x}: {:?}", + current_addr, e + ); + panic!("QSPI erase failed"); + } + } + } + let write_size = core::cmp::min(256, boot_bin_size - current_addr); + let write_slice = &boot_bin_slice[current_addr..current_addr + write_size]; + log::debug!("Programming address {:#x}", current_addr); + match spansion_qspi.program_page(current_addr as u32, write_slice) { + Ok(()) => {} + Err(e) => { + log::error!( + "failed to write data to QSPI at address {:#x}: {:?}", + current_addr, + e + ); + panic!("QSPI write failed"); + } + } + if VERIFY_PROGRAMMING { + spansion_qspi.read_page_fast_read( + current_addr as u32, + &mut read_buf[0..write_size], + true, + ); + if &read_buf[0..write_size] != write_slice { + error!( + "data verification failed at address {:#x}: wrote {:x?}, read {:x?}", + current_addr, + &write_slice[0..core::cmp::min(16, write_size)], + &read_buf[0..core::cmp::min(16, write_size)] + ); + panic!("QSPI data verification failed"); + } + } + current_addr += write_size; + if current_addr as f32 / boot_bin_size as f32 >= next_checkpoint { + log::info!("Write progress {} %", libm::roundf(next_checkpoint * 100.0)); + next_checkpoint += 0.05; + } + } + info!("flashing done"); let mut mio_led = gpio::Output::new_for_mio(gpio_pins.mio.mio7, gpio::PinState::Low); loop { diff --git a/zynq7000-embassy/Cargo.toml b/zynq/zynq7000-embassy/Cargo.toml similarity index 100% rename from zynq7000-embassy/Cargo.toml rename to zynq/zynq7000-embassy/Cargo.toml diff --git a/zynq7000-embassy/LICENSE-APACHE b/zynq/zynq7000-embassy/LICENSE-APACHE similarity index 100% rename from zynq7000-embassy/LICENSE-APACHE rename to zynq/zynq7000-embassy/LICENSE-APACHE diff --git a/zynq7000-embassy/LICENSE-MIT b/zynq/zynq7000-embassy/LICENSE-MIT similarity index 100% rename from zynq7000-embassy/LICENSE-MIT rename to zynq/zynq7000-embassy/LICENSE-MIT diff --git a/zynq7000-embassy/README.md b/zynq/zynq7000-embassy/README.md similarity index 100% rename from zynq7000-embassy/README.md rename to zynq/zynq7000-embassy/README.md diff --git a/zynq7000-embassy/src/lib.rs b/zynq/zynq7000-embassy/src/lib.rs similarity index 100% rename from zynq7000-embassy/src/lib.rs rename to zynq/zynq7000-embassy/src/lib.rs diff --git a/zynq7000-hal/Cargo.toml b/zynq/zynq7000-hal/Cargo.toml similarity index 85% rename from zynq7000-hal/Cargo.toml rename to zynq/zynq7000-hal/Cargo.toml index 8e8e74d..f5ffc47 100644 --- a/zynq7000-hal/Cargo.toml +++ b/zynq/zynq7000-hal/Cargo.toml @@ -11,9 +11,9 @@ keywords = ["no-std", "hal", "amd", "zynq7000", "xilinx", "bare-metal"] categories = ["embedded", "no-std", "hardware-support"] [dependencies] -cortex-ar = { version = "0.2", git = "https://github.com/rust-embedded/cortex-ar.git", branch = "bump-arbitrary-int" } +cortex-ar = { version = "0.3" } zynq7000 = { path = "../zynq7000" } -zynq-mmu = { path = "../zynq-mmu", version = "0.1.0" } +zynq7000-mmu = { path = "../zynq7000-mmu", version = "0.1.0" } static_assertions = "1.1" bitbybit = "1.4" @@ -22,7 +22,7 @@ thiserror = { version = "2", default-features = false } num_enum = { version = "0.7", default-features = false } ringbuf = { version = "0.4.8", default-features = false } embedded-hal-nb = "1" -embedded-io = "0.6" +embedded-io = "0.7" embedded-hal = "1" embedded-hal-async = "1" heapless = "0.9" @@ -39,7 +39,7 @@ embassy-net-driver = "0.2" smoltcp = { version = "0.12", default-features = false, features = ["proto-ipv4", "medium-ethernet", "socket-raw"] } vcell = "0.1" raw-slicee = "0.1" -embedded-io-async = "0.6" +embedded-io-async = "0.7" [features] std = ["thiserror/std", "alloc"] diff --git a/zynq7000-hal/LICENSE-APACHE b/zynq/zynq7000-hal/LICENSE-APACHE similarity index 100% rename from zynq7000-hal/LICENSE-APACHE rename to zynq/zynq7000-hal/LICENSE-APACHE diff --git a/zynq7000-hal/LICENSE-MIT b/zynq/zynq7000-hal/LICENSE-MIT similarity index 100% rename from zynq7000-hal/LICENSE-MIT rename to zynq/zynq7000-hal/LICENSE-MIT diff --git a/zynq7000-hal/README.md b/zynq/zynq7000-hal/README.md similarity index 100% rename from zynq7000-hal/README.md rename to zynq/zynq7000-hal/README.md diff --git a/zynq7000-hal/docs.sh b/zynq/zynq7000-hal/docs.sh similarity index 100% rename from zynq7000-hal/docs.sh rename to zynq/zynq7000-hal/docs.sh diff --git a/zynq7000-hal/src/cache.rs b/zynq/zynq7000-hal/src/cache.rs similarity index 100% rename from zynq7000-hal/src/cache.rs rename to zynq/zynq7000-hal/src/cache.rs diff --git a/zynq7000-hal/src/clocks/mod.rs b/zynq/zynq7000-hal/src/clocks/mod.rs similarity index 100% rename from zynq7000-hal/src/clocks/mod.rs rename to zynq/zynq7000-hal/src/clocks/mod.rs diff --git a/zynq7000-hal/src/clocks/pll.rs b/zynq/zynq7000-hal/src/clocks/pll.rs similarity index 100% rename from zynq7000-hal/src/clocks/pll.rs rename to zynq/zynq7000-hal/src/clocks/pll.rs diff --git a/zynq7000-hal/src/ddr/ll.rs b/zynq/zynq7000-hal/src/ddr/ll.rs similarity index 100% rename from zynq7000-hal/src/ddr/ll.rs rename to zynq/zynq7000-hal/src/ddr/ll.rs diff --git a/zynq7000-hal/src/ddr/mod.rs b/zynq/zynq7000-hal/src/ddr/mod.rs similarity index 100% rename from zynq7000-hal/src/ddr/mod.rs rename to zynq/zynq7000-hal/src/ddr/mod.rs diff --git a/zynq7000-hal/src/devcfg.rs b/zynq/zynq7000-hal/src/devcfg.rs similarity index 100% rename from zynq7000-hal/src/devcfg.rs rename to zynq/zynq7000-hal/src/devcfg.rs diff --git a/zynq7000-hal/src/eth/embassy_net.rs b/zynq/zynq7000-hal/src/eth/embassy_net.rs similarity index 100% rename from zynq7000-hal/src/eth/embassy_net.rs rename to zynq/zynq7000-hal/src/eth/embassy_net.rs diff --git a/zynq7000-hal/src/eth/ll.rs b/zynq/zynq7000-hal/src/eth/ll.rs similarity index 100% rename from zynq7000-hal/src/eth/ll.rs rename to zynq/zynq7000-hal/src/eth/ll.rs diff --git a/zynq7000-hal/src/eth/mdio.rs b/zynq/zynq7000-hal/src/eth/mdio.rs similarity index 100% rename from zynq7000-hal/src/eth/mdio.rs rename to zynq/zynq7000-hal/src/eth/mdio.rs diff --git a/zynq7000-hal/src/eth/mod.rs b/zynq/zynq7000-hal/src/eth/mod.rs similarity index 100% rename from zynq7000-hal/src/eth/mod.rs rename to zynq/zynq7000-hal/src/eth/mod.rs diff --git a/zynq7000-hal/src/eth/rx_descr.rs b/zynq/zynq7000-hal/src/eth/rx_descr.rs similarity index 100% rename from zynq7000-hal/src/eth/rx_descr.rs rename to zynq/zynq7000-hal/src/eth/rx_descr.rs diff --git a/zynq7000-hal/src/eth/smoltcp.rs b/zynq/zynq7000-hal/src/eth/smoltcp.rs similarity index 100% rename from zynq7000-hal/src/eth/smoltcp.rs rename to zynq/zynq7000-hal/src/eth/smoltcp.rs diff --git a/zynq7000-hal/src/eth/tx_descr.rs b/zynq/zynq7000-hal/src/eth/tx_descr.rs similarity index 100% rename from zynq7000-hal/src/eth/tx_descr.rs rename to zynq/zynq7000-hal/src/eth/tx_descr.rs diff --git a/zynq7000-hal/src/gic.rs b/zynq/zynq7000-hal/src/gic.rs similarity index 100% rename from zynq7000-hal/src/gic.rs rename to zynq/zynq7000-hal/src/gic.rs diff --git a/zynq7000-hal/src/gpio/emio.rs b/zynq/zynq7000-hal/src/gpio/emio.rs similarity index 100% rename from zynq7000-hal/src/gpio/emio.rs rename to zynq/zynq7000-hal/src/gpio/emio.rs diff --git a/zynq7000-hal/src/gpio/ll.rs b/zynq/zynq7000-hal/src/gpio/ll.rs similarity index 100% rename from zynq7000-hal/src/gpio/ll.rs rename to zynq/zynq7000-hal/src/gpio/ll.rs diff --git a/zynq7000-hal/src/gpio/mio.rs b/zynq/zynq7000-hal/src/gpio/mio.rs similarity index 100% rename from zynq7000-hal/src/gpio/mio.rs rename to zynq/zynq7000-hal/src/gpio/mio.rs diff --git a/zynq7000-hal/src/gpio/mod.rs b/zynq/zynq7000-hal/src/gpio/mod.rs similarity index 100% rename from zynq7000-hal/src/gpio/mod.rs rename to zynq/zynq7000-hal/src/gpio/mod.rs diff --git a/zynq7000-hal/src/gtc.rs b/zynq/zynq7000-hal/src/gtc.rs similarity index 100% rename from zynq7000-hal/src/gtc.rs rename to zynq/zynq7000-hal/src/gtc.rs diff --git a/zynq7000-hal/src/i2c.rs b/zynq/zynq7000-hal/src/i2c.rs similarity index 100% rename from zynq7000-hal/src/i2c.rs rename to zynq/zynq7000-hal/src/i2c.rs diff --git a/zynq7000-hal/src/l2_cache.rs b/zynq/zynq7000-hal/src/l2_cache.rs similarity index 100% rename from zynq7000-hal/src/l2_cache.rs rename to zynq/zynq7000-hal/src/l2_cache.rs diff --git a/zynq7000-hal/src/lib.rs b/zynq/zynq7000-hal/src/lib.rs similarity index 100% rename from zynq7000-hal/src/lib.rs rename to zynq/zynq7000-hal/src/lib.rs index c04ea6e..56390bf 100644 --- a/zynq7000-hal/src/lib.rs +++ b/zynq/zynq7000-hal/src/lib.rs @@ -14,8 +14,8 @@ extern crate alloc; use slcr::Slcr; use zynq7000::{ - slcr::{BootModeRegister, BootPllConfig, LevelShifterRegister}, SpiClockPhase, SpiClockPolarity, + slcr::{BootModeRegister, BootPllConfig, LevelShifterRegister}, }; pub mod cache; diff --git a/zynq7000-hal/src/log.rs b/zynq/zynq7000-hal/src/log.rs similarity index 80% rename from zynq7000-hal/src/log.rs rename to zynq/zynq7000-hal/src/log.rs index 06e698a..6593365 100644 --- a/zynq7000-hal/src/log.rs +++ b/zynq/zynq7000-hal/src/log.rs @@ -1,13 +1,23 @@ //! # Simple logging providers. +use core::sync::atomic::{AtomicBool, AtomicU8}; + +static LOGGER_INIT_DONE: AtomicBool = AtomicBool::new(false); + +const LOG_SEL_LOCKED: u8 = 1; +const LOG_SEL_UNSAFE_SINGLE_CORE: u8 = 2; + +static LOG_SEL: AtomicU8 = AtomicU8::new(0); + /// Blocking UART loggers. pub mod uart_blocking { + use super::*; use core::cell::{Cell, RefCell, UnsafeCell}; use embedded_io::Write as _; use cortex_ar::register::Cpsr; use critical_section::Mutex; - use log::{LevelFilter, set_logger, set_max_level}; + use log::{LevelFilter, Log, set_logger, set_max_level}; use crate::uart::Uart; @@ -27,7 +37,10 @@ pub mod uart_blocking { /// For async applications, it is strongly recommended to use the asynchronous ring buffer /// logger instead. pub fn init_with_locks(uart: Uart, level: LevelFilter) { - // TODO: Impl debug for Uart + if LOGGER_INIT_DONE.swap(true, core::sync::atomic::Ordering::Relaxed) { + return; + } + LOG_SEL.swap(LOG_SEL_LOCKED, core::sync::atomic::Ordering::Relaxed); critical_section::with(|cs| { let inner = UART_LOGGER_BLOCKING.0.borrow(cs); inner.replace(Some(uart)); @@ -53,7 +66,16 @@ pub mod uart_blocking { }) } - fn flush(&self) {} + fn flush(&self) { + critical_section::with(|cs| { + let mut opt_logger = self.0.borrow(cs).borrow_mut(); + if opt_logger.is_none() { + return; + } + let logger = opt_logger.as_mut().unwrap(); + logger.flush().unwrap(); + }); + } } pub struct UartLoggerUnsafeSingleThread { @@ -70,23 +92,6 @@ pub mod uart_blocking { uart: UnsafeCell::new(None), }; - /// Initialize the logger with a blocking UART instance. - /// - /// For async applications, it is strongly recommended to use the asynchronous ring buffer - /// logger instead. - /// - /// # Safety - /// - /// This is a blocking logger which performs a write WITHOUT a critical section. This logger is - /// NOT thread-safe. Users must ensure that this logger is not used inside a pre-emptive - /// multi-threading context and interrupt handlers. - pub unsafe fn create_unsafe_single_thread_logger(uart: Uart) -> UartLoggerUnsafeSingleThread { - UartLoggerUnsafeSingleThread { - skip_in_isr: Cell::new(false), - uart: UnsafeCell::new(Some(uart)), - } - } - /// Initialize the logger with a blocking UART instance which does not use locks. /// /// # Safety @@ -95,6 +100,13 @@ pub mod uart_blocking { /// NOT thread-safe, which might lead to garbled output. Log output in ISRs can optionally be /// surpressed. pub unsafe fn init_unsafe_single_core(uart: Uart, level: LevelFilter, skip_in_isr: bool) { + if LOGGER_INIT_DONE.swap(true, core::sync::atomic::Ordering::Relaxed) { + return; + } + LOG_SEL.swap( + LOG_SEL_UNSAFE_SINGLE_CORE, + core::sync::atomic::Ordering::Relaxed, + ); let opt_uart = unsafe { &mut *UART_LOGGER_UNSAFE_SINGLE_THREAD.uart.get() }; opt_uart.replace(uart); UART_LOGGER_UNSAFE_SINGLE_THREAD @@ -134,7 +146,22 @@ pub mod uart_blocking { .unwrap(); } - fn flush(&self) {} + fn flush(&self) { + let uart_mut = unsafe { &mut *self.uart.get() }.as_mut(); + if uart_mut.is_none() { + return; + } + uart_mut.unwrap().flush().unwrap(); + } + } + + // Flush the selected logger instance. + pub fn flush() { + match LOG_SEL.load(core::sync::atomic::Ordering::Relaxed) { + val if val == LOG_SEL_LOCKED => UART_LOGGER_BLOCKING.flush(), + val if val == LOG_SEL_UNSAFE_SINGLE_CORE => UART_LOGGER_UNSAFE_SINGLE_THREAD.flush(), + _ => (), + } } } @@ -205,6 +232,9 @@ pub mod rb { } pub fn init(level: LevelFilter) { + if super::LOGGER_INIT_DONE.swap(true, core::sync::atomic::Ordering::Relaxed) { + return; + } critical_section::with(|cs| { let rb = StaticRb::::default(); let rb_ref = LOGGER_RB.ring_buf.borrow(cs); diff --git a/zynq7000-hal/src/prelude.rs b/zynq/zynq7000-hal/src/prelude.rs similarity index 100% rename from zynq7000-hal/src/prelude.rs rename to zynq/zynq7000-hal/src/prelude.rs diff --git a/zynq7000-hal/src/priv_tim.rs b/zynq/zynq7000-hal/src/priv_tim.rs similarity index 100% rename from zynq7000-hal/src/priv_tim.rs rename to zynq/zynq7000-hal/src/priv_tim.rs diff --git a/zynq7000-hal/src/qspi/lqspi_configs.rs b/zynq/zynq7000-hal/src/qspi/lqspi_configs.rs similarity index 100% rename from zynq7000-hal/src/qspi/lqspi_configs.rs rename to zynq/zynq7000-hal/src/qspi/lqspi_configs.rs diff --git a/zynq7000-hal/src/qspi/mod.rs b/zynq/zynq7000-hal/src/qspi/mod.rs similarity index 100% rename from zynq7000-hal/src/qspi/mod.rs rename to zynq/zynq7000-hal/src/qspi/mod.rs diff --git a/zynq7000-hal/src/slcr.rs b/zynq/zynq7000-hal/src/slcr.rs similarity index 100% rename from zynq7000-hal/src/slcr.rs rename to zynq/zynq7000-hal/src/slcr.rs diff --git a/zynq7000-hal/src/spi/asynch.rs b/zynq/zynq7000-hal/src/spi/asynch.rs similarity index 100% rename from zynq7000-hal/src/spi/asynch.rs rename to zynq/zynq7000-hal/src/spi/asynch.rs diff --git a/zynq7000-hal/src/spi/mod.rs b/zynq/zynq7000-hal/src/spi/mod.rs similarity index 100% rename from zynq7000-hal/src/spi/mod.rs rename to zynq/zynq7000-hal/src/spi/mod.rs diff --git a/zynq7000-hal/src/time.rs b/zynq/zynq7000-hal/src/time.rs similarity index 100% rename from zynq7000-hal/src/time.rs rename to zynq/zynq7000-hal/src/time.rs diff --git a/zynq7000-hal/src/ttc.rs b/zynq/zynq7000-hal/src/ttc.rs similarity index 100% rename from zynq7000-hal/src/ttc.rs rename to zynq/zynq7000-hal/src/ttc.rs diff --git a/zynq7000-hal/src/uart/mod.rs b/zynq/zynq7000-hal/src/uart/mod.rs similarity index 99% rename from zynq7000-hal/src/uart/mod.rs rename to zynq/zynq7000-hal/src/uart/mod.rs index 2d3c6fd..ba9e99d 100644 --- a/zynq7000-hal/src/uart/mod.rs +++ b/zynq/zynq7000-hal/src/uart/mod.rs @@ -578,7 +578,7 @@ impl embedded_hal_nb::serial::Write for Uart { } fn flush(&mut self) -> nb::Result<(), Self::Error> { - self.tx.flush() + embedded_hal_nb::serial::Write::flush(&mut self.tx) } } @@ -604,7 +604,8 @@ impl embedded_io::Write for Uart { } fn flush(&mut self) -> Result<(), Self::Error> { - self.tx.flush() + self.tx.flush(); + Ok(()) } } diff --git a/zynq7000-hal/src/uart/rx.rs b/zynq/zynq7000-hal/src/uart/rx.rs similarity index 100% rename from zynq7000-hal/src/uart/rx.rs rename to zynq/zynq7000-hal/src/uart/rx.rs diff --git a/zynq7000-hal/src/uart/tx.rs b/zynq/zynq7000-hal/src/uart/tx.rs similarity index 96% rename from zynq7000-hal/src/uart/tx.rs rename to zynq/zynq7000-hal/src/uart/tx.rs index 9433174..984e0f8 100644 --- a/zynq7000-hal/src/uart/tx.rs +++ b/zynq/zynq7000-hal/src/uart/tx.rs @@ -78,6 +78,10 @@ impl Tx { } } + pub fn flush(&mut self) { + while !self.regs.read_sr().tx_empty() {} + } + #[inline] pub fn write_fifo_unchecked(&mut self, word: u8) { self.regs.write_fifo(Fifo::new_with_raw_value(word as u32)); @@ -161,11 +165,10 @@ impl embedded_hal_nb::serial::Write for Tx { } fn flush(&mut self) -> nb::Result<(), Self::Error> { - loop { - if self.regs.read_sr().tx_empty() { - return Ok(()); - } + if self.regs.read_sr().tx_empty() { + return Ok(()); } + Err(nb::Error::WouldBlock) } } @@ -195,7 +198,7 @@ impl embedded_io::Write for Tx { } fn flush(&mut self) -> Result<(), Self::Error> { - >::flush(self).ok(); + self.flush(); Ok(()) } } diff --git a/zynq7000-hal/src/uart/tx_async.rs b/zynq/zynq7000-hal/src/uart/tx_async.rs similarity index 97% rename from zynq7000-hal/src/uart/tx_async.rs rename to zynq/zynq7000-hal/src/uart/tx_async.rs index f349e71..3033123 100644 --- a/zynq7000-hal/src/uart/tx_async.rs +++ b/zynq/zynq7000-hal/src/uart/tx_async.rs @@ -202,4 +202,9 @@ impl embedded_io_async::Write for TxAsync { async fn write(&mut self, buf: &[u8]) -> Result { Ok(self.write(buf).await) } + + /// This implementation does not do anything. + async fn flush(&mut self) -> Result<(), Self::Error> { + Ok(()) + } } diff --git a/zynq/zynq7000-mmu/Cargo.toml b/zynq/zynq7000-mmu/Cargo.toml new file mode 100644 index 0000000..06946cf --- /dev/null +++ b/zynq/zynq7000-mmu/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "zynq7000-mmu" +description = "Zynq7000 MMU structures" +version = "0.1.0" +edition = "2024" + +[dependencies] +thiserror = { version = "2", default-features = false } +cortex-ar = { version = "0.3" } + +[features] +tools = [] diff --git a/zynq-mmu/src/lib.rs b/zynq/zynq7000-mmu/src/lib.rs similarity index 100% rename from zynq-mmu/src/lib.rs rename to zynq/zynq7000-mmu/src/lib.rs diff --git a/zynq7000-rt/Cargo.toml b/zynq/zynq7000-rt/Cargo.toml similarity index 79% rename from zynq7000-rt/Cargo.toml rename to zynq/zynq7000-rt/Cargo.toml index fd2df97..1c7197d 100644 --- a/zynq7000-rt/Cargo.toml +++ b/zynq/zynq7000-rt/Cargo.toml @@ -12,13 +12,13 @@ categories = ["embedded", "no-std", "hardware-support"] [dependencies] cortex-a-rt = { version = "0.1", optional = true, features = ["vfp-dp"] } -cortex-ar = { version = "0.2", git = "https://github.com/rust-embedded/cortex-ar.git", branch = "bump-arbitrary-int" } +cortex-ar = { version = "0.3" } arbitrary-int = "2" -zynq-mmu = { path = "../zynq-mmu", version = "0.1.0" } +zynq7000-mmu = { path = "../zynq7000-mmu", version = "0.1.0" } [features] default = ["rt"] -tools = ["zynq-mmu/tools"] +tools = ["zynq7000-mmu/tools"] rt = ["dep:cortex-a-rt"] [[bin]] diff --git a/zynq7000-rt/README.md b/zynq/zynq7000-rt/README.md similarity index 100% rename from zynq7000-rt/README.md rename to zynq/zynq7000-rt/README.md diff --git a/zynq7000-rt/docs.sh b/zynq/zynq7000-rt/docs.sh similarity index 100% rename from zynq7000-rt/docs.sh rename to zynq/zynq7000-rt/docs.sh diff --git a/zynq7000-rt/regen-table.sh b/zynq/zynq7000-rt/regen-table.sh similarity index 100% rename from zynq7000-rt/regen-table.sh rename to zynq/zynq7000-rt/regen-table.sh diff --git a/zynq7000-rt/src/bin/table-gen.rs b/zynq/zynq7000-rt/src/bin/table-gen.rs similarity index 98% rename from zynq7000-rt/src/bin/table-gen.rs rename to zynq/zynq7000-rt/src/bin/table-gen.rs index dccfb0e..000c3c8 100644 --- a/zynq7000-rt/src/bin/table-gen.rs +++ b/zynq/zynq7000-rt/src/bin/table-gen.rs @@ -56,7 +56,7 @@ fn main() { writeln!(buf_writer, "use crate::mmu::section_attrs;").unwrap(); writeln!(buf_writer, "use cortex_ar::mmu::L1Section;").unwrap(); - writeln!(buf_writer, "use zynq_mmu::L1Table;").unwrap(); + writeln!(buf_writer, "use zynq7000_mmu::L1Table;").unwrap(); writeln!(buf_writer, "").unwrap(); writeln!(buf_writer, "/// MMU Level 1 Page table.").unwrap(); diff --git a/zynq7000-rt/src/lib.rs b/zynq/zynq7000-rt/src/lib.rs similarity index 96% rename from zynq7000-rt/src/lib.rs rename to zynq/zynq7000-rt/src/lib.rs index baec7fd..6ae917e 100644 --- a/zynq7000-rt/src/lib.rs +++ b/zynq/zynq7000-rt/src/lib.rs @@ -12,7 +12,7 @@ pub use cortex_a_rt::*; #[cfg(feature = "rt")] -use zynq_mmu::L1TableWrapper; +use zynq7000_mmu::L1TableWrapper; pub mod mmu; #[cfg(feature = "rt")] diff --git a/zynq7000-rt/src/mmu.rs b/zynq/zynq7000-rt/src/mmu.rs similarity index 100% rename from zynq7000-rt/src/mmu.rs rename to zynq/zynq7000-rt/src/mmu.rs diff --git a/zynq7000-rt/src/mmu_table.rs b/zynq/zynq7000-rt/src/mmu_table.rs similarity index 99% rename from zynq7000-rt/src/mmu_table.rs rename to zynq/zynq7000-rt/src/mmu_table.rs index 4ecd507..c4f82ff 100644 --- a/zynq7000-rt/src/mmu_table.rs +++ b/zynq/zynq7000-rt/src/mmu_table.rs @@ -1,7 +1,7 @@ //! This file was auto-generated by table-gen.rs use crate::mmu::section_attrs; use cortex_ar::mmu::L1Section; -use zynq_mmu::L1Table; +use zynq7000_mmu::L1Table; /// MMU Level 1 Page table. /// diff --git a/zynq7000-rt/src/rt.rs b/zynq/zynq7000-rt/src/rt.rs similarity index 100% rename from zynq7000-rt/src/rt.rs rename to zynq/zynq7000-rt/src/rt.rs diff --git a/zynq7000/Cargo.toml b/zynq/zynq7000/Cargo.toml similarity index 100% rename from zynq7000/Cargo.toml rename to zynq/zynq7000/Cargo.toml diff --git a/zynq7000/LICENSE-APACHE b/zynq/zynq7000/LICENSE-APACHE similarity index 100% rename from zynq7000/LICENSE-APACHE rename to zynq/zynq7000/LICENSE-APACHE diff --git a/zynq7000/LICENSE-MIT b/zynq/zynq7000/LICENSE-MIT similarity index 100% rename from zynq7000/LICENSE-MIT rename to zynq/zynq7000/LICENSE-MIT diff --git a/zynq7000/README.md b/zynq/zynq7000/README.md similarity index 100% rename from zynq7000/README.md rename to zynq/zynq7000/README.md diff --git a/zynq7000/build.rs b/zynq/zynq7000/build.rs similarity index 100% rename from zynq7000/build.rs rename to zynq/zynq7000/build.rs diff --git a/zynq7000/docs.sh b/zynq/zynq7000/docs.sh similarity index 100% rename from zynq7000/docs.sh rename to zynq/zynq7000/docs.sh diff --git a/zynq7000/src/ddrc.rs b/zynq/zynq7000/src/ddrc.rs similarity index 100% rename from zynq7000/src/ddrc.rs rename to zynq/zynq7000/src/ddrc.rs diff --git a/zynq7000/src/devcfg.rs b/zynq/zynq7000/src/devcfg.rs similarity index 100% rename from zynq7000/src/devcfg.rs rename to zynq/zynq7000/src/devcfg.rs diff --git a/zynq7000/src/eth.rs b/zynq/zynq7000/src/eth.rs similarity index 100% rename from zynq7000/src/eth.rs rename to zynq/zynq7000/src/eth.rs diff --git a/zynq7000/src/gic.rs b/zynq/zynq7000/src/gic.rs similarity index 100% rename from zynq7000/src/gic.rs rename to zynq/zynq7000/src/gic.rs diff --git a/zynq7000/src/gpio.rs b/zynq/zynq7000/src/gpio.rs similarity index 100% rename from zynq7000/src/gpio.rs rename to zynq/zynq7000/src/gpio.rs diff --git a/zynq7000/src/gtc.rs b/zynq/zynq7000/src/gtc.rs similarity index 100% rename from zynq7000/src/gtc.rs rename to zynq/zynq7000/src/gtc.rs diff --git a/zynq7000/src/i2c.rs b/zynq/zynq7000/src/i2c.rs similarity index 100% rename from zynq7000/src/i2c.rs rename to zynq/zynq7000/src/i2c.rs diff --git a/zynq7000/src/l2_cache.rs b/zynq/zynq7000/src/l2_cache.rs similarity index 100% rename from zynq7000/src/l2_cache.rs rename to zynq/zynq7000/src/l2_cache.rs diff --git a/zynq7000/src/lib.rs b/zynq/zynq7000/src/lib.rs similarity index 100% rename from zynq7000/src/lib.rs rename to zynq/zynq7000/src/lib.rs diff --git a/zynq7000/src/mpcore.rs b/zynq/zynq7000/src/mpcore.rs similarity index 100% rename from zynq7000/src/mpcore.rs rename to zynq/zynq7000/src/mpcore.rs diff --git a/zynq7000/src/priv_tim.rs b/zynq/zynq7000/src/priv_tim.rs similarity index 100% rename from zynq7000/src/priv_tim.rs rename to zynq/zynq7000/src/priv_tim.rs diff --git a/zynq7000/src/qspi.rs b/zynq/zynq7000/src/qspi.rs similarity index 100% rename from zynq7000/src/qspi.rs rename to zynq/zynq7000/src/qspi.rs diff --git a/zynq7000/src/slcr/clocks.rs b/zynq/zynq7000/src/slcr/clocks.rs similarity index 100% rename from zynq7000/src/slcr/clocks.rs rename to zynq/zynq7000/src/slcr/clocks.rs diff --git a/zynq7000/src/slcr/ddriob.rs b/zynq/zynq7000/src/slcr/ddriob.rs similarity index 100% rename from zynq7000/src/slcr/ddriob.rs rename to zynq/zynq7000/src/slcr/ddriob.rs diff --git a/zynq7000/src/slcr/mio.rs b/zynq/zynq7000/src/slcr/mio.rs similarity index 100% rename from zynq7000/src/slcr/mio.rs rename to zynq/zynq7000/src/slcr/mio.rs diff --git a/zynq7000/src/slcr/mod.rs b/zynq/zynq7000/src/slcr/mod.rs similarity index 100% rename from zynq7000/src/slcr/mod.rs rename to zynq/zynq7000/src/slcr/mod.rs diff --git a/zynq7000/src/slcr/reset.rs b/zynq/zynq7000/src/slcr/reset.rs similarity index 100% rename from zynq7000/src/slcr/reset.rs rename to zynq/zynq7000/src/slcr/reset.rs diff --git a/zynq7000/src/spi.rs b/zynq/zynq7000/src/spi.rs similarity index 100% rename from zynq7000/src/spi.rs rename to zynq/zynq7000/src/spi.rs diff --git a/zynq7000/src/ttc.rs b/zynq/zynq7000/src/ttc.rs similarity index 100% rename from zynq7000/src/ttc.rs rename to zynq/zynq7000/src/ttc.rs diff --git a/zynq7000/src/uart.rs b/zynq/zynq7000/src/uart.rs similarity index 100% rename from zynq7000/src/uart.rs rename to zynq/zynq7000/src/uart.rs diff --git a/zynq7000/src/xadc.rs b/zynq/zynq7000/src/xadc.rs similarity index 100% rename from zynq7000/src/xadc.rs rename to zynq/zynq7000/src/xadc.rs diff --git a/zynq7000-boot-image/.gitignore b/zynq7000-boot-image/.gitignore new file mode 100644 index 0000000..5a44eef --- /dev/null +++ b/zynq7000-boot-image/.gitignore @@ -0,0 +1 @@ +/Cargo.lock diff --git a/zynq-boot-image/Cargo.toml b/zynq7000-boot-image/Cargo.toml similarity index 84% rename from zynq-boot-image/Cargo.toml rename to zynq7000-boot-image/Cargo.toml index 922b69b..f72493a 100644 --- a/zynq-boot-image/Cargo.toml +++ b/zynq7000-boot-image/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "zynq-boot-image" +name = "zynq7000-boot-image" version = "0.1.0" edition = "2024" diff --git a/zynq-boot-image/src/lib.rs b/zynq7000-boot-image/src/lib.rs similarity index 100% rename from zynq-boot-image/src/lib.rs rename to zynq7000-boot-image/src/lib.rs diff --git a/zynq-boot-image/staging/.gitignore b/zynq7000-boot-image/staging/.gitignore similarity index 100% rename from zynq-boot-image/staging/.gitignore rename to zynq7000-boot-image/staging/.gitignore diff --git a/zynq-boot-image/staging/README.md b/zynq7000-boot-image/staging/README.md similarity index 100% rename from zynq-boot-image/staging/README.md rename to zynq7000-boot-image/staging/README.md diff --git a/zynq-boot-image/staging/boot.bif b/zynq7000-boot-image/staging/boot.bif similarity index 100% rename from zynq-boot-image/staging/boot.bif rename to zynq7000-boot-image/staging/boot.bif diff --git a/zynq7000-rt/Cargo.lock b/zynq7000-rt/Cargo.lock deleted file mode 100644 index d536135..0000000 --- a/zynq7000-rt/Cargo.lock +++ /dev/null @@ -1,7 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "zynq-rt" -version = "0.1.0"