finished QSPI flasher
Some checks failed
ci / Check build (push) Has been cancelled
ci / Check formatting (push) Has been cancelled
ci / Check Documentation Build (push) Has been cancelled
ci / Clippy (push) Has been cancelled
ci / Check build (pull_request) Has been cancelled
ci / Check formatting (pull_request) Has been cancelled
ci / Check Documentation Build (pull_request) Has been cancelled
ci / Clippy (pull_request) Has been cancelled
Some checks failed
ci / Check build (push) Has been cancelled
ci / Check formatting (push) Has been cancelled
ci / Check Documentation Build (push) Has been cancelled
ci / Clippy (push) Has been cancelled
ci / Check build (pull_request) Has been cancelled
ci / Check formatting (pull_request) Has been cancelled
ci / Check Documentation Build (pull_request) Has been cancelled
ci / Clippy (pull_request) Has been cancelled
This commit is contained in:
@@ -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]
|
[env]
|
||||||
# The following two env variables need to be set for the supplied runner.sh script to work.
|
# The following two env variables need to be set for the supplied runner.sh script to work.
|
||||||
|
|
||||||
|
|||||||
50
.github/workflows/ci.yml
vendored
50
.github/workflows/ci.yml
vendored
@@ -7,41 +7,69 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
- uses: extractions/setup-just@v3
|
||||||
- uses: dtolnay/rust-toolchain@nightly
|
- uses: dtolnay/rust-toolchain@nightly
|
||||||
with:
|
with:
|
||||||
components: rust-src
|
components: rust-src
|
||||||
# Copy config file for rustflags and to build core/alloc.
|
- run: just check zynq
|
||||||
- run: cp .cargo/def-config.toml .cargo/config.toml
|
|
||||||
- run: cargo check --target armv7a-none-eabihf -p zynq7000
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
- run: cargo check --target armv7a-none-eabihf -p zynq7000-rt
|
- 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:
|
fmt:
|
||||||
name: Check formatting
|
name: Check formatting
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@nightly
|
- uses: extractions/setup-just@v3
|
||||||
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
with:
|
with:
|
||||||
components: rustfmt
|
components: rustfmt
|
||||||
- run: cargo fmt --all -- --check
|
- run: just fmt zynq
|
||||||
|
- run: just fmt tools
|
||||||
|
- run: just fmt zynq7000-boot-image
|
||||||
|
|
||||||
docs:
|
docs:
|
||||||
name: Check Documentation Build
|
name: Check Documentation Build
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
- uses: extractions/setup-just@v3
|
||||||
- uses: dtolnay/rust-toolchain@nightly
|
- uses: dtolnay/rust-toolchain@nightly
|
||||||
- run: RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options" cargo +nightly doc -p zynq7000-rt --all-features
|
with:
|
||||||
- run: RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options" cargo +nightly doc -p zynq7000 --all-features
|
components: rust-src
|
||||||
|
- run: just docs-zynq
|
||||||
|
|
||||||
clippy:
|
clippy:
|
||||||
name: Clippy
|
name: Clippy
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
- uses: extractions/setup-just@v3
|
||||||
- uses: dtolnay/rust-toolchain@nightly
|
- uses: dtolnay/rust-toolchain@nightly
|
||||||
with:
|
with:
|
||||||
components: clippy, rust-src
|
components: clippy, rust-src
|
||||||
# Copy config file for rustflags and to build core/alloc.
|
- run: just clippy zynq
|
||||||
- run: cp .cargo/def-config.toml .cargo/config.toml
|
|
||||||
- run: cargo clippy --target armv7a-none-eabihf -- -D warnings
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
with:
|
||||||
|
components: clippy
|
||||||
|
- run: just clippy tools
|
||||||
|
- run: just clippy zynq7000-boot-image
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
/target
|
target
|
||||||
|
|
||||||
/app.map
|
/app.map
|
||||||
/xsct-output.log
|
/xsct-output.log
|
||||||
/.vscode
|
/.vscode
|
||||||
|
|||||||
33
Cargo.toml
33
Cargo.toml
@@ -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"
|
|
||||||
28
README.md
28
README.md
@@ -6,17 +6,23 @@ family of SoCs.
|
|||||||
|
|
||||||
# List of crates
|
# 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)
|
- 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
|
run-time crate containing basic low-level startup code necessary to boot a Rust app on the
|
||||||
Zynq7000.
|
Zynq7000.
|
||||||
- The [`zynq7000`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq7000) PAC
|
- 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)
|
- 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.
|
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)
|
- 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:
|
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
|
This folder also contains dedicated example applications using the
|
||||||
[`embassy`](https://github.com/embassy-rs/embassy) native Rust RTOS.
|
[`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)
|
## Other libraries and tools
|
||||||
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 [`zedboard-fpga-design`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zedboard-fpga-design)
|
||||||
The folder contains a README with all the steps required to load this project from a TCL script.
|
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
|
# 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
|
Use the following command to have a starting `config.toml` file
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
40
justfile
40
justfile
@@ -1,5 +1,45 @@
|
|||||||
|
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']
|
[working-directory: 'zynq-boot-image/staging']
|
||||||
bootgen:
|
bootgen:
|
||||||
bootgen -arch zynq -image boot.bif -o boot.bin -w on
|
bootgen -arch zynq -image boot.bif -o boot.bin -w on
|
||||||
echo "Generated boot.bin at zynq-boot-image/staging"
|
echo "Generated boot.bin at zynq-boot-image/staging"
|
||||||
|
|
||||||
|
[no-cd]
|
||||||
|
run binary:
|
||||||
|
# Run the initialization script. It needs to be run inside the justfile directory.
|
||||||
|
python3 {{justfile_directory()}}/scripts/zynq7000-init.py
|
||||||
|
|
||||||
|
# Run the GDB debugger in GUI mode.
|
||||||
|
gdb-multiarch -q -x {{justfile_directory()}}/zynq/gdb.gdb {{binary}} -tui
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Exit if no arguments are provided
|
|
||||||
if [ "$#" -eq 0 ]; then
|
|
||||||
echo "Error: No arguments provided."
|
|
||||||
echo "Usage: run.sh <binary>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get the absolute path to the `scripts/` directory
|
|
||||||
SCRIPT_DIR="$(cd -- "$(dirname -- "$0")" && pwd)"
|
|
||||||
|
|
||||||
# Get the absolute path to the project root
|
|
||||||
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
||||||
|
|
||||||
# Run the initialization script
|
|
||||||
"$SCRIPT_DIR/zynq7000-init.py"
|
|
||||||
|
|
||||||
# Run the GDB debugger in GUI mode.
|
|
||||||
gdb-multiarch -q -x gdb.gdb "$@" -tui
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
cargo +stable test --target $(rustc -vV | grep host | cut -d ' ' -f2) -p zynq7000-hal
|
|
||||||
cargo +stable test --target $(rustc -vV | grep host | cut -d ' ' -f2) -p zynq7000
|
|
||||||
@@ -121,7 +121,9 @@ def main():
|
|||||||
bitstream = args.bit
|
bitstream = args.bit
|
||||||
init_tcl = args.init_tcl
|
init_tcl = args.init_tcl
|
||||||
|
|
||||||
xsct_script = Path(TCL_SCRIPT_NAME)
|
# Get the script's directory
|
||||||
|
script_dir = Path(__file__).resolve().parent
|
||||||
|
xsct_script = script_dir / TCL_SCRIPT_NAME
|
||||||
|
|
||||||
if not xsct_script.exists():
|
if not xsct_script.exists():
|
||||||
xsct_script = Path(os.path.join(SCRIPTS_DIR, TCL_SCRIPT_NAME))
|
xsct_script = Path(os.path.join(SCRIPTS_DIR, TCL_SCRIPT_NAME))
|
||||||
|
|||||||
796
tools/Cargo.lock
generated
Normal file
796
tools/Cargo.lock
generated
Normal file
@@ -0,0 +1,796 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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 0.60.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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 0.60.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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 = "arm-targets"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3371884971a96d71d8bd4e781188a7d327d7e5e455d07ef4c352922c66695e9e"
|
||||||
|
|
||||||
|
[[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 = "colored"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cortex-ar"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4ea2a354642e242870bc43b57a517359b0be6e96d302b2811cd0644c979c54e"
|
||||||
|
dependencies = [
|
||||||
|
"arbitrary-int 2.0.0",
|
||||||
|
"arm-targets",
|
||||||
|
"bitbybit",
|
||||||
|
"num_enum",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "critical-section"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "deranged"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071"
|
||||||
|
dependencies = [
|
||||||
|
"powerfmt",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive-mmio"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "005a6dabf68a87a460d3cb9b8e2fd5de3f474fc34e8d9451f5a1b6db518da143"
|
||||||
|
dependencies = [
|
||||||
|
"derive-mmio-macro",
|
||||||
|
"rustversion",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive-mmio-macro"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "584dc8e12e4aeb88000c2be8ef7db15657c817fba3e77999a24807d1efcdeefa"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-error2",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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 = "itoa"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.176"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mmu-table-gen"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"zynq7000-mmu",
|
||||||
|
"zynq7000-rt",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-conv"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_enum"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a"
|
||||||
|
dependencies = [
|
||||||
|
"num_enum_derive",
|
||||||
|
"rustversion",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_enum_derive"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_threads"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.21.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||||
|
dependencies = [
|
||||||
|
"critical-section",
|
||||||
|
"portable-atomic",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell_polyfill"
|
||||||
|
version = "1.70.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "portable-atomic"
|
||||||
|
version = "1.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "powerfmt"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error-attr2"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error2"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-error-attr2",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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 = "regex"
|
||||||
|
version = "1.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b5288124840bee7b386bc413c487869b360b2b4ec421ea56425128692f2a82c"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "833eb9ce86d40ef33cb1306d8accf7bc8ec2bfea4355cbdebb3df68b40925cad"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_core"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simple_logger"
|
||||||
|
version = "5.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8c5dfa5e08767553704aa0ffd9d9794d527103c736aba9854773851fd7497eb"
|
||||||
|
dependencies = [
|
||||||
|
"colored",
|
||||||
|
"log",
|
||||||
|
"time",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "static_assertions"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
|
[[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 = "time"
|
||||||
|
version = "0.3.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
|
||||||
|
dependencies = [
|
||||||
|
"deranged",
|
||||||
|
"itoa",
|
||||||
|
"libc",
|
||||||
|
"num-conv",
|
||||||
|
"num_threads",
|
||||||
|
"powerfmt",
|
||||||
|
"serde",
|
||||||
|
"time-core",
|
||||||
|
"time-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time-core"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time-macros"
|
||||||
|
version = "0.2.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3"
|
||||||
|
dependencies = [
|
||||||
|
"num-conv",
|
||||||
|
"time-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.59.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.60.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.53.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.48.5",
|
||||||
|
"windows_aarch64_msvc 0.48.5",
|
||||||
|
"windows_i686_gnu 0.48.5",
|
||||||
|
"windows_i686_msvc 0.48.5",
|
||||||
|
"windows_x86_64_gnu 0.48.5",
|
||||||
|
"windows_x86_64_gnullvm 0.48.5",
|
||||||
|
"windows_x86_64_msvc 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.52.6",
|
||||||
|
"windows_aarch64_msvc 0.52.6",
|
||||||
|
"windows_i686_gnu 0.52.6",
|
||||||
|
"windows_i686_gnullvm 0.52.6",
|
||||||
|
"windows_i686_msvc 0.52.6",
|
||||||
|
"windows_x86_64_gnu 0.52.6",
|
||||||
|
"windows_x86_64_gnullvm 0.52.6",
|
||||||
|
"windows_x86_64_msvc 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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 0.53.1",
|
||||||
|
"windows_aarch64_msvc 0.53.1",
|
||||||
|
"windows_i686_gnu 0.53.1",
|
||||||
|
"windows_i686_gnullvm 0.53.1",
|
||||||
|
"windows_i686_msvc 0.53.1",
|
||||||
|
"windows_x86_64_gnu 0.53.1",
|
||||||
|
"windows_x86_64_gnullvm 0.53.1",
|
||||||
|
"windows_x86_64_msvc 0.53.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
|
[[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.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
|
[[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.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
|
[[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.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
|
[[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.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
|
[[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.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
|
[[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.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
|
[[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.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
|
[[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"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"arbitrary-int 2.0.0",
|
||||||
|
"bitbybit",
|
||||||
|
"derive-mmio",
|
||||||
|
"once_cell",
|
||||||
|
"rustversion",
|
||||||
|
"static_assertions",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zynq7000-boot-image"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"arbitrary-int 2.0.0",
|
||||||
|
"bitbybit",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zynq7000-mmu"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"cortex-ar",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zynq7000-ps7init-extract"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"log",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"regex",
|
||||||
|
"simple_logger",
|
||||||
|
"syn",
|
||||||
|
"zynq7000",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zynq7000-rt"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"arbitrary-int 2.0.0",
|
||||||
|
"cortex-ar",
|
||||||
|
"zynq7000-mmu",
|
||||||
|
]
|
||||||
7
tools/Cargo.toml
Normal file
7
tools/Cargo.toml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[workspace]
|
||||||
|
resolver = "3"
|
||||||
|
members = [
|
||||||
|
"boot-image-test",
|
||||||
|
"mmu-table-gen",
|
||||||
|
"zynq7000-ps7init-extract",
|
||||||
|
]
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
[workspace]
|
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "tester"
|
name = "boot-image-test"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
zynq-boot-image= { path = ".." }
|
zynq7000-boot-image= { path = "../../zynq7000-boot-image" }
|
||||||
clap = { version = "4", features = ["derive"] }
|
clap = { version = "4", features = ["derive"] }
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
use std::{io::Read, path::Path};
|
use std::{io::Read, path::Path};
|
||||||
|
|
||||||
use clap::Parser as _;
|
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)]
|
#[derive(clap::Parser, Debug)]
|
||||||
#[command(version, about)]
|
#[command(version, about)]
|
||||||
8
tools/mmu-table-gen/Cargo.toml
Normal file
8
tools/mmu-table-gen/Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "mmu-table-gen"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
zynq7000-rt = { path = "../../zynq/zynq7000-rt", default-features = false }
|
||||||
|
zynq7000-mmu = { path = "../../zynq/zynq7000-mmu", features = ["tools"] }
|
||||||
@@ -16,7 +16,7 @@ macro_rules! write_l1_section {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let file_path = "src/mmu_table.rs";
|
let file_path = "mmu_table.rs";
|
||||||
let file = File::create(file_path).expect("Failed to create file");
|
let file = File::create(file_path).expect("Failed to create file");
|
||||||
|
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
@@ -56,7 +56,7 @@ fn main() {
|
|||||||
|
|
||||||
writeln!(buf_writer, "use crate::mmu::section_attrs;").unwrap();
|
writeln!(buf_writer, "use crate::mmu::section_attrs;").unwrap();
|
||||||
writeln!(buf_writer, "use cortex_ar::mmu::L1Section;").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, "").unwrap();
|
||||||
|
|
||||||
writeln!(buf_writer, "/// MMU Level 1 Page table.").unwrap();
|
writeln!(buf_writer, "/// MMU Level 1 Page table.").unwrap();
|
||||||
2
tools/zynq7000-ps7init-extract/.gitignore
vendored
Normal file
2
tools/zynq7000-ps7init-extract/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/ddrc_config_autogen.rs
|
||||||
|
/ddriob_config_autogen.rs
|
||||||
251
tools/zynq7000-ps7init-extract/Cargo.lock
generated
Normal file
251
tools/zynq7000-ps7init-extract/Cargo.lock
generated
Normal file
@@ -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",
|
||||||
|
]
|
||||||
14
tools/zynq7000-ps7init-extract/Cargo.toml
Normal file
14
tools/zynq7000-ps7init-extract/Cargo.toml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "zynq7000-ps7init-extract"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
clap = { version = "4", features = ["derive"] }
|
||||||
|
zynq7000 = { path = "../../zynq/zynq7000" }
|
||||||
|
log = "0.4"
|
||||||
|
simple_logger = "5"
|
||||||
|
regex = "1"
|
||||||
|
quote = "1"
|
||||||
|
syn = "2"
|
||||||
|
proc-macro2 = "1"
|
||||||
26
tools/zynq7000-ps7init-extract/README.md
Normal file
26
tools/zynq7000-ps7init-extract/README.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
Zynq7000 PS7 Init Extractor
|
||||||
|
=========
|
||||||
|
|
||||||
|
AMD provides tooling to auto-generate some of the hardware initialization for the external DDR
|
||||||
|
as native Rust code.
|
||||||
|
|
||||||
|
The AMD tooling generates these files as `ps7init.tcl`, `ps7init.c`, `ps7init.h` files but not as
|
||||||
|
Rust files. The specific parameters required for different DDR chips are proprietary, so that
|
||||||
|
portion is required for Rust programs as well. Do avoid the need of compiling the PS7 initialization
|
||||||
|
scripts with a C compiler, this tool extracts all required configuration parameters for DDR and
|
||||||
|
DDRIOB initialization and configuration and exports them as native Rust constants.
|
||||||
|
|
||||||
|
The generates files can be placed in individual projects or board support packages to initialize
|
||||||
|
the DDR in conjunction with the [Zynq7000 HAL library](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/fsbl-rs/zynq/zynq7000-hal).
|
||||||
|
|
||||||
|
Right now, the script expects the `ps7init.tcl` file to be passed as a command line argument
|
||||||
|
for `-p` or `--path`. It then generates the configuration as a `ddrc_config_autogen.rs` and
|
||||||
|
`ddrc_config_autogen.rs` file.
|
||||||
|
|
||||||
|
For example, assuming that there is a `ps7init.tcl` script in the current directory, you can use
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo run -- --path ./ps7init.tcl
|
||||||
|
```
|
||||||
|
|
||||||
|
to generate the configuration files.
|
||||||
341
tools/zynq7000-ps7init-extract/src/main.rs
Normal file
341
tools/zynq7000-ps7init-extract/src/main.rs
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
use std::{collections::HashMap, ops::RangeInclusive, path::Path};
|
||||||
|
|
||||||
|
use clap::Parser as _;
|
||||||
|
use simple_logger::SimpleLogger;
|
||||||
|
|
||||||
|
const DDRC_ADDR_RANGE: RangeInclusive<u32> = 0xf800_6000..=0xf800_62b4;
|
||||||
|
const DDRIOB_ADDR_RANGE: RangeInclusive<u32> = 0xf800_0b40..=0xf800_0b68;
|
||||||
|
|
||||||
|
const DDRC_FILE_NAME: &str = "ddrc_config_autogen.rs";
|
||||||
|
const DDRIOB_FILE_NAME: &str = "ddriob_config_autogen.rs";
|
||||||
|
|
||||||
|
#[derive(clap::Parser, Debug)]
|
||||||
|
#[command(version, about)]
|
||||||
|
pub struct Cli {
|
||||||
|
/// Path to ps7init.tcl file.
|
||||||
|
#[arg(short, long)]
|
||||||
|
path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extract_hex_values(line: &str) -> Option<(u32, u32, u32)> {
|
||||||
|
let re = regex::Regex::new(r"0[xX]([0-9A-Fa-f]+)").unwrap();
|
||||||
|
|
||||||
|
let captures: Vec<u32> = re
|
||||||
|
.captures_iter(line)
|
||||||
|
.filter_map(|cap| u32::from_str_radix(&cap[1], 16).ok())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if captures.len() == 3 {
|
||||||
|
Some((captures[0], captures[1], captures[2]))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct RegisterToValueMap(pub HashMap<u32, u32>);
|
||||||
|
|
||||||
|
impl RegisterToValueMap {
|
||||||
|
fn val_as_token(&self, reg_name: &str, addr: u32) -> proc_macro2::TokenStream {
|
||||||
|
let val = self.0.get(&addr).unwrap_or_else(|| {
|
||||||
|
panic!(
|
||||||
|
"failed to retrieve register value for register {}",
|
||||||
|
reg_name
|
||||||
|
)
|
||||||
|
});
|
||||||
|
format!("{:#010x}", val)
|
||||||
|
.parse::<proc_macro2::TokenStream>()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ParsingMode {
|
||||||
|
DdrRev3,
|
||||||
|
MioRev3,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> std::io::Result<()> {
|
||||||
|
SimpleLogger::new().init().unwrap();
|
||||||
|
let cli = Cli::parse();
|
||||||
|
let ps7init_tcl = Path::new(&cli.path);
|
||||||
|
if !ps7init_tcl.exists() {
|
||||||
|
log::error!("File not found: {}", ps7init_tcl.display());
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
let mut parsing_mode = None;
|
||||||
|
|
||||||
|
let mut reg_to_values = RegisterToValueMap::default();
|
||||||
|
|
||||||
|
for line in std::fs::read_to_string(ps7init_tcl)?.lines() {
|
||||||
|
match parsing_mode {
|
||||||
|
None => {
|
||||||
|
if line.contains("ps7_ddr_init_data_3_0") {
|
||||||
|
parsing_mode = Some(ParsingMode::DdrRev3);
|
||||||
|
} else if line.contains("ps7_mio_init_data_3_0") {
|
||||||
|
parsing_mode = Some(ParsingMode::MioRev3);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Some(ParsingMode::MioRev3) => {
|
||||||
|
if line.contains("}") {
|
||||||
|
parsing_mode = None;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(ParsingMode::DdrRev3) => {
|
||||||
|
if line.contains("}") {
|
||||||
|
parsing_mode = None;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((addr, _mask, value)) = extract_hex_values(line)
|
||||||
|
&& (DDRC_ADDR_RANGE.contains(&addr) || DDRIOB_ADDR_RANGE.contains(&addr))
|
||||||
|
&& addr % 4 == 0
|
||||||
|
{
|
||||||
|
// Only use first value.
|
||||||
|
if reg_to_values.0.contains_key(&addr) {
|
||||||
|
if addr != 0xF800_6000 {
|
||||||
|
log::warn!("detected duplicate register value for address {}", addr);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
reg_to_values.0.insert(addr, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log::info!("generating DDRC config files: {}", DDRC_FILE_NAME);
|
||||||
|
generate_ddrc_config(®_to_values, DDRC_FILE_NAME)?;
|
||||||
|
|
||||||
|
log::info!("generating DDRIOB config files: {}", DDRIOB_FILE_NAME);
|
||||||
|
generate_ddriob_config(®_to_values, DDRIOB_FILE_NAME)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_ddrc_config(
|
||||||
|
reg_to_values: &RegisterToValueMap,
|
||||||
|
file_name: &str,
|
||||||
|
) -> std::io::Result<()> {
|
||||||
|
// Format as hex strings
|
||||||
|
let ddrc = reg_to_values.val_as_token("DDRC Control", 0xF800_6000);
|
||||||
|
let two_rank = reg_to_values.val_as_token("Two Rank", 0xF800_6004);
|
||||||
|
let hpr = reg_to_values.val_as_token("HPR", 0xF800_6008);
|
||||||
|
let lpr = reg_to_values.val_as_token("LPR", 0xF800_600C);
|
||||||
|
let wr = reg_to_values.val_as_token("WR", 0xF800_6010);
|
||||||
|
let dram_param_0 = reg_to_values.val_as_token("DRAM Reg0", 0xF800_6014);
|
||||||
|
let dram_param_1 = reg_to_values.val_as_token("DRAM Reg1", 0xF800_6018);
|
||||||
|
let dram_param_2 = reg_to_values.val_as_token("DRAM Reg2", 0xF800_601C);
|
||||||
|
let dram_param_3 = reg_to_values.val_as_token("DRAM Reg3", 0xF800_6020);
|
||||||
|
let dram_param_4 = reg_to_values.val_as_token("DRAM Reg4", 0xF800_6024);
|
||||||
|
let dram_init_param = reg_to_values.val_as_token("DRAM Init Param", 0xF800_6028);
|
||||||
|
let dram_emr = reg_to_values.val_as_token("DRAM EMR", 0xF800_602C);
|
||||||
|
let dram_emr_mr = reg_to_values.val_as_token("DRAM EMR MR", 0xF800_6030);
|
||||||
|
let dram_burst8_rdwr = reg_to_values.val_as_token("DRAM Burst8 RDWR", 0xF800_6034);
|
||||||
|
let dram_disable_dq = reg_to_values.val_as_token("DRAM Disable DQ", 0xF800_6038);
|
||||||
|
let dram_addr_map_bank = reg_to_values.val_as_token("DRAM Addr Map Bank", 0xF800_603C);
|
||||||
|
let dram_addr_map_col = reg_to_values.val_as_token("DRAM Addr Map Col", 0xF800_6040);
|
||||||
|
let dram_addr_map_row = reg_to_values.val_as_token("DRAM Addr Map Row", 0xF800_6044);
|
||||||
|
let dram_odt = reg_to_values.val_as_token("DRAM ODT", 0xF800_6048);
|
||||||
|
let phy_cmd_timeout_rddata_cpt = reg_to_values.val_as_token("PHY CMD Timeout", 0xF800_6050);
|
||||||
|
let dll_calib = reg_to_values.val_as_token("DLL Calib", 0xF800_6058);
|
||||||
|
let odt_delay_hold = reg_to_values.val_as_token("ODT Delay Hold", 0xF800_605C);
|
||||||
|
let ctrl_reg1 = reg_to_values.val_as_token("CTRL Reg 1", 0xF800_6060);
|
||||||
|
let ctrl_reg2 = reg_to_values.val_as_token("CTRL Reg 2", 0xF800_6064);
|
||||||
|
let ctrl_reg3 = reg_to_values.val_as_token("CTRL Reg 3", 0xF800_6068);
|
||||||
|
let ctrl_reg4 = reg_to_values.val_as_token("CTRL Reg 4", 0xF800_606C);
|
||||||
|
let ctrl_reg5 = reg_to_values.val_as_token("CTRL Reg 5", 0xF800_6078);
|
||||||
|
let ctrl_reg6 = reg_to_values.val_as_token("CTRL Reg 6", 0xF800_607C);
|
||||||
|
let che_t_zq = reg_to_values.val_as_token("CHE T ZQ", 0xF800_60A4);
|
||||||
|
let che_t_zq_short_interval_reg =
|
||||||
|
reg_to_values.val_as_token("CHE T ZQ Short Interval", 0xF800_60A4);
|
||||||
|
let deep_powerdown = reg_to_values.val_as_token("Deep Powerdown", 0xF800_60AC);
|
||||||
|
let reg_2c = reg_to_values.val_as_token("Reg 2C", 0xF800_60B0);
|
||||||
|
let reg_2d = reg_to_values.val_as_token("Reg 2D", 0xF800_60B4);
|
||||||
|
let dfi_timing = reg_to_values.val_as_token("DFI Timing", 0xF800_60B8);
|
||||||
|
let che_ecc_ctrl = reg_to_values.val_as_token("CHE ECC CTRL", 0xF800_60C4);
|
||||||
|
let ecc_scrub = reg_to_values.val_as_token("ECC Scrub", 0xF800_60F4);
|
||||||
|
let phy_receiver_enable = reg_to_values.val_as_token("PHY Receiver Enable", 0xF800_6114);
|
||||||
|
let phy_config_0 = reg_to_values.val_as_token("PHY Config 0", 0xF800_6118);
|
||||||
|
let phy_config_1 = reg_to_values.val_as_token("PHY Config 1", 0xF800_611C);
|
||||||
|
let phy_config_2 = reg_to_values.val_as_token("PHY Config 2", 0xF800_6120);
|
||||||
|
let phy_config_3 = reg_to_values.val_as_token("PHY Config 3", 0xF800_6124);
|
||||||
|
let phy_init_ratio_0 = reg_to_values.val_as_token("PHY Init Ratio 0", 0xF800_612C);
|
||||||
|
let phy_init_ratio_1 = reg_to_values.val_as_token("PHY Init Ratio 1", 0xF800_6130);
|
||||||
|
let phy_init_ratio_2 = reg_to_values.val_as_token("PHY Init Ratio 2", 0xF800_6134);
|
||||||
|
let phy_init_ratio_3 = reg_to_values.val_as_token("PHY Init Ratio 3", 0xF800_6138);
|
||||||
|
let phy_rd_dqs_config_0 = reg_to_values.val_as_token("PHY RD DQS Config 0", 0xF800_6140);
|
||||||
|
let phy_rd_dqs_config_1 = reg_to_values.val_as_token("PHY RD DQS Config 1", 0xF800_6144);
|
||||||
|
let phy_rd_dqs_config_2 = reg_to_values.val_as_token("PHY RD DQS Config 2", 0xF800_6148);
|
||||||
|
let phy_rd_dqs_config_3 = reg_to_values.val_as_token("PHY RD DQS Config 3", 0xF800_614C);
|
||||||
|
let phy_wr_dqs_config_0 = reg_to_values.val_as_token("PHY WR DQS Config 0", 0xF800_6154);
|
||||||
|
let phy_wr_dqs_config_1 = reg_to_values.val_as_token("PHY WR DQS Config 1", 0xF800_6158);
|
||||||
|
let phy_wr_dqs_config_2 = reg_to_values.val_as_token("PHY WR DQS Config 2", 0xF800_615C);
|
||||||
|
let phy_wr_dqs_config_3 = reg_to_values.val_as_token("PHY WR DQS Config 3", 0xF800_6160);
|
||||||
|
let phy_we_cfg_0 = reg_to_values.val_as_token("PHY WE Config 0", 0xF800_6168);
|
||||||
|
let phy_we_cfg_1 = reg_to_values.val_as_token("PHY WE Config 1", 0xF800_616C);
|
||||||
|
let phy_we_cfg_2 = reg_to_values.val_as_token("PHY WE Config 2", 0xF800_6170);
|
||||||
|
let phy_we_cfg_3 = reg_to_values.val_as_token("PHY WE Config 3", 0xF800_6174);
|
||||||
|
let phy_wr_data_slv_0 = reg_to_values.val_as_token("PHY WR Data Slv 0", 0xF800_617C);
|
||||||
|
let phy_wr_data_slv_1 = reg_to_values.val_as_token("PHY WR Data Slv 1", 0xF800_6180);
|
||||||
|
let phy_wr_data_slv_2 = reg_to_values.val_as_token("PHY WR Data Slv 2", 0xF800_6184);
|
||||||
|
let phy_wr_data_slv_3 = reg_to_values.val_as_token("PHY WR Data Slv 3", 0xF800_6188);
|
||||||
|
let reg64 = reg_to_values.val_as_token("Reg64", 0xF800_6190);
|
||||||
|
let reg65 = reg_to_values.val_as_token("Reg65", 0xF800_6194);
|
||||||
|
let page_mask = reg_to_values.val_as_token("Page Mask", 0xF800_6204);
|
||||||
|
let axi_priority_wr_port_0 = reg_to_values.val_as_token("AXI Priority WR Port 0", 0xF800_6208);
|
||||||
|
let axi_priority_wr_port_1 = reg_to_values.val_as_token("AXI Priority WR Port 1", 0xF800_620C);
|
||||||
|
let axi_priority_wr_port_2 = reg_to_values.val_as_token("AXI Priority WR Port 2", 0xF800_6210);
|
||||||
|
let axi_priority_wr_port_3 = reg_to_values.val_as_token("AXI Priority WR Port 3", 0xF800_6214);
|
||||||
|
let axi_priority_rd_port_0 = reg_to_values.val_as_token("AXI Priority RD Port 0", 0xF800_6218);
|
||||||
|
let axi_priority_rd_port_1 = reg_to_values.val_as_token("AXI Priority RD Port 1", 0xF800_621C);
|
||||||
|
let axi_priority_rd_port_2 = reg_to_values.val_as_token("AXI Priority RD Port 2", 0xF800_6220);
|
||||||
|
let axi_priority_rd_port_3 = reg_to_values.val_as_token("AXI Priority RD Port 3", 0xF800_6224);
|
||||||
|
let lpddr_ctrl_0 = reg_to_values.val_as_token("LPDDR CTRL 0", 0xF800_62A8);
|
||||||
|
let lpddr_ctrl_1 = reg_to_values.val_as_token("LPDDR CTRL 1", 0xF800_62AC);
|
||||||
|
let lpddr_ctrl_2 = reg_to_values.val_as_token("LPDDR CTRL 2", 0xF800_62B0);
|
||||||
|
let lpddr_ctrl_3 = reg_to_values.val_as_token("LPDDR CTRL 3", 0xF800_62B4);
|
||||||
|
|
||||||
|
let generated = quote::quote! {
|
||||||
|
//!This file was auto-generated by the [zynq7000-ps7init-extract](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/tools/zynq7000-ps7init-extract) program.
|
||||||
|
//!
|
||||||
|
//!This configuration file contains static DDR configuration parameters extracted from the
|
||||||
|
//!AMD ps7init.tcl file
|
||||||
|
use zynq7000::ddrc::regs;
|
||||||
|
use zynq7000_hal::ddr::DdrcConfigSet;
|
||||||
|
|
||||||
|
pub const DDRC_CONFIG_ZEDBOARD: DdrcConfigSet = DdrcConfigSet {
|
||||||
|
ctrl: regs::DdrcControl::new_with_raw_value(#ddrc),
|
||||||
|
two_rank: regs::TwoRankConfig::new_with_raw_value(#two_rank),
|
||||||
|
hpr: regs::LprHprQueueControl::new_with_raw_value(#hpr),
|
||||||
|
lpr: regs::LprHprQueueControl::new_with_raw_value(#lpr),
|
||||||
|
wr: regs::WriteQueueControl::new_with_raw_value(#wr),
|
||||||
|
dram_param_0: regs::DramParamReg0::new_with_raw_value(#dram_param_0),
|
||||||
|
dram_param_1: regs::DramParamReg1::new_with_raw_value(#dram_param_1),
|
||||||
|
dram_param_2: regs::DramParamReg2::new_with_raw_value(#dram_param_2),
|
||||||
|
dram_param_3: regs::DramParamReg3::new_with_raw_value(#dram_param_3),
|
||||||
|
dram_param_4: regs::DramParamReg4::new_with_raw_value(#dram_param_4),
|
||||||
|
dram_init_param: regs::DramInitParam::new_with_raw_value(#dram_init_param),
|
||||||
|
dram_emr: regs::DramEmr::new_with_raw_value(#dram_emr),
|
||||||
|
dram_emr_mr: regs::DramEmrMr::new_with_raw_value(#dram_emr_mr),
|
||||||
|
dram_burst8_rdwr: regs::DramBurst8ReadWrite::new_with_raw_value(#dram_burst8_rdwr),
|
||||||
|
disable_dq: regs::DisableDq::new_with_raw_value(#dram_disable_dq),
|
||||||
|
dram_addr_map_bank: regs::DramAddrMapBank::new_with_raw_value(#dram_addr_map_bank),
|
||||||
|
dram_addr_map_col: regs::DramAddrMapColumn::new_with_raw_value(#dram_addr_map_col),
|
||||||
|
dram_addr_map_row: regs::DramAddrMapRow::new_with_raw_value(#dram_addr_map_row),
|
||||||
|
dram_odt: regs::DramOdt::new_with_raw_value(#dram_odt),
|
||||||
|
phy_cmd_timeout_rddata_cpt: regs::PhyCmdTimeoutRdDataCpt::new_with_raw_value(#phy_cmd_timeout_rddata_cpt),
|
||||||
|
dll_calib: regs::DllCalib::new_with_raw_value(#dll_calib),
|
||||||
|
odt_delay_hold: regs::OdtDelayHold::new_with_raw_value(#odt_delay_hold),
|
||||||
|
ctrl_reg1: regs::CtrlReg1::new_with_raw_value(#ctrl_reg1),
|
||||||
|
ctrl_reg2: regs::CtrlReg2::new_with_raw_value(#ctrl_reg2),
|
||||||
|
ctrl_reg3: regs::CtrlReg3::new_with_raw_value(#ctrl_reg3),
|
||||||
|
ctrl_reg4: regs::CtrlReg4::new_with_raw_value(#ctrl_reg4),
|
||||||
|
ctrl_reg5: regs::CtrlReg5::new_with_raw_value(#ctrl_reg5),
|
||||||
|
ctrl_reg6: regs::CtrlReg6::new_with_raw_value(#ctrl_reg6),
|
||||||
|
che_t_zq: regs::CheTZq::new_with_raw_value(#che_t_zq),
|
||||||
|
che_t_zq_short_interval_reg: regs::CheTZqShortInterval::new_with_raw_value(#che_t_zq_short_interval_reg),
|
||||||
|
deep_powerdown: regs::DeepPowerdown::new_with_raw_value(#deep_powerdown),
|
||||||
|
reg_2c: regs::Reg2c::new_with_raw_value(#reg_2c),
|
||||||
|
reg_2d: regs::Reg2d::new_with_raw_value(#reg_2d),
|
||||||
|
dfi_timing: regs::DfiTiming::new_with_raw_value(#dfi_timing),
|
||||||
|
che_ecc_ctrl: regs::CheEccControl::new_with_raw_value(#che_ecc_ctrl),
|
||||||
|
ecc_scrub: regs::EccScrub::new_with_raw_value(#ecc_scrub),
|
||||||
|
phy_receiver_enable: regs::PhyReceiverEnable::new_with_raw_value(#phy_receiver_enable),
|
||||||
|
phy_config: [
|
||||||
|
regs::PhyConfig::new_with_raw_value(#phy_config_0),
|
||||||
|
regs::PhyConfig::new_with_raw_value(#phy_config_1),
|
||||||
|
regs::PhyConfig::new_with_raw_value(#phy_config_2),
|
||||||
|
regs::PhyConfig::new_with_raw_value(#phy_config_3),
|
||||||
|
],
|
||||||
|
phy_init_ratio: [
|
||||||
|
regs::PhyInitRatio::new_with_raw_value(#phy_init_ratio_0),
|
||||||
|
regs::PhyInitRatio::new_with_raw_value(#phy_init_ratio_1),
|
||||||
|
regs::PhyInitRatio::new_with_raw_value(#phy_init_ratio_2),
|
||||||
|
regs::PhyInitRatio::new_with_raw_value(#phy_init_ratio_3),
|
||||||
|
],
|
||||||
|
phy_rd_dqs_config: [
|
||||||
|
regs::PhyDqsConfig::new_with_raw_value(#phy_rd_dqs_config_0),
|
||||||
|
regs::PhyDqsConfig::new_with_raw_value(#phy_rd_dqs_config_1),
|
||||||
|
regs::PhyDqsConfig::new_with_raw_value(#phy_rd_dqs_config_2),
|
||||||
|
regs::PhyDqsConfig::new_with_raw_value(#phy_rd_dqs_config_3),
|
||||||
|
],
|
||||||
|
phy_wr_dqs_config: [
|
||||||
|
regs::PhyDqsConfig::new_with_raw_value(#phy_wr_dqs_config_0),
|
||||||
|
regs::PhyDqsConfig::new_with_raw_value(#phy_wr_dqs_config_1),
|
||||||
|
regs::PhyDqsConfig::new_with_raw_value(#phy_wr_dqs_config_2),
|
||||||
|
regs::PhyDqsConfig::new_with_raw_value(#phy_wr_dqs_config_3),
|
||||||
|
],
|
||||||
|
phy_we_cfg: [
|
||||||
|
regs::PhyWriteEnableConfig::new_with_raw_value(#phy_we_cfg_0),
|
||||||
|
regs::PhyWriteEnableConfig::new_with_raw_value(#phy_we_cfg_1),
|
||||||
|
regs::PhyWriteEnableConfig::new_with_raw_value(#phy_we_cfg_2),
|
||||||
|
regs::PhyWriteEnableConfig::new_with_raw_value(#phy_we_cfg_3),
|
||||||
|
],
|
||||||
|
phy_wr_data_slv: [
|
||||||
|
regs::PhyWriteDataSlaveConfig::new_with_raw_value(#phy_wr_data_slv_0),
|
||||||
|
regs::PhyWriteDataSlaveConfig::new_with_raw_value(#phy_wr_data_slv_1),
|
||||||
|
regs::PhyWriteDataSlaveConfig::new_with_raw_value(#phy_wr_data_slv_2),
|
||||||
|
regs::PhyWriteDataSlaveConfig::new_with_raw_value(#phy_wr_data_slv_3),
|
||||||
|
],
|
||||||
|
reg64: regs::Reg64::new_with_raw_value(#reg64),
|
||||||
|
reg65: regs::Reg65::new_with_raw_value(#reg65),
|
||||||
|
page_mask: #page_mask,
|
||||||
|
axi_priority_wr_port: [
|
||||||
|
regs::AxiPriorityWritePort::new_with_raw_value(#axi_priority_wr_port_0),
|
||||||
|
regs::AxiPriorityWritePort::new_with_raw_value(#axi_priority_wr_port_1),
|
||||||
|
regs::AxiPriorityWritePort::new_with_raw_value(#axi_priority_wr_port_2),
|
||||||
|
regs::AxiPriorityWritePort::new_with_raw_value(#axi_priority_wr_port_3),
|
||||||
|
],
|
||||||
|
axi_priority_rd_port: [
|
||||||
|
regs::AxiPriorityReadPort::new_with_raw_value(#axi_priority_rd_port_0),
|
||||||
|
regs::AxiPriorityReadPort::new_with_raw_value(#axi_priority_rd_port_1),
|
||||||
|
regs::AxiPriorityReadPort::new_with_raw_value(#axi_priority_rd_port_2),
|
||||||
|
regs::AxiPriorityReadPort::new_with_raw_value(#axi_priority_rd_port_3),
|
||||||
|
],
|
||||||
|
lpddr_ctrl_0: regs::LpddrControl0::new_with_raw_value(#lpddr_ctrl_0),
|
||||||
|
lpddr_ctrl_1: regs::LpddrControl1::new_with_raw_value(#lpddr_ctrl_1),
|
||||||
|
lpddr_ctrl_2: regs::LpddrControl2::new_with_raw_value(#lpddr_ctrl_2),
|
||||||
|
lpddr_ctrl_3: regs::LpddrControl3::new_with_raw_value(#lpddr_ctrl_3),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
std::fs::write(file_name, generated.to_string())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_ddriob_config(
|
||||||
|
reg_to_values: &RegisterToValueMap,
|
||||||
|
file_name: &str,
|
||||||
|
) -> std::io::Result<()> {
|
||||||
|
// Format as hex strings
|
||||||
|
let addr0 = reg_to_values.val_as_token("DDRIOB Addr 0", 0xF800_0B40);
|
||||||
|
let addr1 = reg_to_values.val_as_token("DDRIOB Addr 1", 0xF800_0B44);
|
||||||
|
let data0 = reg_to_values.val_as_token("DDRIOB Data 0", 0xF800_0B48);
|
||||||
|
let data1 = reg_to_values.val_as_token("DDRIOB Data 1", 0xF800_0B4C);
|
||||||
|
let diff0 = reg_to_values.val_as_token("DDRIOB Diff 0", 0xF800_0B50);
|
||||||
|
let diff1 = reg_to_values.val_as_token("DDRIOB Diff 1", 0xF800_0B54);
|
||||||
|
let clock = reg_to_values.val_as_token("DDRIOB Clock", 0xF800_0B58);
|
||||||
|
let generated = quote::quote! {
|
||||||
|
//!This file was auto-generated by the [zynq7000-ps7init-extract](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/tools/zynq7000-ps7init-extract) program.
|
||||||
|
//!
|
||||||
|
//!This configuration file contains static DDRIOB configuration parameters extracted from the
|
||||||
|
//!AMD ps7init.tcl file
|
||||||
|
use zynq7000::ddrc::regs;
|
||||||
|
use zynq7000_hal::ddr::DdriobConfigSet;
|
||||||
|
|
||||||
|
pub const DDRIOB_CONFIG_SET_ZEDBOARD: DdriobConfigSet = DdriobConfigSet {
|
||||||
|
addr0: regs::DdriobConfig::new_with_raw_value(#addr0),
|
||||||
|
addr1: regs::DdriobConfig::new_with_raw_value(#addr1),
|
||||||
|
data0: regs::DdriobConfig::new_with_raw_value(#data0),
|
||||||
|
data1: regs::DdriobConfig::new_with_raw_value(#data1),
|
||||||
|
diff0: regs::DdriobConfig::new_with_raw_value(#diff0),
|
||||||
|
diff1: regs::DdriobConfig::new_with_raw_value(#diff1),
|
||||||
|
clock: regs::DdriobConfig::new_with_raw_value(#clock),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
std::fs::write(file_name, generated.to_string())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#![no_std]
|
|
||||||
|
|
||||||
pub mod phy_marvell;
|
|
||||||
pub mod qspi_spansion;
|
|
||||||
@@ -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
|
You can perform all the steps specified in the Vivado GUI as well using `Execute TCL script` and
|
||||||
`Load Project`.
|
`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.
|
||||||
|
|||||||
@@ -1,503 +0,0 @@
|
|||||||
use arbitrary_int::{u2, u3, u4, u5, u6, u7, u9, u10, u11, u12, u20};
|
|
||||||
use zynq7000::{
|
|
||||||
ddrc::regs::{
|
|
||||||
AxiPriorityReadPort, AxiPriorityWritePort, CheEccControl, CheTZq, CheTZqShortInterval,
|
|
||||||
CtrlReg1, CtrlReg2, CtrlReg3, CtrlReg4, CtrlReg5, CtrlReg6, DataBusWidth, DdrcControl,
|
|
||||||
DeepPowerdown, DfiTiming, DisableDq, DllCalib, DllCalibSel, DramAddrMapBank,
|
|
||||||
DramAddrMapColumn, DramAddrMapRow, DramBurst8ReadWrite, DramEmr, DramEmrMr, DramInitParam,
|
|
||||||
DramOdt, DramParamReg0, DramParamReg1, DramParamReg2, DramParamReg3, DramParamReg4,
|
|
||||||
EccMode, EccScrub, LpddrBit, LpddrControl0, LpddrControl1, LpddrControl2, LpddrControl3,
|
|
||||||
LprHprQueueControl, MobileSetting, ModeRegisterType, OdtDelayHold, PhyCmdTimeoutRdDataCpt,
|
|
||||||
PhyConfig, PhyDqsConfig, PhyInitRatio, PhyReceiverEnable, PhyWriteDataSlaveConfig,
|
|
||||||
PhyWriteEnableConfig, Reg2c, Reg2d, Reg64, Reg65, SoftReset, TwoRankConfig,
|
|
||||||
WriteQueueControl,
|
|
||||||
},
|
|
||||||
slcr::ddriob::{DciType, DdriobConfig, InputType, OutputEnable},
|
|
||||||
};
|
|
||||||
use zynq7000_hal::ddr::{DdrcConfigSet, DdriobConfigSet};
|
|
||||||
|
|
||||||
const DDRIOB_ADDR_CFG: DdriobConfig = DdriobConfig::builder()
|
|
||||||
.with_pullup_enable(false)
|
|
||||||
.with_output_enable(OutputEnable::OBuf)
|
|
||||||
.with_term_disable_mode(false)
|
|
||||||
.with_ibuf_disable_mode(false)
|
|
||||||
.with_dci_type(DciType::Disabled)
|
|
||||||
.with_termination_enable(false)
|
|
||||||
.with_dci_update_enable(false)
|
|
||||||
.with_inp_type(InputType::Off)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
const DDRIOB_DATA_CFG: DdriobConfig = DdriobConfig::builder()
|
|
||||||
.with_pullup_enable(false)
|
|
||||||
.with_output_enable(OutputEnable::OBuf)
|
|
||||||
.with_term_disable_mode(false)
|
|
||||||
.with_ibuf_disable_mode(false)
|
|
||||||
.with_dci_type(DciType::DciTermination)
|
|
||||||
.with_termination_enable(true)
|
|
||||||
.with_dci_update_enable(false)
|
|
||||||
.with_inp_type(InputType::VRefBasedDifferentialReceiverForSstlHstl)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
const DDRIOB_DIFF_CFG: DdriobConfig = DdriobConfig::builder()
|
|
||||||
.with_pullup_enable(false)
|
|
||||||
.with_output_enable(OutputEnable::OBuf)
|
|
||||||
.with_term_disable_mode(false)
|
|
||||||
.with_ibuf_disable_mode(false)
|
|
||||||
.with_dci_type(DciType::DciTermination)
|
|
||||||
.with_termination_enable(true)
|
|
||||||
.with_dci_update_enable(false)
|
|
||||||
.with_inp_type(InputType::DifferentialInputReceiver)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
const DDRIOB_CLOCK_CFG: DdriobConfig = DdriobConfig::builder()
|
|
||||||
.with_pullup_enable(false)
|
|
||||||
.with_output_enable(OutputEnable::OBuf)
|
|
||||||
.with_term_disable_mode(false)
|
|
||||||
.with_ibuf_disable_mode(false)
|
|
||||||
.with_dci_type(DciType::Disabled)
|
|
||||||
.with_termination_enable(false)
|
|
||||||
.with_dci_update_enable(false)
|
|
||||||
.with_inp_type(InputType::Off)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// TODO: Auto-generate from ps7init.tcl
|
|
||||||
pub const DDRIOB_CONFIG_SET_ZEDBOARD: DdriobConfigSet = DdriobConfigSet {
|
|
||||||
addr0: DDRIOB_ADDR_CFG,
|
|
||||||
addr1: DDRIOB_ADDR_CFG,
|
|
||||||
data0: DDRIOB_DATA_CFG,
|
|
||||||
data1: DDRIOB_DATA_CFG,
|
|
||||||
diff0: DDRIOB_DIFF_CFG,
|
|
||||||
diff1: DDRIOB_DIFF_CFG,
|
|
||||||
clock: DDRIOB_CLOCK_CFG,
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: Auto-generate from ps7init.tcl
|
|
||||||
pub const DDRC_CONFIG_ZEDBOARD_FULL_BUILDERS: DdrcConfigSet = DdrcConfigSet {
|
|
||||||
ctrl: DdrcControl::builder()
|
|
||||||
.with_disable_auto_refresh(false)
|
|
||||||
.with_disable_active_bypass(false)
|
|
||||||
.with_disable_read_bypass(false)
|
|
||||||
.with_read_write_idle_gap(u7::new(1))
|
|
||||||
.with_burst8_refresh(u3::new(0))
|
|
||||||
.with_data_bus_width(DataBusWidth::_32Bit)
|
|
||||||
.with_power_down_enable(false)
|
|
||||||
.with_soft_reset(SoftReset::Reset)
|
|
||||||
.build(),
|
|
||||||
two_rank: TwoRankConfig::builder()
|
|
||||||
.with_addrmap_cs_bit0(u5::new(0))
|
|
||||||
.with_ddrc_active_ranks(u2::new(1))
|
|
||||||
.with_rfc_nom_x32(u12::new(0x82))
|
|
||||||
.build(),
|
|
||||||
hpr: LprHprQueueControl::builder()
|
|
||||||
.with_xact_run_length(u4::new(0xf))
|
|
||||||
.with_max_starve_x32(u11::new(0xf))
|
|
||||||
.with_min_non_critical_x32(u11::new(0xf))
|
|
||||||
.build(),
|
|
||||||
lpr: LprHprQueueControl::builder()
|
|
||||||
.with_xact_run_length(u4::new(0x8))
|
|
||||||
.with_max_starve_x32(u11::new(0x2))
|
|
||||||
.with_min_non_critical_x32(u11::new(0x1))
|
|
||||||
.build(),
|
|
||||||
wr: WriteQueueControl::builder()
|
|
||||||
.with_max_starve_x32(u11::new(0x2))
|
|
||||||
.with_xact_run_length(u4::new(0x8))
|
|
||||||
.with_min_non_critical_x32(u11::new(0x1))
|
|
||||||
.build(),
|
|
||||||
dram_param_0: DramParamReg0::builder()
|
|
||||||
.with_post_selfref_gap_x32(u7::new(0x10))
|
|
||||||
.with_t_rfc_min(0x56)
|
|
||||||
.with_t_rc(u6::new(0x1b))
|
|
||||||
.build(),
|
|
||||||
dram_param_1: DramParamReg1::builder()
|
|
||||||
.with_t_cke(u4::new(0x4))
|
|
||||||
.with_t_ras_min(u5::new(0x13))
|
|
||||||
.with_t_ras_max(u6::new(0x24))
|
|
||||||
.with_t_faw(u6::new(0x16))
|
|
||||||
.with_powerdown_to_x32(u5::new(0x6))
|
|
||||||
.with_wr2pre(u5::new(0x13))
|
|
||||||
.build(),
|
|
||||||
dram_param_2: DramParamReg2::builder()
|
|
||||||
.with_t_rcd(u4::new(0x7))
|
|
||||||
.with_rd2pre(u5::new(0x5))
|
|
||||||
.with_pad_pd(u3::new(0x0))
|
|
||||||
.with_t_xp(u5::new(0x5))
|
|
||||||
.with_wr2rd(u5::new(0xf))
|
|
||||||
.with_rd2wr(u5::new(0x7))
|
|
||||||
.with_write_latency(u5::new(0x5))
|
|
||||||
.build(),
|
|
||||||
dram_param_3: DramParamReg3::builder()
|
|
||||||
.with_disable_pad_pd_feature(false)
|
|
||||||
.with_read_latency(u5::new(0x7))
|
|
||||||
.with_enable_dfi_dram_clk_disable(false)
|
|
||||||
.with_mobile(MobileSetting::Ddr2Ddr3)
|
|
||||||
.with_sdram(false)
|
|
||||||
.with_refresh_to_x32(u5::new(0x8))
|
|
||||||
.with_t_rp(u4::new(0x7))
|
|
||||||
.with_refresh_margin(u4::new(0x2))
|
|
||||||
.with_t_rrd(u3::new(0x6))
|
|
||||||
.with_t_ccd(u3::new(0x4))
|
|
||||||
.build(),
|
|
||||||
dram_param_4: DramParamReg4::builder()
|
|
||||||
.with_mr_rdata_valid(false)
|
|
||||||
.with_mr_type(ModeRegisterType::Write)
|
|
||||||
.with_mr_wr_busy(false)
|
|
||||||
.with_mr_data(0x0)
|
|
||||||
.with_mr_addr(u2::new(0x0))
|
|
||||||
.with_mr_wr(false)
|
|
||||||
.with_prefer_write(false)
|
|
||||||
.with_enable_2t_timing_mode(false)
|
|
||||||
.build(),
|
|
||||||
dram_init_param: DramInitParam::builder()
|
|
||||||
.with_t_mrd(u3::new(0x4))
|
|
||||||
.with_pre_ocd_x32(u4::new(0x0))
|
|
||||||
.with_final_wait_x32(u7::new(0x7))
|
|
||||||
.build(),
|
|
||||||
dram_emr: DramEmr::builder().with_emr3(0x0).with_emr2(0x8).build(),
|
|
||||||
dram_emr_mr: DramEmrMr::builder().with_emr(0x4).with_mr(0xb30).build(),
|
|
||||||
dram_burst8_rdwr: DramBurst8ReadWrite::builder()
|
|
||||||
.with_burst_rdwr(u4::new(0x4))
|
|
||||||
.with_pre_cke_x1024(u10::new(0x16d))
|
|
||||||
.with_post_cke_x1024(u10::new(0x1))
|
|
||||||
.with_burstchop(false)
|
|
||||||
.build(),
|
|
||||||
disable_dq: DisableDq::builder()
|
|
||||||
.with_dis_dq(false)
|
|
||||||
.with_force_low_pri_n(false)
|
|
||||||
.build(),
|
|
||||||
dram_addr_map_bank: DramAddrMapBank::builder()
|
|
||||||
.with_addrmap_bank_b6(u4::new(0))
|
|
||||||
.with_addrmap_bank_b5(u4::new(0))
|
|
||||||
.with_addrmap_bank_b2(u4::new(0x7))
|
|
||||||
.with_addrmap_bank_b1(u4::new(0x7))
|
|
||||||
.with_addrmap_bank_b0(u4::new(0x7))
|
|
||||||
.build(),
|
|
||||||
dram_addr_map_col: DramAddrMapColumn::builder()
|
|
||||||
.with_addrmap_col_b11(u4::new(0xf))
|
|
||||||
.with_addrmap_col_b10(u4::new(0xf))
|
|
||||||
.with_addrmap_col_b9(u4::new(0xf))
|
|
||||||
.with_addrmap_col_b8(u4::new(0x0))
|
|
||||||
.with_addrmap_col_b7(u4::new(0x0))
|
|
||||||
.with_addrmap_col_b4(u4::new(0x0))
|
|
||||||
.with_addrmap_col_b3(u4::new(0x0))
|
|
||||||
.with_addrmap_col_b2(u4::new(0x0))
|
|
||||||
.build(),
|
|
||||||
dram_addr_map_row: DramAddrMapRow::builder()
|
|
||||||
.with_addrmap_row_b15(u4::new(0xf))
|
|
||||||
.with_addrmap_row_b14(u4::new(0xf))
|
|
||||||
.with_addrmap_row_b13(u4::new(0x6))
|
|
||||||
.with_addrmap_row_b12(u4::new(0x6))
|
|
||||||
.with_addrmap_row_b2_11(u4::new(0x6))
|
|
||||||
.with_addrmap_row_b1(u4::new(0x6))
|
|
||||||
.with_addrmap_row_b0(u4::new(0x4))
|
|
||||||
.build(),
|
|
||||||
dram_odt: DramOdt::builder()
|
|
||||||
.with_phy_idle_local_odt(u2::new(0x0))
|
|
||||||
.with_phy_write_local_odt(u2::new(0x3))
|
|
||||||
.with_phy_read_local_odt(u2::new(0x0))
|
|
||||||
.with_rank0_wr_odt(u3::new(0x1))
|
|
||||||
.with_rank0_rd_odt(u3::new(0x0))
|
|
||||||
.build(),
|
|
||||||
phy_cmd_timeout_rddata_cpt: PhyCmdTimeoutRdDataCpt::builder()
|
|
||||||
.with_wrlvl_num_of_dq0(u4::new(0x7))
|
|
||||||
.with_gatelvl_num_of_dq0(u4::new(0x7))
|
|
||||||
.with_clk_stall_level(false)
|
|
||||||
.with_dis_phy_ctrl_rstn(false)
|
|
||||||
.with_rdc_fifo_rst_err_cnt_clr(false)
|
|
||||||
.with_use_fixed_re(true)
|
|
||||||
.with_rdc_we_to_re_delay(u4::new(0x8))
|
|
||||||
.with_wr_cmd_to_data(u4::new(0x0))
|
|
||||||
.with_rd_cmd_to_data(u4::new(0x0))
|
|
||||||
.build(),
|
|
||||||
dll_calib: DllCalib::builder().with_sel(DllCalibSel::Periodic).build(),
|
|
||||||
odt_delay_hold: OdtDelayHold::builder()
|
|
||||||
.with_wr_odt_hold(u4::new(0x5))
|
|
||||||
.with_rd_odt_hold(u4::new(0x0))
|
|
||||||
.with_wr_odt_delay(u4::new(0x0))
|
|
||||||
.with_rd_odt_delay(u4::new(0x3))
|
|
||||||
.build(),
|
|
||||||
ctrl_reg1: CtrlReg1::builder()
|
|
||||||
.with_selfref_enable(false)
|
|
||||||
.with_dis_collision_page_opt(false)
|
|
||||||
.with_dis_wc(false)
|
|
||||||
.with_refresh_update_level(false)
|
|
||||||
.with_auto_pre_en(false)
|
|
||||||
.with_lpr_num_entries(u6::new(0x1f))
|
|
||||||
.with_pageclose(false)
|
|
||||||
.build(),
|
|
||||||
ctrl_reg2: CtrlReg2::builder()
|
|
||||||
.with_go_2_critcal_enable(true)
|
|
||||||
.with_go_2_critical_hysteresis(0x0)
|
|
||||||
.build(),
|
|
||||||
ctrl_reg3: CtrlReg3::builder()
|
|
||||||
.with_dfi_t_wlmrd(u10::new(0x28))
|
|
||||||
.with_rdlvl_rr(0x41)
|
|
||||||
.with_wrlvl_ww(0x41)
|
|
||||||
.build(),
|
|
||||||
ctrl_reg4: CtrlReg4::builder()
|
|
||||||
.with_dfi_t_ctrlupd_interval_max_x1024(0x16)
|
|
||||||
.with_dfi_t_ctrlupd_interval_min_x1024(0x10)
|
|
||||||
.build(),
|
|
||||||
ctrl_reg5: CtrlReg5::builder()
|
|
||||||
.with_t_ckesr(u6::new(0x4))
|
|
||||||
.with_t_cksrx(u4::new(0x6))
|
|
||||||
.with_t_ckrse(u4::new(0x6))
|
|
||||||
.with_dfi_t_dram_clk_enable(u4::new(0x1))
|
|
||||||
.with_dfi_t_dram_clk_disable(u4::new(0x1))
|
|
||||||
.with_dfi_t_ctrl_delay(u4::new(0x1))
|
|
||||||
.build(),
|
|
||||||
ctrl_reg6: CtrlReg6::builder()
|
|
||||||
.with_t_cksx(u4::new(0x3))
|
|
||||||
.with_t_ckdpdx(u4::new(0x2))
|
|
||||||
.with_t_ckdpde(u4::new(0x2))
|
|
||||||
.with_t_ckpdx(u4::new(0x2))
|
|
||||||
.with_t_ckpde(u4::new(0x2))
|
|
||||||
.build(),
|
|
||||||
che_t_zq: CheTZq::builder()
|
|
||||||
.with_t_zq_short_nop(u10::new(0x40))
|
|
||||||
.with_t_zq_long_nop(u10::new(0x200))
|
|
||||||
.with_t_mode(u10::new(0x200))
|
|
||||||
.with_ddr3(true)
|
|
||||||
.with_dis_auto_zq(false)
|
|
||||||
.build(),
|
|
||||||
che_t_zq_short_interval_reg: CheTZqShortInterval::builder()
|
|
||||||
.with_dram_rstn_x1024(0x69)
|
|
||||||
.with_t_zq_short_interval(u20::new(0xcb73))
|
|
||||||
.build(),
|
|
||||||
deep_powerdown: DeepPowerdown::builder()
|
|
||||||
.with_deep_powerdown_to_x1024(0xff)
|
|
||||||
.with_enable(false)
|
|
||||||
.build(),
|
|
||||||
reg_2c: Reg2c::builder()
|
|
||||||
.with_dfi_rd_data_eye_train(true)
|
|
||||||
.with_dfi_rd_dqs_gate_level(true)
|
|
||||||
.with_dfi_wr_level_enable(true)
|
|
||||||
.with_trdlvl_max_error(false)
|
|
||||||
.with_twrlvl_max_error(false)
|
|
||||||
.with_dfi_rdlvl_max_x1024(u12::new(0xfff))
|
|
||||||
.with_dfi_wrlvl_max_x1024(u12::new(0xfff))
|
|
||||||
.build(),
|
|
||||||
reg_2d: Reg2d::builder().with_skip_ocd(true).build(),
|
|
||||||
dfi_timing: DfiTiming::builder()
|
|
||||||
.with_dfi_t_ctrlup_max(u10::new(0x40))
|
|
||||||
.with_dfi_t_ctrlup_min(u10::new(0x3))
|
|
||||||
.with_dfi_t_rddata_enable(u5::new(0x6))
|
|
||||||
.build(),
|
|
||||||
che_ecc_ctrl: CheEccControl::builder()
|
|
||||||
.with_clear_correctable_errors(false)
|
|
||||||
.with_clear_uncorrectable_errors(false)
|
|
||||||
.build(),
|
|
||||||
ecc_scrub: EccScrub::builder()
|
|
||||||
.with_disable_scrub(true)
|
|
||||||
.with_ecc_mode(EccMode::NoEcc)
|
|
||||||
.build(),
|
|
||||||
phy_receiver_enable: PhyReceiverEnable::builder()
|
|
||||||
.with_phy_dif_off(u4::new(0))
|
|
||||||
.with_phy_dif_on(u4::new(0))
|
|
||||||
.build(),
|
|
||||||
phy_config: [PhyConfig::builder()
|
|
||||||
.with_dq_offset(u7::new(0x40))
|
|
||||||
.with_wrlvl_inc_mode(false)
|
|
||||||
.with_gatelvl_inc_mode(false)
|
|
||||||
.with_rdlvl_inc_mode(false)
|
|
||||||
.with_data_slice_in_use(true)
|
|
||||||
.build(); 4],
|
|
||||||
phy_init_ratio: [
|
|
||||||
PhyInitRatio::builder()
|
|
||||||
.with_gatelvl_init_ratio(u10::new(0xcf))
|
|
||||||
.with_wrlvl_init_ratio(u10::new(0x3))
|
|
||||||
.build(),
|
|
||||||
PhyInitRatio::builder()
|
|
||||||
.with_gatelvl_init_ratio(u10::new(0xd0))
|
|
||||||
.with_wrlvl_init_ratio(u10::new(0x3))
|
|
||||||
.build(),
|
|
||||||
PhyInitRatio::builder()
|
|
||||||
.with_gatelvl_init_ratio(u10::new(0xbd))
|
|
||||||
.with_wrlvl_init_ratio(u10::new(0x0))
|
|
||||||
.build(),
|
|
||||||
PhyInitRatio::builder()
|
|
||||||
.with_gatelvl_init_ratio(u10::new(0xc1))
|
|
||||||
.with_wrlvl_init_ratio(u10::new(0x0))
|
|
||||||
.build(),
|
|
||||||
],
|
|
||||||
phy_rd_dqs_config: [
|
|
||||||
PhyDqsConfig::builder()
|
|
||||||
.with_dqs_slave_delay(u9::new(0x0))
|
|
||||||
.with_dqs_slave_force(false)
|
|
||||||
.with_dqs_slave_ratio(u10::new(0x35))
|
|
||||||
.build(),
|
|
||||||
PhyDqsConfig::builder()
|
|
||||||
.with_dqs_slave_delay(u9::new(0x0))
|
|
||||||
.with_dqs_slave_force(false)
|
|
||||||
.with_dqs_slave_ratio(u10::new(0x35))
|
|
||||||
.build(),
|
|
||||||
PhyDqsConfig::builder()
|
|
||||||
.with_dqs_slave_delay(u9::new(0x0))
|
|
||||||
.with_dqs_slave_force(false)
|
|
||||||
.with_dqs_slave_ratio(u10::new(0x35))
|
|
||||||
.build(),
|
|
||||||
PhyDqsConfig::builder()
|
|
||||||
.with_dqs_slave_delay(u9::new(0x0))
|
|
||||||
.with_dqs_slave_force(false)
|
|
||||||
.with_dqs_slave_ratio(u10::new(0x35))
|
|
||||||
.build(),
|
|
||||||
],
|
|
||||||
phy_wr_dqs_config: [
|
|
||||||
PhyDqsConfig::builder()
|
|
||||||
.with_dqs_slave_delay(u9::new(0x0))
|
|
||||||
.with_dqs_slave_force(false)
|
|
||||||
.with_dqs_slave_ratio(u10::new(0x83))
|
|
||||||
.build(),
|
|
||||||
PhyDqsConfig::builder()
|
|
||||||
.with_dqs_slave_delay(u9::new(0x0))
|
|
||||||
.with_dqs_slave_force(false)
|
|
||||||
.with_dqs_slave_ratio(u10::new(0x83))
|
|
||||||
.build(),
|
|
||||||
PhyDqsConfig::builder()
|
|
||||||
.with_dqs_slave_delay(u9::new(0x0))
|
|
||||||
.with_dqs_slave_force(false)
|
|
||||||
.with_dqs_slave_ratio(u10::new(0x7f))
|
|
||||||
.build(),
|
|
||||||
PhyDqsConfig::builder()
|
|
||||||
.with_dqs_slave_delay(u9::new(0x0))
|
|
||||||
.with_dqs_slave_force(false)
|
|
||||||
.with_dqs_slave_ratio(u10::new(0x78))
|
|
||||||
.build(),
|
|
||||||
],
|
|
||||||
phy_we_cfg: [
|
|
||||||
PhyWriteEnableConfig::builder()
|
|
||||||
.with_fifo_we_in_delay(u9::new(0x0))
|
|
||||||
.with_fifo_we_in_force(false)
|
|
||||||
.with_fifo_we_slave_ratio(u11::new(0x124))
|
|
||||||
.build(),
|
|
||||||
PhyWriteEnableConfig::builder()
|
|
||||||
.with_fifo_we_in_delay(u9::new(0x0))
|
|
||||||
.with_fifo_we_in_force(false)
|
|
||||||
.with_fifo_we_slave_ratio(u11::new(0x125))
|
|
||||||
.build(),
|
|
||||||
PhyWriteEnableConfig::builder()
|
|
||||||
.with_fifo_we_in_delay(u9::new(0x0))
|
|
||||||
.with_fifo_we_in_force(false)
|
|
||||||
.with_fifo_we_slave_ratio(u11::new(0x112))
|
|
||||||
.build(),
|
|
||||||
PhyWriteEnableConfig::builder()
|
|
||||||
.with_fifo_we_in_delay(u9::new(0x0))
|
|
||||||
.with_fifo_we_in_force(false)
|
|
||||||
.with_fifo_we_slave_ratio(u11::new(0x116))
|
|
||||||
.build(),
|
|
||||||
],
|
|
||||||
phy_wr_data_slv: [
|
|
||||||
PhyWriteDataSlaveConfig::builder()
|
|
||||||
.with_wr_data_slave_delay(u9::new(0x0))
|
|
||||||
.with_wr_data_slave_force(false)
|
|
||||||
.with_wr_data_slave_ratio(u10::new(0xc3))
|
|
||||||
.build(),
|
|
||||||
PhyWriteDataSlaveConfig::builder()
|
|
||||||
.with_wr_data_slave_delay(u9::new(0x0))
|
|
||||||
.with_wr_data_slave_force(false)
|
|
||||||
.with_wr_data_slave_ratio(u10::new(0xc3))
|
|
||||||
.build(),
|
|
||||||
PhyWriteDataSlaveConfig::builder()
|
|
||||||
.with_wr_data_slave_delay(u9::new(0x0))
|
|
||||||
.with_wr_data_slave_force(false)
|
|
||||||
.with_wr_data_slave_ratio(u10::new(0xbf))
|
|
||||||
.build(),
|
|
||||||
PhyWriteDataSlaveConfig::builder()
|
|
||||||
.with_wr_data_slave_delay(u9::new(0x0))
|
|
||||||
.with_wr_data_slave_force(false)
|
|
||||||
.with_wr_data_slave_ratio(u10::new(0xb8))
|
|
||||||
.build(),
|
|
||||||
],
|
|
||||||
reg64: Reg64::builder()
|
|
||||||
.with_cmd_latency(false)
|
|
||||||
.with_lpddr(false)
|
|
||||||
.with_ctrl_slave_delay(u7::new(0x0))
|
|
||||||
.with_ctrl_slave_force(false)
|
|
||||||
.with_ctrl_slave_ratio(u10::new(0x100))
|
|
||||||
.with_sel_logic(false)
|
|
||||||
.with_invert_clkout(true)
|
|
||||||
.with_bl2(false)
|
|
||||||
.build(),
|
|
||||||
reg65: Reg65::builder()
|
|
||||||
.with_ctrl_slave_delay(u2::new(0x0))
|
|
||||||
.with_dis_calib_rst(false)
|
|
||||||
.with_use_rd_data_eye_level(true)
|
|
||||||
.with_use_rd_dqs_gate_level(true)
|
|
||||||
.with_use_wr_level(true)
|
|
||||||
.with_dll_lock_diff(u4::new(0xf))
|
|
||||||
.with_rd_rl_delay(u5::new(0x4))
|
|
||||||
.with_wr_rl_delay(u5::new(0x2))
|
|
||||||
.build(),
|
|
||||||
page_mask: 0x0,
|
|
||||||
axi_priority_wr_port: [
|
|
||||||
AxiPriorityWritePort::builder()
|
|
||||||
.with_disable_page_match(false)
|
|
||||||
.with_disable_urgent(false)
|
|
||||||
.with_disable_aging(false)
|
|
||||||
.with_pri_wr_port(u10::new(0x3ff))
|
|
||||||
.build(),
|
|
||||||
AxiPriorityWritePort::builder()
|
|
||||||
.with_disable_page_match(false)
|
|
||||||
.with_disable_urgent(false)
|
|
||||||
.with_disable_aging(false)
|
|
||||||
.with_pri_wr_port(u10::new(0x3ff))
|
|
||||||
.build(),
|
|
||||||
AxiPriorityWritePort::builder()
|
|
||||||
.with_disable_page_match(false)
|
|
||||||
.with_disable_urgent(false)
|
|
||||||
.with_disable_aging(false)
|
|
||||||
.with_pri_wr_port(u10::new(0x3ff))
|
|
||||||
.build(),
|
|
||||||
AxiPriorityWritePort::builder()
|
|
||||||
.with_disable_page_match(false)
|
|
||||||
.with_disable_urgent(false)
|
|
||||||
.with_disable_aging(false)
|
|
||||||
.with_pri_wr_port(u10::new(0x3ff))
|
|
||||||
.build(),
|
|
||||||
],
|
|
||||||
axi_priority_rd_port: [
|
|
||||||
AxiPriorityReadPort::builder()
|
|
||||||
.with_enable_hpr(false)
|
|
||||||
.with_disable_page_match(false)
|
|
||||||
.with_disable_urgent(false)
|
|
||||||
.with_disable_aging(false)
|
|
||||||
.with_pri_rd_port_n(u10::new(0x3ff))
|
|
||||||
.build(),
|
|
||||||
AxiPriorityReadPort::builder()
|
|
||||||
.with_enable_hpr(false)
|
|
||||||
.with_disable_page_match(false)
|
|
||||||
.with_disable_urgent(false)
|
|
||||||
.with_disable_aging(false)
|
|
||||||
.with_pri_rd_port_n(u10::new(0x3ff))
|
|
||||||
.build(),
|
|
||||||
AxiPriorityReadPort::builder()
|
|
||||||
.with_enable_hpr(false)
|
|
||||||
.with_disable_page_match(false)
|
|
||||||
.with_disable_urgent(false)
|
|
||||||
.with_disable_aging(false)
|
|
||||||
.with_pri_rd_port_n(u10::new(0x3ff))
|
|
||||||
.build(),
|
|
||||||
AxiPriorityReadPort::builder()
|
|
||||||
.with_enable_hpr(false)
|
|
||||||
.with_disable_page_match(false)
|
|
||||||
.with_disable_urgent(false)
|
|
||||||
.with_disable_aging(false)
|
|
||||||
.with_pri_rd_port_n(u10::new(0x3ff))
|
|
||||||
.build(),
|
|
||||||
],
|
|
||||||
lpddr_ctrl_0: LpddrControl0::builder()
|
|
||||||
.with_mr4_margin(0x0)
|
|
||||||
.with_derate_enable(false)
|
|
||||||
.with_per_bank_refresh(false)
|
|
||||||
.with_lpddr2(LpddrBit::Ddr2Ddr3)
|
|
||||||
.build(),
|
|
||||||
lpddr_ctrl_1: LpddrControl1::builder().with_mr4_read_interval(0x0).build(),
|
|
||||||
lpddr_ctrl_2: LpddrControl2::builder()
|
|
||||||
.with_t_mrw(u10::new(0x5))
|
|
||||||
.with_idle_after_reset_x32(0x12)
|
|
||||||
.with_min_stable_clock_x1(u4::new(0x5))
|
|
||||||
.build(),
|
|
||||||
lpddr_ctrl_3: LpddrControl3::builder()
|
|
||||||
.with_dev_zqinit_x32(u10::new(0x12))
|
|
||||||
.with_max_auto_init_x1024(0xa8)
|
|
||||||
.build(),
|
|
||||||
};
|
|
||||||
@@ -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 = []
|
|
||||||
20
zynq/.cargo/config.toml
Normal file
20
zynq/.cargo/config.toml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
[target.armv7a-none-eabihf]
|
||||||
|
runner = "just run"
|
||||||
|
|
||||||
|
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"
|
||||||
1
zynq/.gitignore
vendored
Normal file
1
zynq/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Cargo.lock
|
||||||
21
zynq/Cargo.toml
Normal file
21
zynq/Cargo.toml
Normal file
@@ -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",
|
||||||
|
]
|
||||||
@@ -11,7 +11,7 @@ keywords = ["no-std", "arm", "cortex-a", "amd", "zynq7000"]
|
|||||||
categories = ["embedded", "no-std", "hardware-support"]
|
categories = ["embedded", "no-std", "hardware-support"]
|
||||||
|
|
||||||
[dependencies]
|
[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-rt = { path = "../../zynq7000-rt" }
|
||||||
zynq7000 = { path = "../../zynq7000" }
|
zynq7000 = { path = "../../zynq7000" }
|
||||||
zynq7000-hal = { path = "../../zynq7000-hal" }
|
zynq7000-hal = { path = "../../zynq7000-hal" }
|
||||||
@@ -20,19 +20,35 @@ dht-sensor = { git = "https://github.com/michaelbeaumont/dht-sensor.git", rev =
|
|||||||
static_cell = "2"
|
static_cell = "2"
|
||||||
critical-section = "1"
|
critical-section = "1"
|
||||||
heapless = "0.9"
|
heapless = "0.9"
|
||||||
embedded-io = "0.6"
|
embedded-io = "0.7"
|
||||||
embedded-hal = "1"
|
embedded-hal = "1"
|
||||||
fugit = "0.3"
|
fugit = "0.3"
|
||||||
log = "0.4"
|
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",
|
"arch-cortex-ar",
|
||||||
"executor-thread",
|
"executor-thread",
|
||||||
]}
|
]}
|
||||||
# TODO: Remove generic-queue-16 feature as soon as upstream executor is used again.
|
# 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"] }
|
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
|
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
|
||||||
@@ -79,7 +79,7 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
info!("Boot mode: {:?}", boot_mode);
|
info!("Boot mode: {:?}", boot_mode);
|
||||||
|
|
||||||
let led = Output::new_for_mio(mio_pins.mio7, PinState::Low);
|
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 mut log_buf: [u8; 2048] = [0; 2048];
|
||||||
let frame_queue = zynq7000_hal::log::rb::get_frame_queue();
|
let frame_queue = zynq7000_hal::log::rb::get_frame_queue();
|
||||||
loop {
|
loop {
|
||||||
@@ -8,7 +8,7 @@ use embassy_time::{Duration, Ticker};
|
|||||||
use embedded_hal::digital::StatefulOutputPin;
|
use embedded_hal::digital::StatefulOutputPin;
|
||||||
use embedded_io::Write;
|
use embedded_io::Write;
|
||||||
use log::{error, info};
|
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 _;
|
use zynq7000_rt as _;
|
||||||
|
|
||||||
@@ -9,11 +9,11 @@ repository = "https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs"
|
|||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
[dependencies]
|
[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-rt = { path = "../../zynq7000-rt" }
|
||||||
zynq7000 = { path = "../../zynq7000" }
|
zynq7000 = { path = "../../zynq7000" }
|
||||||
zynq7000-hal = { path = "../../zynq7000-hal" }
|
zynq7000-hal = { path = "../../zynq7000-hal" }
|
||||||
embedded-io = "0.6"
|
embedded-io = "0.7"
|
||||||
embedded-hal = "1"
|
embedded-hal = "1"
|
||||||
fugit = "0.3"
|
fugit = "0.3"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
@@ -11,7 +11,7 @@ keywords = ["no-std", "arm", "cortex-a", "amd", "zynq7000"]
|
|||||||
categories = ["embedded", "no-std", "hardware-support"]
|
categories = ["embedded", "no-std", "hardware-support"]
|
||||||
|
|
||||||
[dependencies]
|
[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-rt = { path = "../../zynq7000-rt" }
|
||||||
zynq7000 = { path = "../../zynq7000" }
|
zynq7000 = { path = "../../zynq7000" }
|
||||||
zynq7000-hal = { path = "../../zynq7000-hal" }
|
zynq7000-hal = { path = "../../zynq7000-hal" }
|
||||||
@@ -19,7 +19,7 @@ zynq7000-embassy = { path = "../../zynq7000-embassy" }
|
|||||||
zedboard-bsp = { path = "../../zedboard-bsp" }
|
zedboard-bsp = { path = "../../zedboard-bsp" }
|
||||||
num_enum = { version = "0.7", default-features = false }
|
num_enum = { version = "0.7", default-features = false }
|
||||||
l3gd20 = { git = "https://github.com/us-irs/l3gd20.git", branch = "add-async-if" }
|
l3gd20 = { git = "https://github.com/us-irs/l3gd20.git", branch = "add-async-if" }
|
||||||
embedded-io = "0.6"
|
embedded-io = "0.7"
|
||||||
bitbybit = "1.4"
|
bitbybit = "1.4"
|
||||||
arbitrary-int = "2"
|
arbitrary-int = "2"
|
||||||
embedded-io-async = "0.6"
|
embedded-io-async = "0.6"
|
||||||
@@ -10,7 +10,7 @@ use embedded_io::Write;
|
|||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use zedboard::PS_CLOCK_FREQUENCY;
|
use zedboard::PS_CLOCK_FREQUENCY;
|
||||||
use zedboard_bsp::qspi_spansion;
|
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 _;
|
use zynq7000_rt as _;
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ use embedded_hal::digital::StatefulOutputPin;
|
|||||||
use embedded_io::Write;
|
use embedded_io::Write;
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use zedboard::PS_CLOCK_FREQUENCY;
|
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 _;
|
use zynq7000_rt as _;
|
||||||
|
|
||||||
@@ -1,3 +1,2 @@
|
|||||||
[toolchain]
|
[toolchain]
|
||||||
# channel = "stable"
|
|
||||||
channel = "nightly"
|
channel = "nightly"
|
||||||
@@ -4,6 +4,7 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
zynq7000 = { path = "../zynq7000" }
|
||||||
zynq7000-hal = { path = "../zynq7000-hal" }
|
zynq7000-hal = { path = "../zynq7000-hal" }
|
||||||
bitbybit = "1.4"
|
bitbybit = "1.4"
|
||||||
arbitrary-int = "2"
|
arbitrary-int = "2"
|
||||||
101
zynq/zedboard-bsp/src/ddrc_config_autogen.rs
Normal file
101
zynq/zedboard-bsp/src/ddrc_config_autogen.rs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
# program."]
|
||||||
|
#![doc = r""]
|
||||||
|
#![doc = r"This configuration file contains static DDR configuration parameters extracted from the"]
|
||||||
|
#![doc = r"AMD ps7init.tcl file"]
|
||||||
|
use zynq7000::ddrc::regs;
|
||||||
|
use zynq7000_hal::ddr::DdrcConfigSet;
|
||||||
|
pub const DDRC_CONFIG_ZEDBOARD: DdrcConfigSet = DdrcConfigSet {
|
||||||
|
ctrl: regs::DdrcControl::new_with_raw_value(0x00000080),
|
||||||
|
two_rank: regs::TwoRankConfig::new_with_raw_value(0x00001082),
|
||||||
|
hpr: regs::LprHprQueueControl::new_with_raw_value(0x03c0780f),
|
||||||
|
lpr: regs::LprHprQueueControl::new_with_raw_value(0x02001001),
|
||||||
|
wr: regs::WriteQueueControl::new_with_raw_value(0x00014001),
|
||||||
|
dram_param_0: regs::DramParamReg0::new_with_raw_value(0x0004159b),
|
||||||
|
dram_param_1: regs::DramParamReg1::new_with_raw_value(0x44e458d3),
|
||||||
|
dram_param_2: regs::DramParamReg2::new_with_raw_value(0x7282bce5),
|
||||||
|
dram_param_3: regs::DramParamReg3::new_with_raw_value(0x270872d0),
|
||||||
|
dram_param_4: regs::DramParamReg4::new_with_raw_value(0x00000000),
|
||||||
|
dram_init_param: regs::DramInitParam::new_with_raw_value(0x00002007),
|
||||||
|
dram_emr: regs::DramEmr::new_with_raw_value(0x00000008),
|
||||||
|
dram_emr_mr: regs::DramEmrMr::new_with_raw_value(0x00040b30),
|
||||||
|
dram_burst8_rdwr: regs::DramBurst8ReadWrite::new_with_raw_value(0x000116d4),
|
||||||
|
disable_dq: regs::DisableDq::new_with_raw_value(0x00000000),
|
||||||
|
dram_addr_map_bank: regs::DramAddrMapBank::new_with_raw_value(0x00000777),
|
||||||
|
dram_addr_map_col: regs::DramAddrMapColumn::new_with_raw_value(0xfff00000),
|
||||||
|
dram_addr_map_row: regs::DramAddrMapRow::new_with_raw_value(0x0ff66666),
|
||||||
|
dram_odt: regs::DramOdt::new_with_raw_value(0x0003c008),
|
||||||
|
phy_cmd_timeout_rddata_cpt: regs::PhyCmdTimeoutRdDataCpt::new_with_raw_value(0x77010800),
|
||||||
|
dll_calib: regs::DllCalib::new_with_raw_value(0x00000000),
|
||||||
|
odt_delay_hold: regs::OdtDelayHold::new_with_raw_value(0x00005003),
|
||||||
|
ctrl_reg1: regs::CtrlReg1::new_with_raw_value(0x0000003e),
|
||||||
|
ctrl_reg2: regs::CtrlReg2::new_with_raw_value(0x00020000),
|
||||||
|
ctrl_reg3: regs::CtrlReg3::new_with_raw_value(0x00284141),
|
||||||
|
ctrl_reg4: regs::CtrlReg4::new_with_raw_value(0x00001610),
|
||||||
|
ctrl_reg5: regs::CtrlReg5::new_with_raw_value(0x00466111),
|
||||||
|
ctrl_reg6: regs::CtrlReg6::new_with_raw_value(0x00032222),
|
||||||
|
che_t_zq: regs::CheTZq::new_with_raw_value(0x10200802),
|
||||||
|
che_t_zq_short_interval_reg: regs::CheTZqShortInterval::new_with_raw_value(0x10200802),
|
||||||
|
deep_powerdown: regs::DeepPowerdown::new_with_raw_value(0x000001fe),
|
||||||
|
reg_2c: regs::Reg2c::new_with_raw_value(0x1cffffff),
|
||||||
|
reg_2d: regs::Reg2d::new_with_raw_value(0x00000200),
|
||||||
|
dfi_timing: regs::DfiTiming::new_with_raw_value(0x00200066),
|
||||||
|
che_ecc_ctrl: regs::CheEccControl::new_with_raw_value(0x00000000),
|
||||||
|
ecc_scrub: regs::EccScrub::new_with_raw_value(0x00000008),
|
||||||
|
phy_receiver_enable: regs::PhyReceiverEnable::new_with_raw_value(0x00000000),
|
||||||
|
phy_config: [
|
||||||
|
regs::PhyConfig::new_with_raw_value(0x40000001),
|
||||||
|
regs::PhyConfig::new_with_raw_value(0x40000001),
|
||||||
|
regs::PhyConfig::new_with_raw_value(0x40000001),
|
||||||
|
regs::PhyConfig::new_with_raw_value(0x40000001),
|
||||||
|
],
|
||||||
|
phy_init_ratio: [
|
||||||
|
regs::PhyInitRatio::new_with_raw_value(0x00033c03),
|
||||||
|
regs::PhyInitRatio::new_with_raw_value(0x00034003),
|
||||||
|
regs::PhyInitRatio::new_with_raw_value(0x0002f400),
|
||||||
|
regs::PhyInitRatio::new_with_raw_value(0x00030400),
|
||||||
|
],
|
||||||
|
phy_rd_dqs_config: [
|
||||||
|
regs::PhyDqsConfig::new_with_raw_value(0x00000035),
|
||||||
|
regs::PhyDqsConfig::new_with_raw_value(0x00000035),
|
||||||
|
regs::PhyDqsConfig::new_with_raw_value(0x00000035),
|
||||||
|
regs::PhyDqsConfig::new_with_raw_value(0x00000035),
|
||||||
|
],
|
||||||
|
phy_wr_dqs_config: [
|
||||||
|
regs::PhyDqsConfig::new_with_raw_value(0x00000083),
|
||||||
|
regs::PhyDqsConfig::new_with_raw_value(0x00000083),
|
||||||
|
regs::PhyDqsConfig::new_with_raw_value(0x0000007f),
|
||||||
|
regs::PhyDqsConfig::new_with_raw_value(0x00000078),
|
||||||
|
],
|
||||||
|
phy_we_cfg: [
|
||||||
|
regs::PhyWriteEnableConfig::new_with_raw_value(0x00000124),
|
||||||
|
regs::PhyWriteEnableConfig::new_with_raw_value(0x00000125),
|
||||||
|
regs::PhyWriteEnableConfig::new_with_raw_value(0x00000112),
|
||||||
|
regs::PhyWriteEnableConfig::new_with_raw_value(0x00000116),
|
||||||
|
],
|
||||||
|
phy_wr_data_slv: [
|
||||||
|
regs::PhyWriteDataSlaveConfig::new_with_raw_value(0x000000c3),
|
||||||
|
regs::PhyWriteDataSlaveConfig::new_with_raw_value(0x000000c3),
|
||||||
|
regs::PhyWriteDataSlaveConfig::new_with_raw_value(0x000000bf),
|
||||||
|
regs::PhyWriteDataSlaveConfig::new_with_raw_value(0x000000b8),
|
||||||
|
],
|
||||||
|
reg64: regs::Reg64::new_with_raw_value(0x00040080),
|
||||||
|
reg65: regs::Reg65::new_with_raw_value(0x0001fc82),
|
||||||
|
page_mask: 0x00000000,
|
||||||
|
axi_priority_wr_port: [
|
||||||
|
regs::AxiPriorityWritePort::new_with_raw_value(0x000003ff),
|
||||||
|
regs::AxiPriorityWritePort::new_with_raw_value(0x000003ff),
|
||||||
|
regs::AxiPriorityWritePort::new_with_raw_value(0x000003ff),
|
||||||
|
regs::AxiPriorityWritePort::new_with_raw_value(0x000003ff),
|
||||||
|
],
|
||||||
|
axi_priority_rd_port: [
|
||||||
|
regs::AxiPriorityReadPort::new_with_raw_value(0x000003ff),
|
||||||
|
regs::AxiPriorityReadPort::new_with_raw_value(0x000003ff),
|
||||||
|
regs::AxiPriorityReadPort::new_with_raw_value(0x000003ff),
|
||||||
|
regs::AxiPriorityReadPort::new_with_raw_value(0x000003ff),
|
||||||
|
],
|
||||||
|
lpddr_ctrl_0: regs::LpddrControl0::new_with_raw_value(0x00000000),
|
||||||
|
lpddr_ctrl_1: regs::LpddrControl1::new_with_raw_value(0x00000000),
|
||||||
|
lpddr_ctrl_2: regs::LpddrControl2::new_with_raw_value(0x00005125),
|
||||||
|
lpddr_ctrl_3: regs::LpddrControl3::new_with_raw_value(0x000012a8),
|
||||||
|
};
|
||||||
|
|
||||||
16
zynq/zedboard-bsp/src/ddriob_config_autogen.rs
Normal file
16
zynq/zedboard-bsp/src/ddriob_config_autogen.rs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# program."]
|
||||||
|
#![doc = r""]
|
||||||
|
#![doc = r"This configuration file contains static DDRIOB configuration parameters extracted from the"]
|
||||||
|
#![doc = r"AMD ps7init.tcl file"]
|
||||||
|
use zynq7000::ddrc::regs;
|
||||||
|
use zynq7000_hal::ddr::DdriobConfigSet;
|
||||||
|
pub const DDRIOB_CONFIG_SET_ZEDBOARD: DdriobConfigSet = DdriobConfigSet {
|
||||||
|
addr0: regs::DdriobConfig::new_with_raw_value(0x00000600),
|
||||||
|
addr1: regs::DdriobConfig::new_with_raw_value(0x00000600),
|
||||||
|
data0: regs::DdriobConfig::new_with_raw_value(0x00000672),
|
||||||
|
data1: regs::DdriobConfig::new_with_raw_value(0x00000672),
|
||||||
|
diff0: regs::DdriobConfig::new_with_raw_value(0x00000674),
|
||||||
|
diff1: regs::DdriobConfig::new_with_raw_value(0x00000674),
|
||||||
|
clock: regs::DdriobConfig::new_with_raw_value(0x00000600),
|
||||||
|
};
|
||||||
|
|
||||||
6
zynq/zedboard-bsp/src/lib.rs
Normal file
6
zynq/zedboard-bsp/src/lib.rs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#![no_std]
|
||||||
|
|
||||||
|
pub mod ddrc_config_autogen;
|
||||||
|
pub mod ddriob_config_autogen;
|
||||||
|
pub mod phy_marvell;
|
||||||
|
pub mod qspi_spansion;
|
||||||
@@ -64,6 +64,8 @@ pub enum SectorArchictecture {
|
|||||||
Hybrid = 0x01,
|
Hybrid = 0x01,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const PAGE_SIZE: usize = 256;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct BaseDeviceId {
|
pub struct BaseDeviceId {
|
||||||
manufacturer_id: u8,
|
manufacturer_id: u8,
|
||||||
@@ -221,6 +223,8 @@ pub enum ProgramPageError {
|
|||||||
ProgrammingErrorBitSet,
|
ProgrammingErrorBitSet,
|
||||||
#[error("address error: {0}")]
|
#[error("address error: {0}")]
|
||||||
Addr(#[from] AddrError),
|
Addr(#[from] AddrError),
|
||||||
|
#[error("data is larger than page size {PAGE_SIZE}")]
|
||||||
|
DataLargerThanPage,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct QspiSpansionS25Fl256SIoMode(RefCell<QspiIoMode>);
|
pub struct QspiSpansionS25Fl256SIoMode(RefCell<QspiIoMode>);
|
||||||
@@ -428,14 +432,17 @@ impl QspiSpansionS25Fl256SIoMode {
|
|||||||
/// This function also takes care of enabling writes before programming the page.
|
/// This function also takes care of enabling writes before programming the page.
|
||||||
/// This function will block until the operation has completed.
|
/// This function will block until the operation has completed.
|
||||||
///
|
///
|
||||||
/// TODO: Allow smaller write size
|
/// The data length max not exceed the page size [PAGE_SIZE].
|
||||||
pub fn program_page(&mut self, addr: u32, data: &[u8; 256]) -> Result<(), ProgramPageError> {
|
pub fn program_page(&mut self, addr: u32, data: &[u8]) -> Result<(), ProgramPageError> {
|
||||||
if addr + data.len() as u32 > u24::MAX.as_u32() {
|
if addr + data.len() as u32 > u24::MAX.as_u32() {
|
||||||
return Err(AddrError::OutOfRange.into());
|
return Err(AddrError::OutOfRange.into());
|
||||||
}
|
}
|
||||||
if !addr.is_multiple_of(0x100) {
|
if !addr.is_multiple_of(0x100) {
|
||||||
return Err(AddrError::Alignment.into());
|
return Err(AddrError::Alignment.into());
|
||||||
}
|
}
|
||||||
|
if data.len() > PAGE_SIZE {
|
||||||
|
return Err(ProgramPageError::DataLargerThanPage);
|
||||||
|
}
|
||||||
self.write_enable();
|
self.write_enable();
|
||||||
let qspi = self.0.get_mut();
|
let qspi = self.0.get_mut();
|
||||||
let mut transfer = qspi.transfer_guard();
|
let mut transfer = qspi.transfer_guard();
|
||||||
@@ -448,8 +455,9 @@ impl QspiSpansionS25Fl256SIoMode {
|
|||||||
transfer.write_word_txd_00(u32::from_ne_bytes(raw_word));
|
transfer.write_word_txd_00(u32::from_ne_bytes(raw_word));
|
||||||
let mut read_index: u32 = 0;
|
let mut read_index: u32 = 0;
|
||||||
let mut current_byte_index = 0;
|
let mut current_byte_index = 0;
|
||||||
|
let fifo_writes = data.len().div_ceil(4);
|
||||||
// Fill the FIFO until it is full.
|
// 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(
|
transfer.write_word_txd_00(u32::from_ne_bytes(
|
||||||
data[current_byte_index..current_byte_index + 4]
|
data[current_byte_index..current_byte_index + 4]
|
||||||
.try_into()
|
.try_into()
|
||||||
@@ -470,25 +478,38 @@ impl QspiSpansionS25Fl256SIoMode {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
while current_byte_index < data.len() {
|
||||||
// Immediately fill the FIFO again with the remaining 8 bytes.
|
// Immediately fill the FIFO again with the remaining 8 bytes.
|
||||||
wait_for_tx_slot(&mut transfer);
|
wait_for_tx_slot(&mut transfer);
|
||||||
|
|
||||||
transfer.write_word_txd_00(u32::from_ne_bytes(
|
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]
|
data[current_byte_index..current_byte_index + 4]
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
));
|
),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
transfer.write_word_txd_00(word);
|
||||||
current_byte_index += 4;
|
current_byte_index += 4;
|
||||||
|
}
|
||||||
|
|
||||||
wait_for_tx_slot(&mut transfer);
|
while read_index < data.len() as u32 {
|
||||||
|
|
||||||
transfer.write_word_txd_00(u32::from_ne_bytes(
|
|
||||||
data[current_byte_index..current_byte_index + 4]
|
|
||||||
.try_into()
|
|
||||||
.unwrap(),
|
|
||||||
));
|
|
||||||
|
|
||||||
while read_index < 256 {
|
|
||||||
if transfer.read_status().rx_above_threshold() {
|
if transfer.read_status().rx_above_threshold() {
|
||||||
transfer.read_rx_data();
|
transfer.read_rx_data();
|
||||||
read_index = read_index.wrapping_add(4);
|
read_index = read_index.wrapping_add(4);
|
||||||
@@ -528,11 +549,7 @@ impl QspiSpansionS25Fl256SIoMode {
|
|||||||
if dummy_byte {
|
if dummy_byte {
|
||||||
bytes_to_write += 1;
|
bytes_to_write += 1;
|
||||||
}
|
}
|
||||||
let fifo_writes = if bytes_to_write.is_multiple_of(4) {
|
let fifo_writes = bytes_to_write.div_ceil(4);
|
||||||
bytes_to_write / 4
|
|
||||||
} else {
|
|
||||||
(bytes_to_write / 4) + 1
|
|
||||||
};
|
|
||||||
// Fill the FIFO until it is full or all 0 bytes have been written.
|
// 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) {
|
for _ in 0..core::cmp::min(fifo_writes, FIFO_DEPTH - 1) {
|
||||||
transfer.write_word_txd_00(0);
|
transfer.write_word_txd_00(0);
|
||||||
@@ -9,13 +9,13 @@ repository = "https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs"
|
|||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
[dependencies]
|
[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-rt = { path = "../zynq7000-rt" }
|
||||||
zynq7000 = { path = "../zynq7000" }
|
zynq7000 = { path = "../zynq7000" }
|
||||||
zynq7000-hal = { path = "../zynq7000-hal" }
|
zynq7000-hal = { path = "../zynq7000-hal" }
|
||||||
|
zynq7000-boot-image = { path = "../../zynq7000-boot-image" }
|
||||||
zedboard-bsp = { path = "../zedboard-bsp" }
|
zedboard-bsp = { path = "../zedboard-bsp" }
|
||||||
zynq-boot-image = { path = "../zynq-boot-image" }
|
embedded-io = "0.7"
|
||||||
embedded-io = "0.6"
|
|
||||||
embedded-hal = "1"
|
embedded-hal = "1"
|
||||||
fugit = "0.3"
|
fugit = "0.3"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
@@ -8,7 +8,8 @@ use cortex_ar::asm::nop;
|
|||||||
use embedded_io::Write as _;
|
use embedded_io::Write as _;
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use zedboard_bsp::qspi_spansion::{self, QspiSpansionS25Fl256SLinearMode};
|
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::{
|
use zynq7000_hal::{
|
||||||
BootMode,
|
BootMode,
|
||||||
clocks::{
|
clocks::{
|
||||||
@@ -16,18 +17,14 @@ use zynq7000_hal::{
|
|||||||
pll::{PllConfig, configure_arm_pll, configure_io_pll},
|
pll::{PllConfig, configure_arm_pll, configure_io_pll},
|
||||||
},
|
},
|
||||||
ddr::{DdrClockSetupConfig, configure_ddr_for_ddr3, memtest},
|
ddr::{DdrClockSetupConfig, configure_ddr_for_ddr3, memtest},
|
||||||
gic, gpio, l2_cache,
|
devcfg, gic, gpio, l2_cache,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
qspi,
|
qspi::{self, QSPI_START_ADDRESS},
|
||||||
time::Hertz,
|
time::Hertz,
|
||||||
uart::{ClockConfig, Config, Uart},
|
uart::{ClockConfig, Config, Uart},
|
||||||
};
|
};
|
||||||
use zynq7000_rt as _;
|
use zynq7000_rt as _;
|
||||||
|
|
||||||
use crate::ddr_cfg::{DDRC_CONFIG_ZEDBOARD_FULL_BUILDERS, DDRIOB_CONFIG_SET_ZEDBOARD};
|
|
||||||
|
|
||||||
pub mod ddr_cfg;
|
|
||||||
|
|
||||||
// PS clock input frequency.
|
// PS clock input frequency.
|
||||||
const PS_CLK: Hertz = Hertz::from_raw(33_333_333);
|
const PS_CLK: Hertz = Hertz::from_raw(33_333_333);
|
||||||
|
|
||||||
@@ -80,35 +77,37 @@ pub fn main() -> ! {
|
|||||||
PllConfig::new_from_target_clock(PS_CLK, IO_CLK).unwrap(),
|
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.
|
// 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 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;
|
let mio_pins = gpio_pins.mio;
|
||||||
// Set up the UART, we are logging with it.
|
// Set up the UART, we are logging with it.
|
||||||
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
let mut uart = Uart::new_with_mio(
|
let mut logger_uart = Uart::new_with_mio(
|
||||||
dp.uart_1,
|
periphs.uart_1,
|
||||||
Config::new_with_clk_config(uart_clk_config),
|
Config::new_with_clk_config(uart_clk_config),
|
||||||
(mio_pins.mio48, mio_pins.mio49),
|
(mio_pins.mio48, mio_pins.mio49),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.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.
|
// Safety: We are not multi-threaded yet.
|
||||||
unsafe {
|
unsafe {
|
||||||
zynq7000_hal::log::uart_blocking::init_unsafe_single_core(
|
zynq7000_hal::log::uart_blocking::init_unsafe_single_core(
|
||||||
uart,
|
logger_uart,
|
||||||
log::LevelFilter::Trace,
|
log::LevelFilter::Trace,
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set up the global interrupt controller.
|
// 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.enable_all_interrupts();
|
||||||
gic.set_all_spi_interrupt_targets_cpu0();
|
gic.set_all_spi_interrupt_targets_cpu0();
|
||||||
gic.enable();
|
gic.enable();
|
||||||
@@ -117,7 +116,7 @@ pub fn main() -> ! {
|
|||||||
|
|
||||||
info!("Configuring DDR..");
|
info!("Configuring DDR..");
|
||||||
configure_ddr_for_ddr3(
|
configure_ddr_for_ddr3(
|
||||||
dp.ddrc,
|
periphs.ddrc,
|
||||||
boot_mode,
|
boot_mode,
|
||||||
DdrClockSetupConfig {
|
DdrClockSetupConfig {
|
||||||
ps_clk: PS_CLK,
|
ps_clk: PS_CLK,
|
||||||
@@ -125,16 +124,18 @@ pub fn main() -> ! {
|
|||||||
ddr_3x_div: u6::new(2),
|
ddr_3x_div: u6::new(2),
|
||||||
ddr_2x_div: u6::new(3),
|
ddr_2x_div: u6::new(3),
|
||||||
},
|
},
|
||||||
&DDRIOB_CONFIG_SET_ZEDBOARD,
|
&zedboard_bsp::ddriob_config_autogen::DDRIOB_CONFIG_SET_ZEDBOARD,
|
||||||
&DDRC_CONFIG_ZEDBOARD_FULL_BUILDERS,
|
&zedboard_bsp::ddrc_config_autogen::DDRC_CONFIG_ZEDBOARD,
|
||||||
);
|
);
|
||||||
info!("DDR init done.");
|
info!("DDR init done.");
|
||||||
|
|
||||||
info!("L2 cache init..");
|
info!("L2 cache init..");
|
||||||
// Set up the L2 cache now that the DDR is in normal operation mode.
|
// 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.");
|
info!("L2 cache init done.");
|
||||||
|
|
||||||
|
let priv_tim = priv_tim::CpuPrivateTimer::take(clocks.arm_clocks()).unwrap();
|
||||||
|
|
||||||
if PERFORM_DDR_MEMTEST {
|
if PERFORM_DDR_MEMTEST {
|
||||||
let ddr_base_addr = 0x100000;
|
let ddr_base_addr = 0x100000;
|
||||||
info!("performing DDR memory test..");
|
info!("performing DDR memory test..");
|
||||||
@@ -154,7 +155,7 @@ pub fn main() -> ! {
|
|||||||
)
|
)
|
||||||
.expect("QSPI clock calculation failed");
|
.expect("QSPI clock calculation failed");
|
||||||
let qspi = qspi::Qspi::new_single_qspi_with_feedback(
|
let qspi = qspi::Qspi::new_single_qspi_with_feedback(
|
||||||
dp.qspi,
|
periphs.qspi,
|
||||||
qspi_clock_config,
|
qspi_clock_config,
|
||||||
embedded_hal::spi::MODE_0,
|
embedded_hal::spi::MODE_0,
|
||||||
qspi::IoType::LvCmos33,
|
qspi::IoType::LvCmos33,
|
||||||
@@ -168,19 +169,19 @@ pub fn main() -> ! {
|
|||||||
let spansion_qspi = qspi_spansion::QspiSpansionS25Fl256SIoMode::new(qspi_io_mode, true);
|
let spansion_qspi = qspi_spansion::QspiSpansionS25Fl256SIoMode::new(qspi_io_mode, true);
|
||||||
let spansion_lqspi =
|
let spansion_lqspi =
|
||||||
spansion_qspi.into_linear_addressed(qspi_spansion::QSPI_DEV_COMBINATION_REV_F.into());
|
spansion_qspi.into_linear_addressed(qspi_spansion::QSPI_DEV_COMBINATION_REV_F.into());
|
||||||
qspi_boot(spansion_lqspi);
|
qspi_boot(spansion_lqspi, priv_tim);
|
||||||
}
|
}
|
||||||
loop {
|
loop {
|
||||||
cortex_ar::asm::nop();
|
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 boot_bin_base_addr = ELF_BASE_ADDR + BOOT_BIN_STAGING_OFFSET;
|
||||||
let mut boot_header_slice = unsafe {
|
let mut boot_header_slice = unsafe {
|
||||||
core::slice::from_raw_parts_mut(
|
core::slice::from_raw_parts_mut(
|
||||||
boot_bin_base_addr as *mut u8,
|
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();
|
let read_guard = qspi.read_guard();
|
||||||
@@ -189,12 +190,12 @@ fn qspi_boot(mut qspi: QspiSpansionS25Fl256SLinearMode) -> ! {
|
|||||||
core::ptr::copy_nonoverlapping(
|
core::ptr::copy_nonoverlapping(
|
||||||
QspiSpansionS25Fl256SLinearMode::BASE_ADDR as *mut u8,
|
QspiSpansionS25Fl256SLinearMode::BASE_ADDR as *mut u8,
|
||||||
boot_header_slice.as_mut_ptr(),
|
boot_header_slice.as_mut_ptr(),
|
||||||
zynq_boot_image::FIXED_BOOT_HEADER_SIZE,
|
zynq7000_boot_image::FIXED_BOOT_HEADER_SIZE,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
drop(read_guard);
|
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();
|
let fsbl_offset = boot_header.source_offset();
|
||||||
boot_header_slice =
|
boot_header_slice =
|
||||||
unsafe { core::slice::from_raw_parts_mut(boot_bin_base_addr as *mut u8, fsbl_offset) };
|
unsafe { core::slice::from_raw_parts_mut(boot_bin_base_addr as *mut u8, fsbl_offset) };
|
||||||
@@ -203,33 +204,101 @@ fn qspi_boot(mut qspi: QspiSpansionS25Fl256SLinearMode) -> ! {
|
|||||||
let read_guard = qspi.read_guard();
|
let read_guard = qspi.read_guard();
|
||||||
unsafe {
|
unsafe {
|
||||||
core::ptr::copy_nonoverlapping(
|
core::ptr::copy_nonoverlapping(
|
||||||
(QspiSpansionS25Fl256SLinearMode::BASE_ADDR + zynq_boot_image::FIXED_BOOT_HEADER_SIZE)
|
(QspiSpansionS25Fl256SLinearMode::BASE_ADDR
|
||||||
as *mut u8,
|
+ zynq7000_boot_image::FIXED_BOOT_HEADER_SIZE) as *mut u8,
|
||||||
boot_header_slice[zynq_boot_image::FIXED_BOOT_HEADER_SIZE..].as_mut_ptr(),
|
boot_header_slice[zynq7000_boot_image::FIXED_BOOT_HEADER_SIZE..].as_mut_ptr(),
|
||||||
fsbl_offset - zynq_boot_image::FIXED_BOOT_HEADER_SIZE,
|
fsbl_offset - zynq7000_boot_image::FIXED_BOOT_HEADER_SIZE,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
drop(read_guard);
|
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];
|
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();
|
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)
|
.partition_header_iterator(boot_header_slice)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
.enumerate()
|
||||||
{
|
{
|
||||||
let section_attrs = partition.section_attributes();
|
let section_attrs = partition.section_attributes();
|
||||||
if let Ok(dest_dev) = section_attrs.destination_device() {
|
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 {
|
match dest_dev {
|
||||||
DestinationDevice::Pl => {
|
DestinationDevice::Pl => {
|
||||||
info!("Loading image '{name}' to PL (FPGA)..");
|
info!("Loading image '{name}' to PL (FPGA)..");
|
||||||
// TODO: Load the bitstream.
|
// 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 => {
|
DestinationDevice::Ps => {
|
||||||
// TODO: Load the binary into DDR. Jump at lowest load address after all
|
// Load the bitstream directly from linear mapped QSPI memory.
|
||||||
// partitions were parsed.
|
let load_addr = partition.destination_load_address();
|
||||||
|
if load_addr < 0x10_0000 {
|
||||||
|
panic!("invalid load address which is not located in DDR memory");
|
||||||
|
}
|
||||||
|
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:?}");
|
error!("Unsupported destination device {dest_dev:?}");
|
||||||
@@ -238,10 +307,23 @@ fn qspi_boot(mut qspi: QspiSpansionS25Fl256SLinearMode) -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
loop {
|
match opt_jump_addr {
|
||||||
cortex_ar::asm::nop();
|
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!"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4,11 +4,13 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[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-rt = { path = "../zynq7000-rt" }
|
||||||
zynq7000 = { path = "../zynq7000" }
|
zynq7000 = { path = "../zynq7000" }
|
||||||
zynq7000-hal = { path = "../zynq7000-hal" }
|
zynq7000-hal = { path = "../zynq7000-hal" }
|
||||||
|
zynq7000-boot-image = { path = "../../zynq7000-boot-image" }
|
||||||
zedboard-bsp = { path = "../zedboard-bsp" }
|
zedboard-bsp = { path = "../zedboard-bsp" }
|
||||||
embedded-io = "0.6"
|
embedded-io = "0.7"
|
||||||
embedded-hal = "1"
|
embedded-hal = "1"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
libm = "0.2"
|
||||||
31
zynq/zedboard-qspi-flasher/build.rs
Normal file
31
zynq/zedboard-qspi-flasher/build.rs
Normal file
@@ -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");
|
||||||
|
}
|
||||||
22
zynq/zedboard-qspi-flasher/memory.x
Normal file
22
zynq/zedboard-qspi-flasher/memory.x
Normal file
@@ -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
|
||||||
|
}
|
||||||
151
zynq/zedboard-qspi-flasher/qspi-flasher.tcl
Normal file
151
zynq/zedboard-qspi-flasher/qspi-flasher.tcl
Normal file
@@ -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 <init.tcl> \[-b|--bin <boot.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 <init.tcl>
|
||||||
|
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"
|
||||||
@@ -7,10 +7,11 @@ use core::panic::PanicInfo;
|
|||||||
use cortex_ar::asm::nop;
|
use cortex_ar::asm::nop;
|
||||||
use embedded_hal::{delay::DelayNs as _, digital::StatefulOutputPin as _};
|
use embedded_hal::{delay::DelayNs as _, digital::StatefulOutputPin as _};
|
||||||
use embedded_io::Write as _;
|
use embedded_io::Write as _;
|
||||||
use log::info;
|
use log::{error, info};
|
||||||
use zedboard_bsp::qspi_spansion;
|
use zedboard_bsp::qspi_spansion;
|
||||||
|
use zynq7000_boot_image::BootHeader;
|
||||||
use zynq7000_hal::{
|
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 _;
|
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.
|
// 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);
|
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)]
|
#[allow(dead_code)]
|
||||||
const QSPI_DEV_COMBINATION: qspi::QspiDeviceCombination = qspi::QspiDeviceCombination {
|
const QSPI_DEV_COMBINATION: qspi::QspiDeviceCombination = qspi::QspiDeviceCombination {
|
||||||
vendor: qspi::QspiVendor::WinbondAndSpansion,
|
vendor: qspi::QspiVendor::WinbondAndSpansion,
|
||||||
@@ -67,7 +77,7 @@ pub fn main() -> ! {
|
|||||||
unsafe {
|
unsafe {
|
||||||
zynq7000_hal::log::uart_blocking::init_unsafe_single_core(
|
zynq7000_hal::log::uart_blocking::init_unsafe_single_core(
|
||||||
uart,
|
uart,
|
||||||
log::LevelFilter::Trace,
|
log::LevelFilter::Info,
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@@ -96,7 +106,83 @@ pub fn main() -> ! {
|
|||||||
|
|
||||||
let qspi_io_mode = qspi.into_io_mode(false);
|
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);
|
let mut mio_led = gpio::Output::new_for_mio(gpio_pins.mio.mio7, gpio::PinState::Low);
|
||||||
loop {
|
loop {
|
||||||
@@ -11,9 +11,9 @@ keywords = ["no-std", "hal", "amd", "zynq7000", "xilinx", "bare-metal"]
|
|||||||
categories = ["embedded", "no-std", "hardware-support"]
|
categories = ["embedded", "no-std", "hardware-support"]
|
||||||
|
|
||||||
[dependencies]
|
[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" }
|
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"
|
static_assertions = "1.1"
|
||||||
bitbybit = "1.4"
|
bitbybit = "1.4"
|
||||||
@@ -22,7 +22,7 @@ thiserror = { version = "2", default-features = false }
|
|||||||
num_enum = { version = "0.7", default-features = false }
|
num_enum = { version = "0.7", default-features = false }
|
||||||
ringbuf = { version = "0.4.8", default-features = false }
|
ringbuf = { version = "0.4.8", default-features = false }
|
||||||
embedded-hal-nb = "1"
|
embedded-hal-nb = "1"
|
||||||
embedded-io = "0.6"
|
embedded-io = "0.7"
|
||||||
embedded-hal = "1"
|
embedded-hal = "1"
|
||||||
embedded-hal-async = "1"
|
embedded-hal-async = "1"
|
||||||
heapless = "0.9"
|
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"] }
|
smoltcp = { version = "0.12", default-features = false, features = ["proto-ipv4", "medium-ethernet", "socket-raw"] }
|
||||||
vcell = "0.1"
|
vcell = "0.1"
|
||||||
raw-slicee = "0.1"
|
raw-slicee = "0.1"
|
||||||
embedded-io-async = "0.6"
|
embedded-io-async = "0.7"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
std = ["thiserror/std", "alloc"]
|
std = ["thiserror/std", "alloc"]
|
||||||
@@ -212,6 +212,7 @@ pub unsafe fn configure_iob(cfg_set: &DdriobConfigSet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Full static DDRC configuration set.
|
/// Full static DDRC configuration set.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct DdrcConfigSet {
|
pub struct DdrcConfigSet {
|
||||||
pub ctrl: DdrcControl,
|
pub ctrl: DdrcControl,
|
||||||
pub two_rank: TwoRankConfig,
|
pub two_rank: TwoRankConfig,
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user