forked from M-Labs/zynq-rs
Compare commits
20 Commits
master
...
bump_to_la
Author | SHA1 | Date |
---|---|---|
Simon Renblad | e894f502a4 | |
Simon Renblad | cd56ef6d48 | |
Simon Renblad | 0a91f883bc | |
Simon Renblad | 3e59dcbc94 | |
Simon Renblad | 4138a65270 | |
Simon Renblad | cb0ec48ef0 | |
Simon Renblad | 14dffaf49c | |
Simon Renblad | bd0c45497e | |
Simon Renblad | 6dc831a8f8 | |
Simon Renblad | aef7dcabae | |
Simon Renblad | 49a84da2ce | |
Simon Renblad | b00f297cd0 | |
Simon Renblad | 526e80401a | |
newell | cc20478d91 | |
Sebastien Bourdeauducq | 5ef3016554 | |
newell | 6a45a0dfd0 | |
Sebastien Bourdeauducq | b2b3e5c933 | |
Simon Renblad | 0efbbe39fe | |
Sebastien Bourdeauducq | 51b8111e79 | |
Simon Renblad | 46dc25b89e |
|
@ -1,7 +1,7 @@
|
||||||
[target.armv7-none-eabihf]
|
[target.armv7-none-eabihf]
|
||||||
rustflags = [
|
rustflags = [
|
||||||
"-C", "link-arg=-Tlink.x",
|
"-C", "link-arg=-Tlink.x",
|
||||||
"-C", "target-feature=a9,armv7-a,neon",
|
"-C", "target-feature=+a9,+armv7-a,+neon",
|
||||||
"-C", "target-cpu=cortex-a9",
|
"-C", "target-cpu=cortex-a9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit_field"
|
name = "bit_field"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
|
@ -12,6 +14,12 @@ version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.4.3"
|
||||||
|
@ -32,18 +40,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "compiler_builtins"
|
name = "compiler_builtins"
|
||||||
version = "0.1.39"
|
version = "0.1.109"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3748f82c7d366a0b4950257d19db685d4958d2fa27c6d164a3f069fec42b748b"
|
checksum = "f11973008a8cf741fe6d22f339eba21fd0ca81e2760a769ba8243ed6c21edd7e"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "core_io"
|
|
||||||
version = "0.1.20210325"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "97f8932064288cc79feb4d343a399d353a6f6f001e586ece47fe518a9e8507df"
|
|
||||||
dependencies = [
|
|
||||||
"rustc_version",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embedded-hal"
|
name = "embedded-hal"
|
||||||
|
@ -70,13 +69,10 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fatfs"
|
name = "fatfs"
|
||||||
version = "0.3.5"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/rafalh/rust-fatfs?rev=85f06e0#85f06e08edbd3368e1b0562f2fc1b6d178bf7b8a"
|
||||||
checksum = "e18f80a87439240dac45d927fd8f8081b6f1e34c03e97271189fa8a8c2e96c8f"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.6.0",
|
||||||
"byteorder",
|
|
||||||
"core_io",
|
|
||||||
"log",
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -111,7 +107,6 @@ dependencies = [
|
||||||
name = "libconfig"
|
name = "libconfig"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"core_io",
|
|
||||||
"fatfs",
|
"fatfs",
|
||||||
"libboard_zynq",
|
"libboard_zynq",
|
||||||
"log",
|
"log",
|
||||||
|
@ -196,28 +191,13 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
|
checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustc_version"
|
|
||||||
version = "0.1.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
|
|
||||||
dependencies = [
|
|
||||||
"semver",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "semver"
|
|
||||||
version = "0.1.20"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smoltcp"
|
name = "smoltcp"
|
||||||
version = "0.7.5"
|
version = "0.7.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3e4a069bef843d170df47e7c0a8bf8d037f217d9f5b325865acc3e466ffe40d3"
|
checksum = "3e4a069bef843d170df47e7c0a8bf8d037f217d9f5b325865acc3e466ffe40d3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"managed",
|
"managed",
|
||||||
]
|
]
|
||||||
|
@ -227,7 +207,7 @@ name = "szl"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"core_io",
|
"fatfs",
|
||||||
"libboard_zynq",
|
"libboard_zynq",
|
||||||
"libconfig",
|
"libconfig",
|
||||||
"libcortex_a9",
|
"libcortex_a9",
|
||||||
|
|
|
@ -9,6 +9,7 @@ members = [
|
||||||
"experiments",
|
"experiments",
|
||||||
"szl",
|
"szl",
|
||||||
]
|
]
|
||||||
|
resolver = "2"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
|
|
@ -3,11 +3,12 @@ name = "experiments"
|
||||||
description = "Developing bare-metal Rust on Zynq"
|
description = "Developing bare-metal Rust on Zynq"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
authors = ["M-Labs"]
|
authors = ["M-Labs"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
target_zc706 = ["libboard_zynq/target_zc706", "libsupport_zynq/target_zc706"]
|
target_zc706 = ["libboard_zynq/target_zc706", "libsupport_zynq/target_zc706"]
|
||||||
target_coraz7 = ["libboard_zynq/target_coraz7", "libsupport_zynq/target_coraz7"]
|
target_coraz7 = ["libboard_zynq/target_coraz7", "libsupport_zynq/target_coraz7"]
|
||||||
|
target_ebaz4205 = ["libboard_zynq/target_ebaz4205", "libsupport_zynq/target_ebaz4205"]
|
||||||
target_redpitaya = ["libboard_zynq/target_redpitaya", "libsupport_zynq/target_redpitaya"]
|
target_redpitaya = ["libboard_zynq/target_redpitaya", "libsupport_zynq/target_redpitaya"]
|
||||||
target_kasli_soc = ["libboard_zynq/target_kasli_soc", "libsupport_zynq/target_kasli_soc"]
|
target_kasli_soc = ["libboard_zynq/target_kasli_soc", "libsupport_zynq/target_kasli_soc"]
|
||||||
default = ["target_zc706"]
|
default = ["target_zc706"]
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(const_in_array_repeat_expressions)]
|
|
||||||
#![feature(naked_functions)]
|
#![feature(naked_functions)]
|
||||||
#![feature(asm)]
|
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
use alloc::collections::BTreeMap;
|
use alloc::collections::BTreeMap;
|
||||||
|
use core::arch::asm;
|
||||||
use libasync::{
|
use libasync::{
|
||||||
delay,
|
delay,
|
||||||
smoltcp::{Sockets, TcpStream},
|
smoltcp::{Sockets, TcpStream},
|
||||||
|
@ -116,6 +115,7 @@ pub fn main_core0() {
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
feature = "target_zc706",
|
feature = "target_zc706",
|
||||||
|
feature = "target_ebaz4205",
|
||||||
feature = "target_redpitaya",
|
feature = "target_redpitaya",
|
||||||
feature = "target_kasli_soc",
|
feature = "target_kasli_soc",
|
||||||
))]
|
))]
|
||||||
|
|
|
@ -18,16 +18,16 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1715087517,
|
"lastModified": 1729181673,
|
||||||
"narHash": "sha256-CLU5Tsg24Ke4+7sH8azHWXKd0CFd4mhLWfhYgUiDBpQ=",
|
"narHash": "sha256-LDiPhQ3l+fBjRATNtnuDZsBS7hqoBtPkKBkhpoBHv3I=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "b211b392b8486ee79df6cdfb1157ad2133427a29",
|
"rev": "4eb33fe664af7b41a4c446f87d20c9a0a6321fa3",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "nixos-unstable",
|
"ref": "nixos-24.05",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
|
23
flake.nix
23
flake.nix
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
description = "Bare-metal Rust on Zynq-7000";
|
description = "Bare-metal Rust on Zynq-7000";
|
||||||
|
|
||||||
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-unstable;
|
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-24.05;
|
||||||
inputs.mozilla-overlay = { url = github:mozilla/nixpkgs-mozilla; flake = false; };
|
inputs.mozilla-overlay = { url = github:mozilla/nixpkgs-mozilla; flake = false; };
|
||||||
|
|
||||||
outputs = { self, nixpkgs, mozilla-overlay }:
|
outputs = { self, nixpkgs, mozilla-overlay }:
|
||||||
|
@ -9,8 +9,8 @@
|
||||||
pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ (import mozilla-overlay) crosspkgs-overlay ]; };
|
pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ (import mozilla-overlay) crosspkgs-overlay ]; };
|
||||||
|
|
||||||
rustManifest = pkgs.fetchurl {
|
rustManifest = pkgs.fetchurl {
|
||||||
url = "https://static.rust-lang.org/dist/2021-01-29/channel-rust-nightly.toml";
|
url = "https://static.rust-lang.org/dist/2024-07-19/channel-rust-nightly.toml";
|
||||||
sha256 = "sha256-EZKgw89AH4vxaJpUHmIMzMW/80wAFQlfcxRoBD9nz0c=";
|
sha256 = "sha256-MM2K43Kg+f83XQXT2lI7W/ZdQjLXhMUvA6eGtD+rqDY=";
|
||||||
};
|
};
|
||||||
rustTargets = [];
|
rustTargets = [];
|
||||||
rustChannelOfTargets = _channel: _date: targets:
|
rustChannelOfTargets = _channel: _date: targets:
|
||||||
|
@ -96,9 +96,7 @@
|
||||||
dontFixup = true;
|
dontFixup = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
cargo-xbuild = pkgs.cargo-xbuild.overrideAttrs(oa: {
|
cargo-xbuild = pkgs.cargo-xbuild;
|
||||||
postPatch = "substituteInPlace src/sysroot.rs --replace 2021 2018";
|
|
||||||
});
|
|
||||||
|
|
||||||
build-crate = name: crate: features: rustPlatform.buildRustPackage rec {
|
build-crate = name: crate: features: rustPlatform.buildRustPackage rec {
|
||||||
name = "${crate}";
|
name = "${crate}";
|
||||||
|
@ -106,9 +104,14 @@
|
||||||
src = builtins.filterSource (path: type:
|
src = builtins.filterSource (path: type:
|
||||||
baseNameOf path != "target"
|
baseNameOf path != "target"
|
||||||
) ./.;
|
) ./.;
|
||||||
cargoLock = { lockFile = ./Cargo.lock; };
|
cargoLock = {
|
||||||
|
lockFile = ./Cargo.lock;
|
||||||
|
outputHashes = {
|
||||||
|
"fatfs-0.4.0" = "sha256-P7IgvhwTPXtNhcyv8cFqwO2UdaEcCGJY7UBG6+yBFSg=";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [ cargo-xbuild pkgs.llvmPackages_14.clang-unwrapped ];
|
nativeBuildInputs = [ cargo-xbuild pkgs.llvmPackages_18.clang-unwrapped ];
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
export XARGO_RUST_SRC="${rust}/lib/rustlib/src/rust/library"
|
export XARGO_RUST_SRC="${rust}/lib/rustlib/src/rust/library"
|
||||||
export CARGO_HOME=$(mktemp -d cargo-home.XXX)
|
export CARGO_HOME=$(mktemp -d cargo-home.XXX)
|
||||||
|
@ -134,7 +137,7 @@
|
||||||
"${target}-experiments" = build-crate "${target}-experiments" "experiments" "target_${target}";
|
"${target}-experiments" = build-crate "${target}-experiments" "experiments" "target_${target}";
|
||||||
"${target}-szl" = build-crate "${target}-szl" "szl" "target_${target}";
|
"${target}-szl" = build-crate "${target}-szl" "szl" "target_${target}";
|
||||||
};
|
};
|
||||||
targets = ["zc706" "coraz7" "redpitaya" "kasli_soc"];
|
targets = ["zc706" "coraz7" "redpitaya" "kasli_soc" "ebaz4205"];
|
||||||
allTargetCrates = (builtins.foldl' (results: target:
|
allTargetCrates = (builtins.foldl' (results: target:
|
||||||
results // targetCrates target
|
results // targetCrates target
|
||||||
) {} targets);
|
) {} targets);
|
||||||
|
@ -164,7 +167,7 @@
|
||||||
|
|
||||||
pkgs.openocd pkgs.gdb
|
pkgs.openocd pkgs.gdb
|
||||||
pkgs.openssh pkgs.rsync
|
pkgs.openssh pkgs.rsync
|
||||||
pkgs.llvmPackages_14.clang-unwrapped
|
pkgs.llvmPackages_18.clang-unwrapped
|
||||||
(pkgs.python3.withPackages(ps: [ ps.pyftdi ]))
|
(pkgs.python3.withPackages(ps: [ ps.pyftdi ]))
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,7 @@ name = "libasync"
|
||||||
description = "low-level async support"
|
description = "low-level async support"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
authors = ["M-Labs"]
|
authors = ["M-Labs"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
#futures = { version = "0.3", default-features = false }
|
#futures = { version = "0.3", default-features = false }
|
||||||
|
|
|
@ -3,11 +3,12 @@ name = "libboard_zynq"
|
||||||
description = "Drivers for peripherals in the Zynq PS"
|
description = "Drivers for peripherals in the Zynq PS"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
authors = ["M-Labs"]
|
authors = ["M-Labs"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
target_zc706 = []
|
target_zc706 = []
|
||||||
target_coraz7 = []
|
target_coraz7 = []
|
||||||
|
target_ebaz4205 = []
|
||||||
target_redpitaya = []
|
target_redpitaya = []
|
||||||
target_kasli_soc = []
|
target_kasli_soc = []
|
||||||
ipv6 = [ "smoltcp/proto-ipv6" ]
|
ipv6 = [ "smoltcp/proto-ipv6" ]
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use core::unimplemented;
|
||||||
|
|
||||||
use libregister::{RegisterR, RegisterRW};
|
use libregister::{RegisterR, RegisterRW};
|
||||||
use super::slcr;
|
use super::slcr;
|
||||||
pub use slcr::ArmPllSource;
|
pub use slcr::ArmPllSource;
|
||||||
|
@ -101,6 +103,8 @@ impl Clocks {
|
||||||
self.ddr,
|
self.ddr,
|
||||||
slcr::PllSource::IoPll =>
|
slcr::PllSource::IoPll =>
|
||||||
self.io,
|
self.io,
|
||||||
|
slcr::PllSource::Emio =>
|
||||||
|
unimplemented!(),
|
||||||
};
|
};
|
||||||
pll / u32::from(uart_clk_ctrl.divisor())
|
pll / u32::from(uart_clk_ctrl.divisor())
|
||||||
}
|
}
|
||||||
|
@ -115,6 +119,8 @@ impl Clocks {
|
||||||
self.ddr,
|
self.ddr,
|
||||||
slcr::PllSource::IoPll =>
|
slcr::PllSource::IoPll =>
|
||||||
self.io,
|
self.io,
|
||||||
|
slcr::PllSource::Emio =>
|
||||||
|
unimplemented!(),
|
||||||
};
|
};
|
||||||
pll / u32::from(sdio_clk_ctrl.divisor())
|
pll / u32::from(sdio_clk_ctrl.divisor())
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ use super::slcr;
|
||||||
pub const PS_CLK: u32 = 33_333_333;
|
pub const PS_CLK: u32 = 33_333_333;
|
||||||
#[cfg(feature = "target_coraz7")]
|
#[cfg(feature = "target_coraz7")]
|
||||||
pub const PS_CLK: u32 = 50_000_000;
|
pub const PS_CLK: u32 = 50_000_000;
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
pub const PS_CLK: u32 = 33_333_333;
|
||||||
#[cfg(feature = "target_redpitaya")]
|
#[cfg(feature = "target_redpitaya")]
|
||||||
pub const PS_CLK: u32 = 33_333_333;
|
pub const PS_CLK: u32 = 33_333_333;
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
|
|
@ -16,6 +16,10 @@ const DDR_FREQ: u32 = 666_666_666;
|
||||||
/// Micron MT41K256M16HA-125: 800 MHz DDR3L, max supported 533 MHz
|
/// Micron MT41K256M16HA-125: 800 MHz DDR3L, max supported 533 MHz
|
||||||
const DDR_FREQ: u32 = 525_000_000;
|
const DDR_FREQ: u32 = 525_000_000;
|
||||||
|
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
/// EtronTech Memory EM6GD16EWKG-12H: 800 MHz DDR3 at 533 MHz
|
||||||
|
const DDR_FREQ: u32 = 533_333_333;
|
||||||
|
|
||||||
#[cfg(feature = "target_redpitaya")]
|
#[cfg(feature = "target_redpitaya")]
|
||||||
/// Alliance Memory AS4C256M16D3B: 800 MHz DDR3 at 533 MHz
|
/// Alliance Memory AS4C256M16D3B: 800 MHz DDR3 at 533 MHz
|
||||||
const DDR_FREQ: u32 = 533_333_333;
|
const DDR_FREQ: u32 = 533_333_333;
|
||||||
|
@ -147,22 +151,23 @@ impl DdrRam {
|
||||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
.output_en(slcr::DdriobOutputEn::Obuf);
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(feature = "target_zc706")]
|
||||||
let data1_config = data0_config.clone();
|
let data1_config = data0_config.clone();
|
||||||
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
#[cfg(any(
|
||||||
|
feature = "target_coraz7",
|
||||||
|
feature = "target_ebaz4205",
|
||||||
|
feature = "target_redpitaya",
|
||||||
|
feature = "target_kasli_soc",
|
||||||
|
))]
|
||||||
let data0_config = slcr::DdriobConfig::zeroed()
|
let data0_config = slcr::DdriobConfig::zeroed()
|
||||||
.inp_type(slcr::DdriobInputType::VrefDifferential)
|
.inp_type(slcr::DdriobInputType::VrefDifferential)
|
||||||
.term_en(true)
|
.term_en(true)
|
||||||
.dci_type(slcr::DdriobDciType::Termination)
|
.dci_type(slcr::DdriobDciType::Termination)
|
||||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
.output_en(slcr::DdriobOutputEn::Obuf);
|
||||||
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
#[cfg(any(
|
||||||
let data1_config = slcr::DdriobConfig::zeroed()
|
feature = "target_coraz7",
|
||||||
.pullup_en(true);
|
feature = "target_ebaz4205",
|
||||||
#[cfg(feature = "target_redpitaya")]
|
feature = "target_redpitaya",
|
||||||
let data0_config = slcr::DdriobConfig::zeroed()
|
feature = "target_kasli_soc",
|
||||||
.inp_type(slcr::DdriobInputType::VrefDifferential)
|
))]
|
||||||
.term_en(true)
|
|
||||||
.dci_type(slcr::DdriobDciType::Termination)
|
|
||||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
|
||||||
#[cfg(feature = "target_redpitaya")]
|
|
||||||
let data1_config = slcr::DdriobConfig::zeroed()
|
let data1_config = slcr::DdriobConfig::zeroed()
|
||||||
.pullup_en(true);
|
.pullup_en(true);
|
||||||
slcr.ddriob_data0.write(data0_config);
|
slcr.ddriob_data0.write(data0_config);
|
||||||
|
@ -176,22 +181,23 @@ impl DdrRam {
|
||||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
.output_en(slcr::DdriobOutputEn::Obuf);
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(feature = "target_zc706")]
|
||||||
let diff1_config = diff0_config.clone();
|
let diff1_config = diff0_config.clone();
|
||||||
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
#[cfg(any(
|
||||||
|
feature = "target_coraz7",
|
||||||
|
feature = "target_ebaz4205",
|
||||||
|
feature = "target_redpitaya",
|
||||||
|
feature = "target_kasli_soc",
|
||||||
|
))]
|
||||||
let diff0_config = slcr::DdriobConfig::zeroed()
|
let diff0_config = slcr::DdriobConfig::zeroed()
|
||||||
.inp_type(slcr::DdriobInputType::Differential)
|
.inp_type(slcr::DdriobInputType::Differential)
|
||||||
.term_en(true)
|
.term_en(true)
|
||||||
.dci_type(slcr::DdriobDciType::Termination)
|
.dci_type(slcr::DdriobDciType::Termination)
|
||||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
.output_en(slcr::DdriobOutputEn::Obuf);
|
||||||
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
#[cfg(any(
|
||||||
let diff1_config = slcr::DdriobConfig::zeroed()
|
feature = "target_coraz7",
|
||||||
.pullup_en(true);
|
feature = "target_ebaz4205",
|
||||||
#[cfg(feature = "target_redpitaya")]
|
feature = "target_redpitaya",
|
||||||
let diff0_config = slcr::DdriobConfig::zeroed()
|
feature = "target_kasli_soc",
|
||||||
.inp_type(slcr::DdriobInputType::Differential)
|
))]
|
||||||
.term_en(true)
|
|
||||||
.dci_type(slcr::DdriobDciType::Termination)
|
|
||||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
|
||||||
#[cfg(feature = "target_redpitaya")]
|
|
||||||
let diff1_config = slcr::DdriobConfig::zeroed()
|
let diff1_config = slcr::DdriobConfig::zeroed()
|
||||||
.pullup_en(true);
|
.pullup_en(true);
|
||||||
slcr.ddriob_diff0.write(diff0_config);
|
slcr.ddriob_diff0.write(diff0_config);
|
||||||
|
@ -210,7 +216,12 @@ impl DdrRam {
|
||||||
slcr.ddriob_drive_slew_clock.write(0x00F9861C);
|
slcr.ddriob_drive_slew_clock.write(0x00F9861C);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
#[cfg(any(
|
||||||
|
feature = "target_coraz7",
|
||||||
|
feature = "target_ebaz4205",
|
||||||
|
feature = "target_redpitaya",
|
||||||
|
feature = "target_kasli_soc",
|
||||||
|
))]
|
||||||
slcr.ddriob_ddr_ctrl.modify(|_, w| w
|
slcr.ddriob_ddr_ctrl.modify(|_, w| w
|
||||||
.vref_int_en(false)
|
.vref_int_en(false)
|
||||||
.vref_ext_en_lower(true)
|
.vref_ext_en_lower(true)
|
||||||
|
@ -224,13 +235,6 @@ impl DdrRam {
|
||||||
.vref_ext_en_lower(false)
|
.vref_ext_en_lower(false)
|
||||||
.vref_ext_en_upper(false)
|
.vref_ext_en_upper(false)
|
||||||
);
|
);
|
||||||
#[cfg(feature = "target_redpitaya")]
|
|
||||||
slcr.ddriob_ddr_ctrl.modify(|_, w| w
|
|
||||||
.vref_int_en(false)
|
|
||||||
.vref_ext_en_lower(true)
|
|
||||||
.vref_ext_en_upper(false)
|
|
||||||
.refio_en(true)
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,6 +246,13 @@ impl DdrRam {
|
||||||
.t_rfc_min(0x9e)
|
.t_rfc_min(0x9e)
|
||||||
.post_selfref_gap_x32(0x10)
|
.post_selfref_gap_x32(0x10)
|
||||||
);
|
);
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
self.regs.dram_param0.write(
|
||||||
|
regs::DramParam0::zeroed()
|
||||||
|
.t_rc(0x1a)
|
||||||
|
.t_rfc_min(0x56)
|
||||||
|
.post_selfref_gap_x32(0x10)
|
||||||
|
);
|
||||||
#[cfg(feature = "target_redpitaya")]
|
#[cfg(feature = "target_redpitaya")]
|
||||||
self.regs.dram_param0.write(
|
self.regs.dram_param0.write(
|
||||||
regs::DramParam0::zeroed()
|
regs::DramParam0::zeroed()
|
||||||
|
@ -256,6 +267,12 @@ impl DdrRam {
|
||||||
.t_rfc_min(0x56)
|
.t_rfc_min(0x56)
|
||||||
.post_selfref_gap_x32(0x10)
|
.post_selfref_gap_x32(0x10)
|
||||||
);
|
);
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
self.regs.dram_param1.modify(
|
||||||
|
|_, w| w
|
||||||
|
.t_faw(0x16)
|
||||||
|
.t_ras_min(0x13)
|
||||||
|
);
|
||||||
#[cfg(feature = "target_redpitaya")]
|
#[cfg(feature = "target_redpitaya")]
|
||||||
self.regs.dram_param1.modify(
|
self.regs.dram_param1.modify(
|
||||||
|_, w| w
|
|_, w| w
|
||||||
|
@ -277,6 +294,11 @@ impl DdrRam {
|
||||||
.rd2pre(0x4)
|
.rd2pre(0x4)
|
||||||
.t_rcd(0x7)
|
.t_rcd(0x7)
|
||||||
);
|
);
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
self.regs.dram_param3.modify(
|
||||||
|
|_, w| w
|
||||||
|
.t_rp(7)
|
||||||
|
);
|
||||||
#[cfg(feature = "target_redpitaya")]
|
#[cfg(feature = "target_redpitaya")]
|
||||||
self.regs.dram_param3.modify(
|
self.regs.dram_param3.modify(
|
||||||
|_, w| w
|
|_, w| w
|
||||||
|
@ -298,19 +320,21 @@ impl DdrRam {
|
||||||
.emr(0x4)
|
.emr(0x4)
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
#[cfg(any(
|
||||||
|
feature = "target_coraz7",
|
||||||
|
feature = "target_ebaz4205",
|
||||||
|
feature = "target_redpitaya",
|
||||||
|
feature = "target_kasli_soc",
|
||||||
|
))]
|
||||||
self.regs.phy_configs[2].modify(
|
self.regs.phy_configs[2].modify(
|
||||||
|_, w| w.data_slice_in_use(false)
|
|_, w| w.data_slice_in_use(false)
|
||||||
);
|
);
|
||||||
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
#[cfg(any(
|
||||||
self.regs.phy_configs[3].modify(
|
feature = "target_coraz7",
|
||||||
|_, w| w.data_slice_in_use(false)
|
feature = "target_ebaz4205",
|
||||||
);
|
feature = "target_redpitaya",
|
||||||
#[cfg(feature = "target_redpitaya")]
|
feature = "target_kasli_soc",
|
||||||
self.regs.phy_configs[2].modify(
|
))]
|
||||||
|_, w| w.data_slice_in_use(false)
|
|
||||||
);
|
|
||||||
#[cfg(feature = "target_redpitaya")]
|
|
||||||
self.regs.phy_configs[3].modify(
|
self.regs.phy_configs[3].modify(
|
||||||
|_, w| w.data_slice_in_use(false)
|
|_, w| w.data_slice_in_use(false)
|
||||||
);
|
);
|
||||||
|
@ -354,7 +378,11 @@ impl DdrRam {
|
||||||
.gatelvl_init_ratio(0xee)
|
.gatelvl_init_ratio(0xee)
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
#[cfg(any(
|
||||||
|
feature = "target_coraz7",
|
||||||
|
feature = "target_ebaz4205",
|
||||||
|
feature = "target_kasli_soc"),
|
||||||
|
)]
|
||||||
self.regs.reg_64.modify(
|
self.regs.reg_64.modify(
|
||||||
|_, w| w
|
|_, w| w
|
||||||
.phy_ctrl_slave_ratio(0x100)
|
.phy_ctrl_slave_ratio(0x100)
|
||||||
|
@ -390,9 +418,12 @@ impl DdrRam {
|
||||||
fn reset_ddrc<F: FnMut(&mut Self)>(&mut self, mut f: F) {
|
fn reset_ddrc<F: FnMut(&mut Self)>(&mut self, mut f: F) {
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(feature = "target_zc706")]
|
||||||
let width = regs::DataBusWidth::Width32bit;
|
let width = regs::DataBusWidth::Width32bit;
|
||||||
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
#[cfg(any(
|
||||||
let width = regs::DataBusWidth::Width16bit;
|
feature = "target_coraz7",
|
||||||
#[cfg(feature = "target_redpitaya")]
|
feature = "target_ebaz4205",
|
||||||
|
feature = "target_redpitaya",
|
||||||
|
feature = "target_kasli_soc",
|
||||||
|
))]
|
||||||
let width = regs::DataBusWidth::Width16bit;
|
let width = regs::DataBusWidth::Width16bit;
|
||||||
self.regs.ddrc_ctrl.modify(|_, w| w
|
self.regs.ddrc_ctrl.modify(|_, w| w
|
||||||
.soft_rstb(false)
|
.soft_rstb(false)
|
||||||
|
@ -410,6 +441,7 @@ impl DdrRam {
|
||||||
}
|
}
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
feature = "target_coraz7",
|
feature = "target_coraz7",
|
||||||
|
feature = "target_ebaz4205",
|
||||||
feature = "target_redpitaya",
|
feature = "target_redpitaya",
|
||||||
feature = "target_kasli_soc",
|
feature = "target_kasli_soc",
|
||||||
))]
|
))]
|
||||||
|
@ -450,6 +482,8 @@ impl DdrRam {
|
||||||
feature = "target_kasli_soc",
|
feature = "target_kasli_soc",
|
||||||
))]
|
))]
|
||||||
let megabytes = 512;
|
let megabytes = 512;
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
let megabytes = 256;
|
||||||
|
|
||||||
megabytes * 1024 * 1024
|
megabytes * 1024 * 1024
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,17 +65,31 @@ impl Gem for Gem0 {
|
||||||
slcr.gem0_clk_ctrl.write(
|
slcr.gem0_clk_ctrl.write(
|
||||||
// 0x0050_0801: 8, 5: 100 Mb/s
|
// 0x0050_0801: 8, 5: 100 Mb/s
|
||||||
// ...: 8, 1: 1000 Mb/s
|
// ...: 8, 1: 1000 Mb/s
|
||||||
|
#[cfg(not(feature = "target_ebaz4205"))]
|
||||||
slcr::GemClkCtrl::zeroed()
|
slcr::GemClkCtrl::zeroed()
|
||||||
.clkact(true)
|
.clkact(true)
|
||||||
.srcsel(slcr::PllSource::IoPll)
|
.srcsel(slcr::PllSource::IoPll)
|
||||||
.divisor(divisor0 as u8)
|
.divisor(divisor0 as u8)
|
||||||
|
.divisor1(divisor1 as u8),
|
||||||
|
// ebaz4205 -- EMIO
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
slcr::GemClkCtrl::zeroed()
|
||||||
|
.clkact(true)
|
||||||
|
.srcsel(slcr::PllSource::Emio)
|
||||||
|
.divisor(divisor0 as u8)
|
||||||
.divisor1(divisor1 as u8)
|
.divisor1(divisor1 as u8)
|
||||||
);
|
);
|
||||||
// Enable gem0 recv clock
|
// Enable gem0 recv clock
|
||||||
slcr.gem0_rclk_ctrl.write(
|
slcr.gem0_rclk_ctrl.write(
|
||||||
// 0x0000_0801
|
// 0x0000_0801
|
||||||
|
#[cfg(not(feature = "target_ebaz4205"))]
|
||||||
|
slcr::RclkCtrl::zeroed()
|
||||||
|
.clkact(true),
|
||||||
|
// ebaz4205 -- EMIO
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
slcr::RclkCtrl::zeroed()
|
slcr::RclkCtrl::zeroed()
|
||||||
.clkact(true)
|
.clkact(true)
|
||||||
|
.srcsel(true)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -154,6 +168,7 @@ pub struct Eth<GEM: Gem, RX, TX> {
|
||||||
|
|
||||||
impl Eth<Gem0, (), ()> {
|
impl Eth<Gem0, (), ()> {
|
||||||
pub fn eth0(macaddr: [u8; 6]) -> Self {
|
pub fn eth0(macaddr: [u8; 6]) -> Self {
|
||||||
|
#[cfg(not(feature = "target_ebaz4205"))]
|
||||||
slcr::RegisterBlock::unlocked(|slcr| {
|
slcr::RegisterBlock::unlocked(|slcr| {
|
||||||
// Manual example: 0x0000_1280
|
// Manual example: 0x0000_1280
|
||||||
// MDIO
|
// MDIO
|
||||||
|
|
|
@ -83,6 +83,7 @@ pub struct Phy {
|
||||||
const OUI_MARVELL: u32 = 0x005043;
|
const OUI_MARVELL: u32 = 0x005043;
|
||||||
const OUI_REALTEK: u32 = 0x000732;
|
const OUI_REALTEK: u32 = 0x000732;
|
||||||
const OUI_LANTIQ : u32 = 0x355969;
|
const OUI_LANTIQ : u32 = 0x355969;
|
||||||
|
const OUI_ICPLUS : u32 = 0x0090c3;
|
||||||
|
|
||||||
//only change pages on Kasli-SoC's Marvel 88E11xx
|
//only change pages on Kasli-SoC's Marvel 88E11xx
|
||||||
#[cfg(feature="target_kasli_soc")]
|
#[cfg(feature="target_kasli_soc")]
|
||||||
|
@ -117,6 +118,12 @@ impl Phy {
|
||||||
model: 0,
|
model: 0,
|
||||||
..
|
..
|
||||||
}) => true,
|
}) => true,
|
||||||
|
Some(PhyIdentifier {
|
||||||
|
oui: OUI_ICPLUS,
|
||||||
|
// IP101G-DS-R01
|
||||||
|
model: 5,
|
||||||
|
rev: 4,
|
||||||
|
}) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}).map(|addr| Phy { addr })
|
}).map(|addr| Phy { addr })
|
||||||
|
|
|
@ -4,6 +4,7 @@ use embedded_hal::timer::CountDown;
|
||||||
|
|
||||||
pub struct EEPROM<'a> {
|
pub struct EEPROM<'a> {
|
||||||
i2c: &'a mut I2c,
|
i2c: &'a mut I2c,
|
||||||
|
#[cfg(not(feature = "target_ebaz4205"))]
|
||||||
port: u8,
|
port: u8,
|
||||||
address: u8,
|
address: u8,
|
||||||
page_size: u8,
|
page_size: u8,
|
||||||
|
@ -46,6 +47,11 @@ impl<'a> EEPROM<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
fn select(&mut self) -> Result<(), &'static str> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Random read
|
/// Random read
|
||||||
pub fn read<'r>(&mut self, addr: u8, buf: &'r mut [u8]) -> Result<(), &'static str> {
|
pub fn read<'r>(&mut self, addr: u8, buf: &'r mut [u8]) -> Result<(), &'static str> {
|
||||||
self.select()?;
|
self.select()?;
|
||||||
|
|
|
@ -2,10 +2,13 @@
|
||||||
|
|
||||||
mod regs;
|
mod regs;
|
||||||
pub mod eeprom;
|
pub mod eeprom;
|
||||||
|
#[cfg(not(feature = "target_ebaz4205"))]
|
||||||
use super::slcr;
|
use super::slcr;
|
||||||
use super::time::Microseconds;
|
use super::time::Microseconds;
|
||||||
use embedded_hal::timer::CountDown;
|
use embedded_hal::timer::CountDown;
|
||||||
use libregister::{RegisterR, RegisterRW, RegisterW};
|
use libregister::{RegisterR, RegisterRW};
|
||||||
|
#[cfg(not(feature = "target_ebaz4205"))]
|
||||||
|
use libregister::RegisterW;
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
|
@ -22,9 +25,10 @@ pub struct I2c {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl I2c {
|
impl I2c {
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
pub fn i2c0() -> Self {
|
pub fn i2c0() -> Self {
|
||||||
// Route I2C 0 SCL / SDA Signals to MIO Pins 50 / 51
|
// Route I2C 0 SCL / SDA Signals to MIO Pins 50 / 51
|
||||||
|
#[cfg(not(feature = "target_ebaz4205"))]
|
||||||
slcr::RegisterBlock::unlocked(|slcr| {
|
slcr::RegisterBlock::unlocked(|slcr| {
|
||||||
// SCL
|
// SCL
|
||||||
slcr.mio_pin_50.write(
|
slcr.mio_pin_50.write(
|
||||||
|
|
|
@ -21,6 +21,7 @@ use libregister::{
|
||||||
// Current compatibility:
|
// Current compatibility:
|
||||||
// zc706: GPIO 50, 51 == SCL, SDA
|
// zc706: GPIO 50, 51 == SCL, SDA
|
||||||
// kasli_soc: GPIO 50, 51 == SCL, SDA; GPIO 33 == I2C_SW_RESET
|
// kasli_soc: GPIO 50, 51 == SCL, SDA; GPIO 33 == I2C_SW_RESET
|
||||||
|
// ebaz4205: GPIO (EMIO)
|
||||||
|
|
||||||
pub struct RegisterBlock {
|
pub struct RegisterBlock {
|
||||||
pub gpio_output_mask: &'static mut GPIOOutputMask,
|
pub gpio_output_mask: &'static mut GPIOOutputMask,
|
||||||
|
@ -48,17 +49,17 @@ register!(gpio_output_mask,
|
||||||
/// MASK_DATA_1_MSW:
|
/// MASK_DATA_1_MSW:
|
||||||
/// Maskable output data for MIO[53:48]
|
/// Maskable output data for MIO[53:48]
|
||||||
GPIOOutputMask, RW, u32);
|
GPIOOutputMask, RW, u32);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_at!(GPIOOutputMask, 0xE000A00C, new);
|
register_at!(GPIOOutputMask, 0xE000A00C, new);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_bit!(gpio_output_mask,
|
register_bit!(gpio_output_mask,
|
||||||
/// Output for SCL
|
/// Output for SCL
|
||||||
scl_o, 2);
|
scl_o, 2);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_bit!(gpio_output_mask,
|
register_bit!(gpio_output_mask,
|
||||||
/// Output for SDA
|
/// Output for SDA
|
||||||
sda_o, 3);
|
sda_o, 3);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_bits!(gpio_output_mask,
|
register_bits!(gpio_output_mask,
|
||||||
/// Mask for keeping bits except SCL and SDA unchanged
|
/// Mask for keeping bits except SCL and SDA unchanged
|
||||||
mask, u16, 16, 31);
|
mask, u16, 16, 31);
|
||||||
|
@ -82,13 +83,13 @@ register!(gpio_input,
|
||||||
/// DATA_1_RO:
|
/// DATA_1_RO:
|
||||||
/// Input data for MIO[53:32]
|
/// Input data for MIO[53:32]
|
||||||
GPIOInput, RO, u32);
|
GPIOInput, RO, u32);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_at!(GPIOInput, 0xE000A064, new);
|
register_at!(GPIOInput, 0xE000A064, new);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_bit!(gpio_input,
|
register_bit!(gpio_input,
|
||||||
/// Input for SCL
|
/// Input for SCL
|
||||||
scl, 18);
|
scl, 18);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_bit!(gpio_input,
|
register_bit!(gpio_input,
|
||||||
/// Input for SDA
|
/// Input for SDA
|
||||||
sda, 19);
|
sda, 19);
|
||||||
|
@ -98,13 +99,13 @@ register!(gpio_direction,
|
||||||
/// DIRM_1:
|
/// DIRM_1:
|
||||||
/// Direction mode for MIO[53:32]; 0/1 = in/out
|
/// Direction mode for MIO[53:32]; 0/1 = in/out
|
||||||
GPIODirection, RW, u32);
|
GPIODirection, RW, u32);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_at!(GPIODirection, 0xE000A244, new);
|
register_at!(GPIODirection, 0xE000A244, new);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_bit!(gpio_direction,
|
register_bit!(gpio_direction,
|
||||||
/// Direction for SCL
|
/// Direction for SCL
|
||||||
scl, 18);
|
scl, 18);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_bit!(gpio_direction,
|
register_bit!(gpio_direction,
|
||||||
/// Direction for SDA
|
/// Direction for SDA
|
||||||
sda, 19);
|
sda, 19);
|
||||||
|
@ -117,13 +118,13 @@ register!(gpio_output_enable,
|
||||||
/// OEN_1:
|
/// OEN_1:
|
||||||
/// Output enable for MIO[53:32]
|
/// Output enable for MIO[53:32]
|
||||||
GPIOOutputEnable, RW, u32);
|
GPIOOutputEnable, RW, u32);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_at!(GPIOOutputEnable, 0xE000A248, new);
|
register_at!(GPIOOutputEnable, 0xE000A248, new);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_bit!(gpio_output_enable,
|
register_bit!(gpio_output_enable,
|
||||||
/// Output enable for SCL
|
/// Output enable for SCL
|
||||||
scl, 18);
|
scl, 18);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_bit!(gpio_output_enable,
|
register_bit!(gpio_output_enable,
|
||||||
/// Output enable for SDA
|
/// Output enable for SDA
|
||||||
sda, 19);
|
sda, 19);
|
||||||
|
|
|
@ -19,7 +19,7 @@ pub mod gic;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
pub mod sdio;
|
pub mod sdio;
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
pub mod i2c;
|
pub mod i2c;
|
||||||
pub mod logger;
|
pub mod logger;
|
||||||
pub mod ps7_init;
|
pub mod ps7_init;
|
||||||
|
|
|
@ -116,8 +116,8 @@ impl Sdio {
|
||||||
.speed(true),
|
.speed(true),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// redpitaya card detect pin
|
// kasli_soc and redpitaya card detect pin
|
||||||
#[cfg(any(feature = "target_redpitaya", feature = "target_kasli_soc"))]
|
#[cfg(any(feature = "target_kasli_soc", feature = "target_redpitaya"))]
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
slcr.sd0_wp_cd_sel.write(46 << 16);
|
slcr.sd0_wp_cd_sel.write(46 << 16);
|
||||||
|
@ -128,6 +128,20 @@ impl Sdio {
|
||||||
.speed(true),
|
.speed(true),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// ebaz4205 card detect pin
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
slcr.sd0_wp_cd_sel.write(34 << 16);
|
||||||
|
}
|
||||||
|
slcr.mio_pin_34.write(
|
||||||
|
slcr::MioPin34::zeroed()
|
||||||
|
.io_type(slcr::IoBufferType::Lvcmos33)
|
||||||
|
.pullup(true)
|
||||||
|
.speed(true),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
slcr.sdio_rst_ctrl.reset_sdio0();
|
slcr.sdio_rst_ctrl.reset_sdio0();
|
||||||
slcr.aper_clk_ctrl.enable_sdio0();
|
slcr.aper_clk_ctrl.enable_sdio0();
|
||||||
slcr.sdio_clk_ctrl.enable_sdio0();
|
slcr.sdio_clk_ctrl.enable_sdio0();
|
||||||
|
|
|
@ -9,9 +9,11 @@ use libregister::{
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum PllSource {
|
pub enum PllSource {
|
||||||
IoPll = 0b00,
|
IoPll = 0b000,
|
||||||
ArmPll = 0b10,
|
ArmPll = 0b010,
|
||||||
DdrPll = 0b11,
|
DdrPll = 0b011,
|
||||||
|
// Ethernet controller 0 EMIO clock
|
||||||
|
Emio = 0b100,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
|
|
@ -47,7 +47,11 @@ impl DerefMut for LazyUart {
|
||||||
LazyUart::Uninitialized => {
|
LazyUart::Uninitialized => {
|
||||||
#[cfg(any(feature = "target_coraz7", feature = "target_redpitaya"))]
|
#[cfg(any(feature = "target_coraz7", feature = "target_redpitaya"))]
|
||||||
let uart = Uart::uart0(UART_RATE);
|
let uart = Uart::uart0(UART_RATE);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
#[cfg(any(
|
||||||
|
feature = "target_zc706",
|
||||||
|
feature = "target_ebaz4205",
|
||||||
|
feature = "target_kasli_soc",
|
||||||
|
))]
|
||||||
let uart = Uart::uart1(UART_RATE);
|
let uart = Uart::uart1(UART_RATE);
|
||||||
*self = LazyUart::Initialized(uart);
|
*self = LazyUart::Initialized(uart);
|
||||||
self
|
self
|
||||||
|
|
|
@ -79,6 +79,39 @@ impl Uart {
|
||||||
self_
|
self_
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
pub fn uart1(baudrate: u32) -> Self {
|
||||||
|
slcr::RegisterBlock::unlocked(|slcr| {
|
||||||
|
// Route UART 1 RxD/TxD Signals to MIO Pins
|
||||||
|
// TX pin
|
||||||
|
slcr.mio_pin_24.write(
|
||||||
|
slcr::MioPin24::zeroed()
|
||||||
|
.l3_sel(0b111)
|
||||||
|
.io_type(slcr::IoBufferType::Lvcmos33)
|
||||||
|
.pullup(true)
|
||||||
|
);
|
||||||
|
// RX pin
|
||||||
|
slcr.mio_pin_25.write(
|
||||||
|
slcr::MioPin25::zeroed()
|
||||||
|
.tri_enable(true)
|
||||||
|
.l3_sel(0b111)
|
||||||
|
.io_type(slcr::IoBufferType::Lvcmos33)
|
||||||
|
.pullup(true)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
slcr::RegisterBlock::unlocked(|slcr| {
|
||||||
|
slcr.uart_rst_ctrl.reset_uart1();
|
||||||
|
slcr.aper_clk_ctrl.enable_uart1();
|
||||||
|
slcr.uart_clk_ctrl.enable_uart1();
|
||||||
|
});
|
||||||
|
let mut self_ = Uart {
|
||||||
|
regs: regs::RegisterBlock::uart1(),
|
||||||
|
};
|
||||||
|
self_.configure(baudrate);
|
||||||
|
self_
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_byte(&mut self, value: u8) {
|
pub fn write_byte(&mut self, value: u8) {
|
||||||
while self.tx_fifo_full() {}
|
while self.tx_fifo_full() {}
|
||||||
|
|
||||||
|
|
|
@ -2,17 +2,22 @@
|
||||||
name = "libconfig"
|
name = "libconfig"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["M-Labs"]
|
authors = ["M-Labs"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libboard_zynq = { path = "../libboard_zynq" }
|
libboard_zynq = { path = "../libboard_zynq" }
|
||||||
core_io = { version = "0.1", features = ["collections"] }
|
|
||||||
fatfs = { version = "0.3", features = ["core_io"], default-features = false }
|
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
||||||
|
[dependencies.fatfs]
|
||||||
|
git = "https://github.com/rafalh/rust-fatfs"
|
||||||
|
rev = "85f06e0"
|
||||||
|
default-features = false
|
||||||
|
features = ["alloc", "lfn"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
target_zc706 = []
|
target_zc706 = []
|
||||||
target_coraz7 = []
|
target_coraz7 = []
|
||||||
|
target_ebaz4205 = []
|
||||||
target_redpitaya = []
|
target_redpitaya = []
|
||||||
target_kasli_soc = []
|
target_kasli_soc = []
|
||||||
ipv6 = []
|
ipv6 = []
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core_io::{Error, Read, Seek, SeekFrom};
|
use fatfs::{self, Read, Seek, SeekFrom};
|
||||||
use libboard_zynq::devc;
|
use libboard_zynq::devc;
|
||||||
|
use crate::sd_reader;
|
||||||
|
use crate::File;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
|
||||||
|
type Error = fatfs::Error<sd_reader::Error>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum BootgenLoadingError {
|
pub enum BootgenLoadingError {
|
||||||
InvalidBootImageHeader,
|
InvalidBootImageHeader,
|
||||||
|
@ -58,7 +62,7 @@ struct PartitionHeader {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a u32 word from the reader.
|
/// Read a u32 word from the reader.
|
||||||
fn read_u32<Reader: Read>(reader: &mut Reader) -> Result<u32, BootgenLoadingError> {
|
fn read_u32<'a>(reader: &mut File<'a>) -> Result<u32, BootgenLoadingError> {
|
||||||
let mut buffer: [u8; 4] = [0; 4];
|
let mut buffer: [u8; 4] = [0; 4];
|
||||||
reader.read_exact(&mut buffer)?;
|
reader.read_exact(&mut buffer)?;
|
||||||
let mut result: u32 = 0;
|
let mut result: u32 = 0;
|
||||||
|
@ -69,8 +73,8 @@ fn read_u32<Reader: Read>(reader: &mut Reader) -> Result<u32, BootgenLoadingErro
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Load PL partition header.
|
/// Load PL partition header.
|
||||||
fn load_pl_header<File: Read + Seek>(
|
fn load_pl_header<'a>(
|
||||||
file: &mut File,
|
file: &mut File<'a>,
|
||||||
) -> Result<Option<PartitionHeader>, BootgenLoadingError> {
|
) -> Result<Option<PartitionHeader>, BootgenLoadingError> {
|
||||||
let mut buffer: [u8; 0x40] = [0; 0x40];
|
let mut buffer: [u8; 0x40] = [0; 0x40];
|
||||||
file.read_exact(&mut buffer)?;
|
file.read_exact(&mut buffer)?;
|
||||||
|
@ -82,8 +86,8 @@ fn load_pl_header<File: Read + Seek>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_ps_header<File: Read + Seek>(
|
fn load_ps_header<'a>(
|
||||||
file: &mut File,
|
file: &mut File<'a>,
|
||||||
) -> Result<Option<PartitionHeader>, BootgenLoadingError> {
|
) -> Result<Option<PartitionHeader>, BootgenLoadingError> {
|
||||||
let mut buffer: [u8; 0x40] = [0; 0x40];
|
let mut buffer: [u8; 0x40] = [0; 0x40];
|
||||||
file.read_exact(&mut buffer)?;
|
file.read_exact(&mut buffer)?;
|
||||||
|
@ -98,10 +102,10 @@ fn load_ps_header<File: Read + Seek>(
|
||||||
/// Locate the partition from the image, and return the size (in bytes) of the partition if successful.
|
/// Locate the partition from the image, and return the size (in bytes) of the partition if successful.
|
||||||
/// This function would seek the file to the location of the partition.
|
/// This function would seek the file to the location of the partition.
|
||||||
fn locate<
|
fn locate<
|
||||||
File: Read + Seek,
|
'a,
|
||||||
F: Fn(&mut File) -> Result<Option<PartitionHeader>, BootgenLoadingError>,
|
F: Fn(&mut File<'a>) -> Result<Option<PartitionHeader>, BootgenLoadingError>,
|
||||||
>(
|
>(
|
||||||
file: &mut File,
|
file: &mut File<'a>,
|
||||||
f: F,
|
f: F,
|
||||||
) -> Result<usize, BootgenLoadingError> {
|
) -> Result<usize, BootgenLoadingError> {
|
||||||
file.seek(SeekFrom::Start(0))?;
|
file.seek(SeekFrom::Start(0))?;
|
||||||
|
@ -149,7 +153,7 @@ fn locate<
|
||||||
/// Load bitstream from bootgen file.
|
/// Load bitstream from bootgen file.
|
||||||
/// This function parses the file, locate the bitstream and load it through the PCAP driver.
|
/// This function parses the file, locate the bitstream and load it through the PCAP driver.
|
||||||
/// It requires a large buffer, please enable the DDR RAM before using it.
|
/// It requires a large buffer, please enable the DDR RAM before using it.
|
||||||
pub fn load_bitstream<File: Read + Seek>(file: &mut File) -> Result<(), BootgenLoadingError> {
|
pub fn load_bitstream<'a>(file: &mut File<'a>) -> Result<(), BootgenLoadingError> {
|
||||||
let size = locate(file, load_pl_header)?;
|
let size = locate(file, load_pl_header)?;
|
||||||
unsafe {
|
unsafe {
|
||||||
// align to 64 bytes
|
// align to 64 bytes
|
||||||
|
@ -170,7 +174,7 @@ pub fn load_bitstream<File: Read + Seek>(file: &mut File) -> Result<(), BootgenL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_runtime<File: Read + Seek>(file: &mut File) -> Result<Vec<u8>, BootgenLoadingError> {
|
pub fn get_runtime<'a>(file: &mut File<'a>) -> Result<Vec<u8>, BootgenLoadingError> {
|
||||||
let size = locate(file, load_ps_header)?;
|
let size = locate(file, load_ps_header)?;
|
||||||
let mut buffer = Vec::with_capacity(size);
|
let mut buffer = Vec::with_capacity(size);
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -1,19 +1,24 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
use core::fmt;
|
use alloc::{rc::Rc, string::{FromUtf8Error, String}, vec::Vec};
|
||||||
use alloc::{string::FromUtf8Error, string::String, vec::Vec, rc::Rc};
|
use sd_reader::SdReader;
|
||||||
use core_io::{self as io, BufRead, BufReader, Read, Write, Seek, SeekFrom};
|
use core::{cmp, fmt};
|
||||||
|
use fatfs::{self, Read, Seek, SeekFrom, Write};
|
||||||
use libboard_zynq::sdio;
|
use libboard_zynq::sdio;
|
||||||
|
|
||||||
pub mod sd_reader;
|
|
||||||
pub mod net_settings;
|
|
||||||
pub mod bootgen;
|
pub mod bootgen;
|
||||||
|
pub mod net_settings;
|
||||||
|
pub mod sd_reader;
|
||||||
|
|
||||||
|
type SdReadError = fatfs::Error<sd_reader::Error>;
|
||||||
|
|
||||||
|
pub type File<'a> = fatfs::File<'a, SdReader, fatfs::NullTimeProvider, fatfs::LossyOemCpConverter>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error<'a> {
|
pub enum Error<'a> {
|
||||||
SdError(sdio::sd_card::CardInitializationError),
|
SdError(sdio::sd_card::CardInitializationError),
|
||||||
IoError(io::Error),
|
IoError(SdReadError),
|
||||||
Utf8Error(FromUtf8Error),
|
Utf8Error(FromUtf8Error),
|
||||||
KeyNotFoundError(&'a str),
|
KeyNotFoundError(&'a str),
|
||||||
NoConfig,
|
NoConfig,
|
||||||
|
@ -39,8 +44,8 @@ impl<'a> From<sdio::sd_card::CardInitializationError> for Error<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<io::Error> for Error<'a> {
|
impl<'a> From<SdReadError> for Error<'a> {
|
||||||
fn from(error: io::Error) -> Self {
|
fn from(error: SdReadError) -> Self {
|
||||||
Error::IoError(error)
|
Error::IoError(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,14 +56,60 @@ impl<'a> From<FromUtf8Error> for Error<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Simplified replacements to `read_to_end` and `read_to_string` from core_io
|
||||||
|
fn read_to_end<'a>(file: &mut File<'a>, buffer: &mut Vec<u8>) -> Result<'a, usize> {
|
||||||
|
const PROBE_SIZE: usize = 32;
|
||||||
|
const MAX_READ_SIZE: usize = 512; // read max BLOCK_SIZE at a time
|
||||||
|
let start_len = buffer.len();
|
||||||
|
let start_cap = buffer.capacity();
|
||||||
|
fn small_probe_read<'a>(file: &mut File<'a>, buffer: &mut Vec<u8>) -> Result<'a, usize> {
|
||||||
|
let mut probe = [0u8; PROBE_SIZE];
|
||||||
|
let n = file.read(&mut probe)?;
|
||||||
|
buffer.extend_from_slice(&probe[..n]);
|
||||||
|
Ok(n)
|
||||||
|
}
|
||||||
|
if start_cap - start_len < PROBE_SIZE {
|
||||||
|
let read = small_probe_read(file, buffer)?;
|
||||||
|
if read == 0 {
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loop {
|
||||||
|
if buffer.len() == buffer.capacity() && buffer.capacity() == start_cap {
|
||||||
|
let read = small_probe_read(file, buffer)?;
|
||||||
|
if read == 0 {
|
||||||
|
return Ok(buffer.len() - start_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if buffer.len() == buffer.capacity() {
|
||||||
|
buffer.try_reserve(PROBE_SIZE).unwrap();
|
||||||
|
}
|
||||||
|
let mut read_buf = [0u8; MAX_READ_SIZE];
|
||||||
|
let buf_len = cmp::min(MAX_READ_SIZE, buffer.capacity() - buffer.len());
|
||||||
|
let mut read_buf_mut = &mut read_buf[..buf_len];
|
||||||
|
let bytes_read = file.read(&mut read_buf_mut)?;
|
||||||
|
if bytes_read == 0 {
|
||||||
|
return Ok(buffer.len() - start_len);
|
||||||
|
}
|
||||||
|
buffer.extend_from_slice(&read_buf_mut[..bytes_read]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_to_string<'a>(file: &mut File<'a>) -> Result<'a, String> {
|
||||||
|
let mut buffer: Vec<u8> = Vec::new();
|
||||||
|
read_to_end(file, &mut buffer).map(|_| ())?;
|
||||||
|
Ok(String::from_utf8(buffer)?)
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_config<'a>(
|
fn parse_config<'a>(
|
||||||
key: &'a str,
|
key: &'a str,
|
||||||
buffer: &mut Vec<u8>,
|
buffer: &mut Vec<u8>,
|
||||||
file: fatfs::File<sd_reader::SdReader>,
|
mut file: File<'a>,
|
||||||
) -> Result<'a, ()> {
|
) -> Result<'a, ()> {
|
||||||
let prefix = [key, "="].concat().to_ascii_lowercase();
|
let prefix = [key, "="].concat().to_ascii_lowercase();
|
||||||
for line in BufReader::new(file).lines() {
|
let read_buffer = read_to_string(&mut file)?;
|
||||||
let line = line?.to_ascii_lowercase();
|
for line in read_buffer.lines() {
|
||||||
|
let line = line.to_ascii_lowercase();
|
||||||
if line.starts_with(&prefix) {
|
if line.starts_with(&prefix) {
|
||||||
buffer.extend(line[prefix.len()..].as_bytes());
|
buffer.extend(line[prefix.len()..].as_bytes());
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -83,7 +134,9 @@ impl Config {
|
||||||
let reader = sd_reader::SdReader::new(sd);
|
let reader = sd_reader::SdReader::new(sd);
|
||||||
|
|
||||||
let fs = reader.mount_fatfs(sd_reader::PartitionEntry::Entry1)?;
|
let fs = reader.mount_fatfs(sd_reader::PartitionEntry::Entry1)?;
|
||||||
Ok(Config { fs: Some(Rc::new(fs)) })
|
Ok(Config {
|
||||||
|
fs: Some(Rc::new(fs)),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_fs(fs: Option<Rc<fatfs::FileSystem<sd_reader::SdReader>>>) -> Self {
|
pub fn from_fs(fs: Option<Rc<fatfs::FileSystem<sd_reader::SdReader>>>) -> Self {
|
||||||
|
@ -94,12 +147,12 @@ impl Config {
|
||||||
Config { fs: None }
|
Config { fs: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read<'b>(&self, key: &'b str) -> Result<'b, Vec<u8>> {
|
pub fn read<'b>(&'b self, key: &'b str) -> Result<'b, Vec<u8>> {
|
||||||
if let Some(fs) = &self.fs {
|
if let Some(fs) = &self.fs {
|
||||||
let root_dir = fs.root_dir();
|
let root_dir = fs.root_dir();
|
||||||
let mut buffer: Vec<u8> = Vec::new();
|
let mut buffer: Vec<u8> = Vec::new();
|
||||||
match root_dir.open_file(&["/CONFIG/", key, ".BIN"].concat()) {
|
match root_dir.open_file(&["/CONFIG/", key, ".BIN"].concat()) {
|
||||||
Ok(mut f) => f.read_to_end(&mut buffer).map(|_| ())?,
|
Ok(mut f) => read_to_end( &mut f, &mut buffer).map(|_| ())?,
|
||||||
Err(_) => match root_dir.open_file("/CONFIG.TXT") {
|
Err(_) => match root_dir.open_file("/CONFIG.TXT") {
|
||||||
Ok(f) => parse_config(key, &mut buffer, f)?,
|
Ok(f) => parse_config(key, &mut buffer, f)?,
|
||||||
Err(_) => return Err(Error::KeyNotFoundError(key)),
|
Err(_) => return Err(Error::KeyNotFoundError(key)),
|
||||||
|
@ -111,11 +164,11 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_str<'b>(&self, key: &'b str) -> Result<'b, String> {
|
pub fn read_str<'b>(&'b self, key: &'b str) -> Result<'b, String> {
|
||||||
Ok(String::from_utf8(self.read(key)?)?)
|
Ok(String::from_utf8(self.read(key)?)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove<'b>(&self, key: &'b str) -> Result<'b, ()> {
|
pub fn remove<'b>(&'b self, key: &'b str) -> Result<'b, ()> {
|
||||||
if let Some(fs) = &self.fs {
|
if let Some(fs) = &self.fs {
|
||||||
let root_dir = fs.root_dir();
|
let root_dir = fs.root_dir();
|
||||||
match root_dir.remove(&["/CONFIG/", key, ".BIN"].concat()) {
|
match root_dir.remove(&["/CONFIG/", key, ".BIN"].concat()) {
|
||||||
|
@ -124,19 +177,19 @@ impl Config {
|
||||||
let prefix = [key, "="].concat().to_ascii_lowercase();
|
let prefix = [key, "="].concat().to_ascii_lowercase();
|
||||||
match root_dir.create_file("/CONFIG.TXT") {
|
match root_dir.create_file("/CONFIG.TXT") {
|
||||||
Ok(mut f) => {
|
Ok(mut f) => {
|
||||||
let mut buffer = String::new();
|
let buffer = read_to_string(&mut f)?;
|
||||||
f.read_to_string(&mut buffer)?;
|
|
||||||
f.seek(SeekFrom::Start(0))?;
|
f.seek(SeekFrom::Start(0))?;
|
||||||
f.truncate()?;
|
f.truncate()?;
|
||||||
for line in buffer.lines() {
|
for line in buffer.lines() {
|
||||||
if line.len() > 0 && !line.to_ascii_lowercase().starts_with(&prefix) {
|
if line.len() > 0 && !line.to_ascii_lowercase().starts_with(&prefix)
|
||||||
|
{
|
||||||
f.write(line.as_bytes())?;
|
f.write(line.as_bytes())?;
|
||||||
f.write(NEWLINE)?;
|
f.write(NEWLINE)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
}
|
||||||
Err(_) => Err(Error::KeyNotFoundError(key))
|
Err(_) => Err(Error::KeyNotFoundError(key)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,7 +215,10 @@ impl Config {
|
||||||
if is_str {
|
if is_str {
|
||||||
let mut f = root_dir.create_file("/CONFIG.TXT")?;
|
let mut f = root_dir.create_file("/CONFIG.TXT")?;
|
||||||
f.seek(SeekFrom::End(0))?;
|
f.seek(SeekFrom::End(0))?;
|
||||||
write!(f, "{}={}\n", key, String::from_utf8(value).unwrap())?;
|
f.write(key.as_bytes())?;
|
||||||
|
f.write("=".as_bytes())?;
|
||||||
|
f.write(value.as_slice())?;
|
||||||
|
f.write(NEWLINE)?;
|
||||||
} else {
|
} else {
|
||||||
let dir = root_dir.create_dir("/CONFIG")?;
|
let dir = root_dir.create_dir("/CONFIG")?;
|
||||||
let mut f = dir.create_file(&[key, ".BIN"].concat())?;
|
let mut f = dir.create_file(&[key, ".BIN"].concat())?;
|
||||||
|
|
|
@ -59,6 +59,10 @@ pub fn get_addresses(cfg: &Config) -> NetAddresses {
|
||||||
let mut hardware_addr = get_address_from_eeprom();
|
let mut hardware_addr = get_address_from_eeprom();
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
let mut ipv4_addr = IpAddress::v4(192, 168, 1, 56);
|
let mut ipv4_addr = IpAddress::v4(192, 168, 1, 56);
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
let mut hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x57]);
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
let mut ipv4_addr = IpAddress::v4(192, 168, 1, 57);
|
||||||
|
|
||||||
if let Ok(Ok(addr)) = cfg.read_str("mac").map(|s| s.parse()) {
|
if let Ok(Ok(addr)) = cfg.read_str("mac").map(|s| s.parse()) {
|
||||||
hardware_addr = addr;
|
hardware_addr = addr;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use core_io::{BufRead, Error, ErrorKind, Read, Result as IoResult, Seek, SeekFrom, Write};
|
use alloc::vec::Vec;
|
||||||
use fatfs;
|
use core::fmt;
|
||||||
|
use fatfs::{self, IoBase, IoError, Read, Seek, SeekFrom, Write};
|
||||||
use libboard_zynq::sdio::{sd_card::SdCard, CmdTransferError};
|
use libboard_zynq::sdio::{sd_card::SdCard, CmdTransferError};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use alloc::vec::Vec;
|
|
||||||
|
|
||||||
const MBR_SIGNATURE: [u8; 2] = [0x55, 0xAA];
|
const MBR_SIGNATURE: [u8; 2] = [0x55, 0xAA];
|
||||||
const PARTID_FAT12: u8 = 0x01;
|
const PARTID_FAT12: u8 = 0x01;
|
||||||
|
@ -12,13 +12,46 @@ const PARTID_FAT32: u8 = 0x0B;
|
||||||
const PARTID_FAT32_LBA: u8 = 0x0C;
|
const PARTID_FAT32_LBA: u8 = 0x0C;
|
||||||
const PARTID_FAT16_LBA: u8 = 0x0E;
|
const PARTID_FAT16_LBA: u8 = 0x0E;
|
||||||
|
|
||||||
fn cmd_error_to_io_error(_: CmdTransferError) -> Error {
|
|
||||||
Error::new(ErrorKind::Other, "Command transfer error")
|
|
||||||
}
|
|
||||||
|
|
||||||
const BLOCK_SIZE: usize = 512;
|
const BLOCK_SIZE: usize = 512;
|
||||||
|
|
||||||
/// SdReader struct implementing `Read + BufRead + Write + Seek` traits for `core_io`.
|
#[derive(Debug)]
|
||||||
|
pub struct Error {
|
||||||
|
message: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error {
|
||||||
|
pub fn new(message: &'static str) -> Self {
|
||||||
|
Self { message: message }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IoError for Error {
|
||||||
|
fn is_interrupted(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_unexpected_eof_error() -> Self {
|
||||||
|
Error::new("Unexpected end of file error")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_write_zero_error() -> Self {
|
||||||
|
Error::new("Write zero error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CmdTransferError> for Error {
|
||||||
|
fn from(_: CmdTransferError) -> Self {
|
||||||
|
Error::new("Command transfer error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// SdReader struct implementing `Read + Write + Seek` traits for `core_io`.
|
||||||
/// Used as an adaptor for fatfs crate, but could be used directly for raw data access.
|
/// Used as an adaptor for fatfs crate, but could be used directly for raw data access.
|
||||||
///
|
///
|
||||||
/// Implementation: all read/writes would be split into unaligned and block-aligned parts,
|
/// Implementation: all read/writes would be split into unaligned and block-aligned parts,
|
||||||
|
@ -43,6 +76,10 @@ pub struct SdReader {
|
||||||
offset: u32,
|
offset: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IoBase for SdReader {
|
||||||
|
type Error = Error;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
// Partition entry enum, normally we would use entry1.
|
// Partition entry enum, normally we would use entry1.
|
||||||
|
@ -72,7 +109,7 @@ impl SdReader {
|
||||||
|
|
||||||
/// Internal read function for unaligned read.
|
/// Internal read function for unaligned read.
|
||||||
/// The read must not cross block boundary.
|
/// The read must not cross block boundary.
|
||||||
fn read_unaligned(&mut self, buf: &mut [u8]) -> IoResult<usize> {
|
fn read_unaligned(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||||
if buf.len() == 0 {
|
if buf.len() == 0 {
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
|
@ -86,7 +123,7 @@ impl SdReader {
|
||||||
|
|
||||||
/// Internal write function for unaligned write.
|
/// Internal write function for unaligned write.
|
||||||
/// The write must not cross block boundary.
|
/// The write must not cross block boundary.
|
||||||
fn write_unaligned(&mut self, buf: &[u8]) -> IoResult<usize> {
|
fn write_unaligned(&mut self, buf: &[u8]) -> Result<usize, Error> {
|
||||||
if buf.len() == 0 {
|
if buf.len() == 0 {
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
|
@ -137,7 +174,7 @@ impl SdReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the base offset of the SD card, to transform from physical address to logical address.
|
/// Set the base offset of the SD card, to transform from physical address to logical address.
|
||||||
fn set_base_offset(&mut self, offset: u32) -> IoResult<u64> {
|
fn set_base_offset(&mut self, offset: u32) -> Result<u64, Error> {
|
||||||
self.offset = offset;
|
self.offset = offset;
|
||||||
self.seek(SeekFrom::Start(0))
|
self.seek(SeekFrom::Start(0))
|
||||||
}
|
}
|
||||||
|
@ -145,29 +182,28 @@ impl SdReader {
|
||||||
/// Mount fatfs from partition entry, and return the fatfs object if success.
|
/// Mount fatfs from partition entry, and return the fatfs object if success.
|
||||||
/// This takes the ownership of self, so currently there is no way to recover from an error,
|
/// This takes the ownership of self, so currently there is no way to recover from an error,
|
||||||
/// except creating a new SD card instance.
|
/// except creating a new SD card instance.
|
||||||
pub fn mount_fatfs(mut self, entry: PartitionEntry) -> IoResult<fatfs::FileSystem<Self>> {
|
pub fn mount_fatfs(
|
||||||
|
mut self,
|
||||||
|
entry: PartitionEntry,
|
||||||
|
) -> Result<fatfs::FileSystem<Self>, fatfs::Error<Error>> {
|
||||||
let mut buffer: [u8; 4] = [0; 4];
|
let mut buffer: [u8; 4] = [0; 4];
|
||||||
self.seek(SeekFrom::Start(0x1FE))?;
|
self.seek(SeekFrom::Start(0x1FE))?;
|
||||||
self.read_exact(&mut buffer[..2])?;
|
self.read_exact(&mut buffer[..2])?;
|
||||||
// check MBR signature
|
// check MBR signature
|
||||||
if buffer[..2] != MBR_SIGNATURE {
|
if buffer[..2] != MBR_SIGNATURE {
|
||||||
return Err(Error::new(
|
return Err(fatfs::Error::Io(Error::new("Incorrect signature for MBR sector.")));
|
||||||
ErrorKind::InvalidData,
|
|
||||||
"Incorrect signature for MBR sector.",
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
// Read partition ID.
|
// Read partition ID.
|
||||||
self.seek(SeekFrom::Start(entry as u64 + 0x4))?;
|
self.seek(SeekFrom::Start(entry as u64 + 0x4))?;
|
||||||
self.read_exact(&mut buffer[..1])?;
|
self.read_exact(&mut buffer[..1])?;
|
||||||
debug!("Partition ID: {:0X}", buffer[0]);
|
debug!("Partition ID: {:0X}", buffer[0]);
|
||||||
match buffer[0] {
|
match buffer[0] {
|
||||||
PARTID_FAT12 | PARTID_FAT16_LESS32M | PARTID_FAT16 |
|
PARTID_FAT12 | PARTID_FAT16_LESS32M | PARTID_FAT16 | PARTID_FAT16_LBA
|
||||||
PARTID_FAT16_LBA | PARTID_FAT32 | PARTID_FAT32_LBA => {}
|
| PARTID_FAT32 | PARTID_FAT32_LBA => {}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::new(
|
return Err(fatfs::Error::Io(Error::new(
|
||||||
ErrorKind::InvalidData,
|
|
||||||
"No FAT partition found for the specified entry.",
|
"No FAT partition found for the specified entry.",
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Read LBA
|
// Read LBA
|
||||||
|
@ -183,10 +219,29 @@ impl SdReader {
|
||||||
// setup fatfs
|
// setup fatfs
|
||||||
fatfs::FileSystem::new(self, fatfs::FsOptions::new())
|
fatfs::FileSystem::new(self, fatfs::FsOptions::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fill_buf(&mut self) -> Result<&[u8], Error> {
|
||||||
|
if self.index == BLOCK_SIZE {
|
||||||
|
// flush the buffer if it is dirty before overwriting it with new data
|
||||||
|
if self.dirty {
|
||||||
|
self.flush()?;
|
||||||
|
}
|
||||||
|
// reload buffer
|
||||||
|
self.sd
|
||||||
|
.read_block(self.byte_addr / (BLOCK_SIZE as u32), 1, &mut self.buffer)?;
|
||||||
|
self.index = (self.byte_addr as usize) % BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
Ok(&self.buffer[self.index..])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn consume(&mut self, amt: usize) {
|
||||||
|
self.index += amt;
|
||||||
|
self.byte_addr += amt as u32;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Read for SdReader {
|
impl Read for SdReader {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||||
let total_length = buf.len();
|
let total_length = buf.len();
|
||||||
let (a, b, c) = self.block_align_mut(buf);
|
let (a, b, c) = self.block_align_mut(buf);
|
||||||
self.read_unaligned(a)?;
|
self.read_unaligned(a)?;
|
||||||
|
@ -211,30 +266,8 @@ impl Read for SdReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BufRead for SdReader {
|
|
||||||
fn fill_buf(&mut self) -> IoResult<&[u8]> {
|
|
||||||
if self.index == BLOCK_SIZE {
|
|
||||||
// flush the buffer if it is dirty before overwriting it with new data
|
|
||||||
if self.dirty {
|
|
||||||
self.flush()?;
|
|
||||||
}
|
|
||||||
// reload buffer
|
|
||||||
self.sd
|
|
||||||
.read_block(self.byte_addr / (BLOCK_SIZE as u32), 1, &mut self.buffer)
|
|
||||||
.map_err(cmd_error_to_io_error)?;
|
|
||||||
self.index = (self.byte_addr as usize) % BLOCK_SIZE;
|
|
||||||
}
|
|
||||||
Ok(&self.buffer[self.index..])
|
|
||||||
}
|
|
||||||
|
|
||||||
fn consume(&mut self, amt: usize) {
|
|
||||||
self.index += amt;
|
|
||||||
self.byte_addr += amt as u32;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Write for SdReader {
|
impl Write for SdReader {
|
||||||
fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
|
fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
|
||||||
let (a, b, c) = self.block_align(buf);
|
let (a, b, c) = self.block_align(buf);
|
||||||
self.write_unaligned(a)?;
|
self.write_unaligned(a)?;
|
||||||
if b.len() > 0 {
|
if b.len() > 0 {
|
||||||
|
@ -255,12 +288,10 @@ impl Write for SdReader {
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&mut self) -> IoResult<()> {
|
fn flush(&mut self) -> Result<(), Error> {
|
||||||
if self.dirty {
|
if self.dirty {
|
||||||
let block_addr = (self.byte_addr - self.index as u32) / (BLOCK_SIZE as u32);
|
let block_addr = (self.byte_addr - self.index as u32) / (BLOCK_SIZE as u32);
|
||||||
self.sd
|
self.sd.write_block(block_addr, 1, &self.buffer)?;
|
||||||
.write_block(block_addr, 1, &self.buffer)
|
|
||||||
.map_err(cmd_error_to_io_error)?;
|
|
||||||
self.dirty = false;
|
self.dirty = false;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -268,14 +299,14 @@ impl Write for SdReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Seek for SdReader {
|
impl Seek for SdReader {
|
||||||
fn seek(&mut self, pos: SeekFrom) -> IoResult<u64> {
|
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Error> {
|
||||||
let raw_target = match pos {
|
let raw_target = match pos {
|
||||||
SeekFrom::Start(x) => self.offset as i64 + x as i64,
|
SeekFrom::Start(x) => self.offset as i64 + x as i64,
|
||||||
SeekFrom::Current(x) => self.byte_addr as i64 + x,
|
SeekFrom::Current(x) => self.byte_addr as i64 + x,
|
||||||
SeekFrom::End(_) => panic!("SD card does not support seek from end"),
|
SeekFrom::End(_) => panic!("SD card does not support seek from end"),
|
||||||
};
|
};
|
||||||
if raw_target < self.offset as i64 || raw_target > core::u32::MAX as i64 {
|
if raw_target < self.offset as i64 || raw_target > core::u32::MAX as i64 {
|
||||||
return Err(Error::new(ErrorKind::InvalidInput, "Invalid address"));
|
return Err(Error::new("Invalid address"));
|
||||||
}
|
}
|
||||||
let target_byte_addr = raw_target as u32;
|
let target_byte_addr = raw_target as u32;
|
||||||
let address_same_block =
|
let address_same_block =
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
name = "libcortex_a9"
|
name = "libcortex_a9"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
authors = ["M-Labs"]
|
authors = ["M-Labs"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
power_saving = []
|
power_saving = []
|
||||||
|
|
|
@ -1,59 +1,60 @@
|
||||||
|
use core::arch::asm;
|
||||||
|
|
||||||
/// The classic no-op
|
/// The classic no-op
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn nop() {
|
pub fn nop() {
|
||||||
unsafe { llvm_asm!("nop" :::: "volatile") }
|
unsafe { asm!("nop") }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait For Event
|
/// Wait For Event
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn wfe() {
|
pub fn wfe() {
|
||||||
unsafe { llvm_asm!("wfe" :::: "volatile") }
|
unsafe { asm!("wfe") }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send Event
|
/// Send Event
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn sev() {
|
pub fn sev() {
|
||||||
unsafe { llvm_asm!("sev" :::: "volatile") }
|
unsafe { asm!("sev") }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data Memory Barrier
|
/// Data Memory Barrier
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn dmb() {
|
pub fn dmb() {
|
||||||
unsafe { llvm_asm!("dmb" :::: "volatile") }
|
unsafe { asm!("dmb") }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data Synchronization Barrier
|
/// Data Synchronization Barrier
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn dsb() {
|
pub fn dsb() {
|
||||||
unsafe { llvm_asm!("dsb" :::: "volatile") }
|
unsafe { asm!("dsb") }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Instruction Synchronization Barrier
|
/// Instruction Synchronization Barrier
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn isb() {
|
pub fn isb() {
|
||||||
unsafe { llvm_asm!("isb" :::: "volatile") }
|
unsafe { asm!("isb") }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable FIQ
|
/// Enable FIQ
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn enable_fiq() {
|
pub unsafe fn enable_fiq() {
|
||||||
llvm_asm!("cpsie f":::: "volatile");
|
asm!("cpsie f");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable IRQ
|
/// Enable IRQ
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn enable_irq() {
|
pub unsafe fn enable_irq() {
|
||||||
llvm_asm!("cpsie i":::: "volatile");
|
asm!("cpsie i");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disable IRQ, return if IRQ was originally enabled.
|
/// Disable IRQ, return if IRQ was originally enabled.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn enter_critical() -> bool {
|
pub unsafe fn enter_critical() -> bool {
|
||||||
let mut cpsr: u32;
|
let mut cpsr: u32;
|
||||||
llvm_asm!(
|
asm!(
|
||||||
"mrs $0, cpsr
|
"mrs {}, cpsr
|
||||||
cpsid i"
|
cpsid i", lateout(reg) cpsr);
|
||||||
: "=r"(cpsr) ::: "volatile");
|
|
||||||
(cpsr & (1 << 7)) == 0
|
(cpsr & (1 << 7)) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,18 +66,18 @@ pub unsafe fn exit_critical(enable: bool) {
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
llvm_asm!(
|
asm!(
|
||||||
"mrs r1, cpsr
|
"mrs r1, cpsr
|
||||||
bic r1, r1, $0
|
bic r1, r1, {}
|
||||||
msr cpsr_c, r1"
|
msr cpsr_c, r1"
|
||||||
:: "r"(mask) : "r1");
|
, in(reg) mask, out("r1") _);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Exiting IRQ
|
/// Exiting IRQ
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn exit_irq() {
|
pub unsafe fn exit_irq() {
|
||||||
llvm_asm!("
|
asm!("
|
||||||
mrs r0, SPSR
|
mrs r0, SPSR
|
||||||
msr CPSR, r0
|
msr CPSR, r0
|
||||||
" ::: "r0");
|
", out("r0") _);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
use super::asm::{dmb, dsb};
|
use super::asm::{dmb, dsb};
|
||||||
use super::l2c::*;
|
use super::l2c::*;
|
||||||
|
use core::arch::asm;
|
||||||
|
|
||||||
/// Invalidate TLBs
|
/// Invalidate TLBs
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn tlbiall() {
|
pub fn tlbiall() {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm_asm!("mcr p15, 0, $0, c8, c7, 0" :: "r" (0) :: "volatile");
|
asm!("mcr p15, 0, {}, c8, c7, 0", in(reg) 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +14,7 @@ pub fn tlbiall() {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn iciallu() {
|
pub fn iciallu() {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm_asm!("mcr p15, 0, $0, c7, c5, 0" :: "r" (0) :: "volatile");
|
asm!("mcr p15, 0, {}, c7, c5, 0", in(reg) 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ pub fn iciallu() {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn bpiall() {
|
pub fn bpiall() {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm_asm!("mcr p15, 0, $0, c7, c5, 6" :: "r" (0) :: "volatile");
|
asm!("mcr p15, 0, {}, c7, c5, 6", in(reg) 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +30,7 @@ pub fn bpiall() {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn dccsw(setway: u32) {
|
pub fn dccsw(setway: u32) {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm_asm!("mcr p15, 0, $0, c7, c10, 2" :: "r" (setway) :: "volatile");
|
asm!("mcr p15, 0, {}, c7, c10, 2", in(reg) setway);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ pub fn dcisw(setway: u32) {
|
||||||
// also see example code (for DCCISW, but DCISW will be
|
// also see example code (for DCCISW, but DCISW will be
|
||||||
// analogous) "Example code for cache maintenance operations"
|
// analogous) "Example code for cache maintenance operations"
|
||||||
// on pages B2-1286 and B2-1287.
|
// on pages B2-1286 and B2-1287.
|
||||||
llvm_asm!("mcr p15, 0, $0, c7, c6, 2" :: "r" (setway) :: "volatile");
|
asm!("mcr p15, 0, {}, c7, c6, 2", in(reg) setway);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ pub fn dcisw(setway: u32) {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn dccisw(setway: u32) {
|
pub fn dccisw(setway: u32) {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm_asm!("mcr p15, 0, $0, c7, c14, 2" :: "r" (setway) :: "volatile");
|
asm!("mcr p15, 0, {}, c7, c14, 2", in(reg) setway);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +70,7 @@ pub fn dciall_l1() {
|
||||||
|
|
||||||
// select L1 data cache
|
// select L1 data cache
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm_asm!("mcr p15, 2, $0, c0, c0, 0" :: "r" (0) :: "volatile");
|
asm!("mcr p15, 2, {}, c0, c0, 0", in(reg) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalidate entire D-Cache by iterating every set and every way
|
// Invalidate entire D-Cache by iterating every set and every way
|
||||||
|
@ -104,7 +105,7 @@ pub fn dcciall_l1() {
|
||||||
|
|
||||||
// select L1 data cache
|
// select L1 data cache
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm_asm!("mcr p15, 2, $0, c0, c0, 0" :: "r" (0) :: "volatile");
|
asm!("mcr p15, 2, {}, c0, c0, 0", in(reg) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalidate entire D-Cache by iterating every set and every way
|
// Invalidate entire D-Cache by iterating every set and every way
|
||||||
|
@ -156,7 +157,7 @@ fn slice_cache_line_addrs<T>(slice: &[T]) -> impl Iterator<Item = usize> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn dccimvac(addr: usize) {
|
pub fn dccimvac(addr: usize) {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm_asm!("mcr p15, 0, $0, c7, c14, 1" :: "r" (addr) :: "volatile");
|
asm!("mcr p15, 0, {}, c7, c14, 1", in(reg) addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,10 +199,9 @@ pub fn dcci_slice<T>(slice: &[T]) {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn dccmvac(addr: usize) {
|
pub fn dccmvac(addr: usize) {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm_asm!("mcr p15, 0, $0, c7, c10, 1" :: "r" (addr) :: "volatile");
|
asm!("mcr p15, 0, {}, c7, c10, 1", in(reg) addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data cache clean for an object.
|
/// Data cache clean for an object.
|
||||||
pub fn dcc<T>(object: &T) {
|
pub fn dcc<T>(object: &T) {
|
||||||
dmb();
|
dmb();
|
||||||
|
@ -239,7 +239,7 @@ pub fn dcc_slice<T>(slice: &[T]) {
|
||||||
/// affecting more data than intended.
|
/// affecting more data than intended.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn dcimvac(addr: usize) {
|
pub unsafe fn dcimvac(addr: usize) {
|
||||||
llvm_asm!("mcr p15, 0, $0, c7, c6, 1" :: "r" (addr) :: "volatile");
|
asm!("mcr p15, 0, {}, c7, c6, 1", in(reg) addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data cache clean and invalidate for an object.
|
/// Data cache clean and invalidate for an object.
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
use core::arch::asm;
|
||||||
/// Enable FPU in the current core.
|
/// Enable FPU in the current core.
|
||||||
pub fn enable_fpu() {
|
pub fn enable_fpu() {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm_asm!("
|
asm!("
|
||||||
mrc p15, 0, r1, c1, c0, 2
|
mrc p15, 0, r1, c1, c0, 2
|
||||||
orr r1, r1, (0b1111<<20)
|
orr r1, r1, (0b1111<<20)
|
||||||
mcr p15, 0, r1, c1, c0, 2
|
mcr p15, 0, r1, c1, c0, 2
|
||||||
|
@ -9,6 +10,6 @@ pub fn enable_fpu() {
|
||||||
vmrs r1, fpexc
|
vmrs r1, fpexc
|
||||||
orr r1, r1, (1<<30)
|
orr r1, r1, (1<<30)
|
||||||
vmsr fpexc, r1
|
vmsr fpexc, r1
|
||||||
":::"r1");
|
", out("r1") _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![feature(llvm_asm, global_asm)]
|
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(const_fn)]
|
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
|
@ -17,6 +15,7 @@ pub mod sync_channel;
|
||||||
mod uncached;
|
mod uncached;
|
||||||
pub use fpu::enable_fpu;
|
pub use fpu::enable_fpu;
|
||||||
pub use uncached::UncachedSlice;
|
pub use uncached::UncachedSlice;
|
||||||
|
use core::arch::global_asm;
|
||||||
|
|
||||||
global_asm!(include_str!("exceptions.s"));
|
global_asm!(include_str!("exceptions.s"));
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ use libregister::{
|
||||||
register_bit, register_bits,
|
register_bit, register_bits,
|
||||||
RegisterR, RegisterW, RegisterRW,
|
RegisterR, RegisterW, RegisterRW,
|
||||||
};
|
};
|
||||||
|
use core::arch::asm;
|
||||||
|
|
||||||
macro_rules! def_reg_r {
|
macro_rules! def_reg_r {
|
||||||
($name:tt, $type: ty, $asm_instr:tt) => {
|
($name:tt, $type: ty, $asm_instr:tt) => {
|
||||||
|
@ -11,7 +12,7 @@ macro_rules! def_reg_r {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read(&self) -> Self::R {
|
fn read(&self) -> Self::R {
|
||||||
let mut value: u32;
|
let mut value: u32;
|
||||||
unsafe { llvm_asm!($asm_instr : "=r" (value) ::: "volatile") }
|
unsafe { asm!($asm_instr, lateout(reg) value) }
|
||||||
value.into()
|
value.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +27,7 @@ macro_rules! def_reg_w {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn write(&mut self, value: Self::W) {
|
fn write(&mut self, value: Self::W) {
|
||||||
let value: u32 = value.into();
|
let value: u32 = value.into();
|
||||||
unsafe { llvm_asm!($asm_instr :: "r" (value) :: "volatile") }
|
unsafe { asm!($asm_instr, in(reg) value) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -71,29 +72,29 @@ macro_rules! wrap_reg {
|
||||||
|
|
||||||
/// Stack Pointer
|
/// Stack Pointer
|
||||||
pub struct SP;
|
pub struct SP;
|
||||||
def_reg_r!(SP, u32, "mov $0, sp");
|
def_reg_r!(SP, u32, "mov {}, sp");
|
||||||
def_reg_w!(SP, u32, "mov sp, $0");
|
def_reg_w!(SP, u32, "mov sp, {}");
|
||||||
|
|
||||||
/// Link register (function call return address)
|
/// Link register (function call return address)
|
||||||
pub struct LR;
|
pub struct LR;
|
||||||
def_reg_r!(LR, u32, "mov $0, lr");
|
def_reg_r!(LR, u32, "mov {}, lr");
|
||||||
def_reg_w!(LR, u32, "mov lr, $0");
|
def_reg_w!(LR, u32, "mov lr, {}");
|
||||||
|
|
||||||
pub struct VBAR;
|
pub struct VBAR;
|
||||||
def_reg_r!(VBAR, u32, "mrc p15, 0, $0, c12, c0, 0");
|
def_reg_r!(VBAR, u32, "mrc p15, 0, {}, c12, c0, 0");
|
||||||
def_reg_w!(VBAR, u32, "mcr p15, 0, $0, c12, c0, 0");
|
def_reg_w!(VBAR, u32, "mcr p15, 0, {}, c12, c0, 0");
|
||||||
|
|
||||||
pub struct MVBAR;
|
pub struct MVBAR;
|
||||||
def_reg_r!(MVBAR, u32, "mrc p15, 0, $0, c12, c0, 1");
|
def_reg_r!(MVBAR, u32, "mrc p15, 0, {}, c12, c0, 1");
|
||||||
def_reg_w!(MVBAR, u32, "mcr p15, 0, $0, c12, c0, 1");
|
def_reg_w!(MVBAR, u32, "mcr p15, 0, {}, c12, c0, 1");
|
||||||
|
|
||||||
pub struct HVBAR;
|
pub struct HVBAR;
|
||||||
def_reg_r!(HVBAR, u32, "mrc p15, 4, $0, c12, c0, 0");
|
def_reg_r!(HVBAR, u32, "mrc p15, 4, {}, c12, c0, 0");
|
||||||
def_reg_w!(HVBAR, u32, "mcr p15, 4, $0, c12, c0, 0");
|
def_reg_w!(HVBAR, u32, "mcr p15, 4, {}, c12, c0, 0");
|
||||||
|
|
||||||
/// Multiprocess Affinity Register
|
/// Multiprocess Affinity Register
|
||||||
pub struct MPIDR;
|
pub struct MPIDR;
|
||||||
def_reg_r!(MPIDR, mpidr::Read, "mrc p15, 0, $0, c0, c0, 5");
|
def_reg_r!(MPIDR, mpidr::Read, "mrc p15, 0, {}, c0, c0, 5");
|
||||||
wrap_reg!(mpidr);
|
wrap_reg!(mpidr);
|
||||||
register_bits!(mpidr,
|
register_bits!(mpidr,
|
||||||
/// CPU core index
|
/// CPU core index
|
||||||
|
@ -106,15 +107,15 @@ register_bit!(mpidr,
|
||||||
u, 30);
|
u, 30);
|
||||||
|
|
||||||
pub struct DFAR;
|
pub struct DFAR;
|
||||||
def_reg_r!(DFAR, u32, "mrc p15, 0, $0, c6, c0, 0");
|
def_reg_r!(DFAR, u32, "mrc p15, 0, {}, c6, c0, 0");
|
||||||
|
|
||||||
pub struct DFSR;
|
pub struct DFSR;
|
||||||
def_reg_r!(DFSR, u32, "mrc p15, 0, $0, c5, c0, 0");
|
def_reg_r!(DFSR, u32, "mrc p15, 0, {}, c5, c0, 0");
|
||||||
|
|
||||||
pub struct SCTLR;
|
pub struct SCTLR;
|
||||||
wrap_reg!(sctlr);
|
wrap_reg!(sctlr);
|
||||||
def_reg_r!(SCTLR, sctlr::Read, "mrc p15, 0, $0, c1, c0, 0");
|
def_reg_r!(SCTLR, sctlr::Read, "mrc p15, 0, {}, c1, c0, 0");
|
||||||
def_reg_w!(SCTLR, sctlr::Write, "mcr p15, 0, $0, c1, c0, 0");
|
def_reg_w!(SCTLR, sctlr::Write, "mcr p15, 0, {}, c1, c0, 0");
|
||||||
register_bit!(sctlr,
|
register_bit!(sctlr,
|
||||||
/// Enables MMU
|
/// Enables MMU
|
||||||
m, 0);
|
m, 0);
|
||||||
|
@ -147,8 +148,8 @@ register_bit!(sctlr,
|
||||||
/// Auxiliary Control Register
|
/// Auxiliary Control Register
|
||||||
pub struct ACTLR;
|
pub struct ACTLR;
|
||||||
wrap_reg!(actlr);
|
wrap_reg!(actlr);
|
||||||
def_reg_r!(ACTLR, actlr::Read, "mrc p15, 0, $0, c1, c0, 1");
|
def_reg_r!(ACTLR, actlr::Read, "mrc p15, 0, {}, c1, c0, 1");
|
||||||
def_reg_w!(ACTLR, actlr::Write, "mcr p15, 0, $0, c1, c0, 1");
|
def_reg_w!(ACTLR, actlr::Write, "mcr p15, 0, {}, c1, c0, 1");
|
||||||
// SMP bit
|
// SMP bit
|
||||||
register_bit!(actlr, parity_on, 9);
|
register_bit!(actlr, parity_on, 9);
|
||||||
register_bit!(actlr, alloc_one_way, 8);
|
register_bit!(actlr, alloc_one_way, 8);
|
||||||
|
@ -183,17 +184,17 @@ impl ACTLR {
|
||||||
|
|
||||||
/// Domain Access Control Register
|
/// Domain Access Control Register
|
||||||
pub struct DACR;
|
pub struct DACR;
|
||||||
def_reg_r!(DACR, u32, "mrc p15, 0, $0, c3, c0, 0");
|
def_reg_r!(DACR, u32, "mrc p15, 0, {}, c3, c0, 0");
|
||||||
def_reg_w!(DACR, u32, "mcr p15, 0, $0, c3, c0, 0");
|
def_reg_w!(DACR, u32, "mcr p15, 0, {}, c3, c0, 0");
|
||||||
|
|
||||||
/// Translation Table Base Register 0
|
/// Translation Table Base Register 0
|
||||||
pub struct TTBR0;
|
pub struct TTBR0;
|
||||||
/// Translation Table Base Register 1
|
/// Translation Table Base Register 1
|
||||||
pub struct TTBR1;
|
pub struct TTBR1;
|
||||||
def_reg_r!(TTBR0, ttbr::Read, "mrc p15, 0, $0, c2, c0, 0");
|
def_reg_r!(TTBR0, ttbr::Read, "mrc p15, 0, {}, c2, c0, 0");
|
||||||
def_reg_w!(TTBR0, ttbr::Write, "mcr p15, 0, $0, c2, c0, 0");
|
def_reg_w!(TTBR0, ttbr::Write, "mcr p15, 0, {}, c2, c0, 0");
|
||||||
def_reg_r!(TTBR1, ttbr::Read, "mrc p15, 0, $0, c2, c0, 1");
|
def_reg_r!(TTBR1, ttbr::Read, "mrc p15, 0, {}, c2, c0, 1");
|
||||||
def_reg_w!(TTBR1, ttbr::Write, "mcr p15, 0, $0, c2, c0, 1");
|
def_reg_w!(TTBR1, ttbr::Write, "mcr p15, 0, {}, c2, c0, 1");
|
||||||
wrap_reg!(ttbr);
|
wrap_reg!(ttbr);
|
||||||
register_bits!(ttbr, table_base, u32, 14, 31);
|
register_bits!(ttbr, table_base, u32, 14, 31);
|
||||||
register_bit!(ttbr, irgn0, 6);
|
register_bit!(ttbr, irgn0, 6);
|
||||||
|
|
|
@ -172,13 +172,12 @@ impl<'a, T> Iterator for Receiver<'a, T> where T: Clone {
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
/// Macro for initializing the sync_channel with static buffer and indexes.
|
/// Macro for initializing the sync_channel with static buffer and indexes.
|
||||||
/// Note that this requires `#![feature(const_in_array_repeat_expressions)]`
|
|
||||||
macro_rules! sync_channel {
|
macro_rules! sync_channel {
|
||||||
($t: ty, $cap: expr) => {
|
($t: ty, $cap: expr) => {
|
||||||
{
|
{
|
||||||
use core::sync::atomic::{AtomicUsize, AtomicPtr};
|
use core::sync::atomic::{AtomicUsize, AtomicPtr};
|
||||||
use $crate::sync_channel::{Sender, Receiver};
|
use $crate::sync_channel::{Sender, Receiver};
|
||||||
static LIST: [AtomicPtr<$t>; $cap + 1] = [AtomicPtr::new(core::ptr::null_mut()); $cap + 1];
|
static LIST: [AtomicPtr<$t>; $cap + 1] = [const { AtomicPtr::new(core::ptr::null_mut()) }; $cap + 1];
|
||||||
static WRITE: AtomicUsize = AtomicUsize::new(0);
|
static WRITE: AtomicUsize = AtomicUsize::new(0);
|
||||||
static READ: AtomicUsize = AtomicUsize::new(0);
|
static READ: AtomicUsize = AtomicUsize::new(0);
|
||||||
(Sender::new(&LIST, &WRITE, &READ), Receiver::new(&LIST, &WRITE, &READ))
|
(Sender::new(&LIST, &WRITE, &READ), Receiver::new(&LIST, &WRITE, &READ))
|
||||||
|
|
|
@ -33,8 +33,6 @@ impl<T> UncachedSlice<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let slice = unsafe { core::slice::from_raw_parts_mut(ptr, len) };
|
let slice = unsafe { core::slice::from_raw_parts_mut(ptr, len) };
|
||||||
// verify size
|
|
||||||
assert!(unsafe { slice.get_unchecked(len) } as *const _ as usize <= start + size);
|
|
||||||
// initialize
|
// initialize
|
||||||
for e in slice.iter_mut() {
|
for e in slice.iter_mut() {
|
||||||
*e = default();
|
*e = default();
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
name = "libregister"
|
name = "libregister"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
authors = ["M-Labs"]
|
authors = ["M-Labs"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
vcell = "0.1"
|
vcell = "0.1"
|
||||||
|
|
|
@ -3,11 +3,12 @@ name = "libsupport_zynq"
|
||||||
description = "Software support for running in the Zynq PS"
|
description = "Software support for running in the Zynq PS"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
authors = ["M-Labs"]
|
authors = ["M-Labs"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
target_zc706 = ["libboard_zynq/target_zc706"]
|
target_zc706 = ["libboard_zynq/target_zc706"]
|
||||||
target_coraz7 = ["libboard_zynq/target_coraz7"]
|
target_coraz7 = ["libboard_zynq/target_coraz7"]
|
||||||
|
target_ebaz4205 = ["libboard_zynq/target_ebaz4205"]
|
||||||
target_redpitaya = ["libboard_zynq/target_redpitaya"]
|
target_redpitaya = ["libboard_zynq/target_redpitaya"]
|
||||||
target_kasli_soc = ["libboard_zynq/target_kasli_soc"]
|
target_kasli_soc = ["libboard_zynq/target_kasli_soc"]
|
||||||
panic_handler = []
|
panic_handler = []
|
||||||
|
@ -19,7 +20,7 @@ default = ["panic_handler", "dummy_irq_handler", "dummy_fiq_handler"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
r0 = "1"
|
r0 = "1"
|
||||||
compiler_builtins = "=0.1.39"
|
compiler_builtins = "=0.1.109"
|
||||||
linked_list_allocator = { version = "0.8", default-features = false, features = ["const_mut_refs"] }
|
linked_list_allocator = { version = "0.8", default-features = false, features = ["const_mut_refs"] }
|
||||||
libregister = { path = "../libregister" }
|
libregister = { path = "../libregister" }
|
||||||
libcortex_a9 = { path = "../libcortex_a9" }
|
libcortex_a9 = { path = "../libcortex_a9" }
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use r0::zero_bss;
|
use r0::zero_bss;
|
||||||
use core::ptr::write_volatile;
|
use core::ptr::write_volatile;
|
||||||
|
use core::arch::asm;
|
||||||
use libregister::{
|
use libregister::{
|
||||||
VolatileCell,
|
VolatileCell,
|
||||||
RegisterR, RegisterRW,
|
RegisterR, RegisterRW,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use libregister::{RegisterR, RegisterW};
|
use libregister::{RegisterR, RegisterW};
|
||||||
use libcortex_a9::{regs::{DFSR, MPIDR, VBAR}, interrupt_handler};
|
use libcortex_a9::{regs::{DFSR, MPIDR, VBAR}, interrupt_handler};
|
||||||
use libboard_zynq::{println, stdio};
|
use libboard_zynq::{println, stdio};
|
||||||
|
use core::arch::asm;
|
||||||
|
|
||||||
pub fn set_vector_table(base_addr: u32){
|
pub fn set_vector_table(base_addr: u32){
|
||||||
VBAR.write(base_addr);
|
VBAR.write(base_addr);
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#![feature(alloc_error_handler)]
|
#![feature(alloc_error_handler)]
|
||||||
#![feature(panic_info_message)]
|
|
||||||
#![feature(naked_functions)]
|
#![feature(naked_functions)]
|
||||||
#![feature(asm)]
|
|
||||||
|
|
||||||
pub extern crate alloc;
|
pub extern crate alloc;
|
||||||
pub extern crate compiler_builtins;
|
pub extern crate compiler_builtins;
|
||||||
|
|
|
@ -10,7 +10,7 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
|
||||||
} else {
|
} else {
|
||||||
print!("unknown location");
|
print!("unknown location");
|
||||||
}
|
}
|
||||||
if let Some(message) = info.message() {
|
if let Some(message) = info.message().as_str() {
|
||||||
println!(": {}", message);
|
println!(": {}", message);
|
||||||
} else {
|
} else {
|
||||||
println!("");
|
println!("");
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
# The contents of this file are partially dependend on
|
||||||
|
# the adapter that you have. Please modify accordingly.
|
||||||
|
adapter driver ftdi
|
||||||
|
ftdi vid_pid 0x0403 0x6010
|
||||||
|
ftdi channel 0
|
||||||
|
# Every pin set as high impedance except TCK, TDI, TDO and TMS
|
||||||
|
ftdi layout_init 0x0088 0x008b
|
||||||
|
|
||||||
|
# nSRST defined on pin CN2-13 of the MiniModule (pin ADBUS5 [AD5] on the FT2232H chip)
|
||||||
|
# This choice is arbitrary. Use other GPIO pin if desired.
|
||||||
|
ftdi layout_signal nSRST -data 0x0020 -oe 0x0020
|
||||||
|
|
||||||
|
transport select jtag
|
||||||
|
adapter speed 10000
|
||||||
|
|
||||||
|
set PL_TAPID 0x13722093
|
||||||
|
set SMP 1
|
||||||
|
|
||||||
|
source ./zynq-7000.cfg
|
||||||
|
|
||||||
|
reset_config srst_only srst_open_drain
|
||||||
|
adapter srst pulse_width 250
|
||||||
|
adapter srst delay 400
|
||||||
|
|
||||||
|
source ./common.cfg
|
||||||
|
|
||||||
|
reset halt
|
||||||
|
|
||||||
|
# Disable MMU
|
||||||
|
targets $_TARGETNAME_1
|
||||||
|
arm mcr 15 0 1 0 0 [expr { [arm mrc 15 0 1 0 0] & ~0xd }]
|
||||||
|
targets $_TARGETNAME_0
|
||||||
|
arm mcr 15 0 1 0 0 [expr { [arm mrc 15 0 1 0 0] & ~0xd }]
|
|
@ -3,11 +3,12 @@ name = "szl"
|
||||||
description = "Simple Zynq Loader"
|
description = "Simple Zynq Loader"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["M-Labs"]
|
authors = ["M-Labs"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
target_zc706 = ["libboard_zynq/target_zc706", "libsupport_zynq/target_zc706", "libconfig/target_zc706"]
|
target_zc706 = ["libboard_zynq/target_zc706", "libsupport_zynq/target_zc706", "libconfig/target_zc706"]
|
||||||
target_coraz7 = ["libboard_zynq/target_coraz7", "libsupport_zynq/target_coraz7", "libconfig/target_coraz7"]
|
target_coraz7 = ["libboard_zynq/target_coraz7", "libsupport_zynq/target_coraz7", "libconfig/target_coraz7"]
|
||||||
|
target_ebaz4205 = ["libboard_zynq/target_ebaz4205", "libsupport_zynq/target_ebaz4205", "libconfig/target_ebaz4205"]
|
||||||
target_redpitaya = ["libboard_zynq/target_redpitaya", "libsupport_zynq/target_redpitaya", "libconfig/target_redpitaya"]
|
target_redpitaya = ["libboard_zynq/target_redpitaya", "libsupport_zynq/target_redpitaya", "libconfig/target_redpitaya"]
|
||||||
target_kasli_soc = ["libboard_zynq/target_kasli_soc", "libsupport_zynq/target_kasli_soc", "libconfig/target_kasli_soc"]
|
target_kasli_soc = ["libboard_zynq/target_kasli_soc", "libsupport_zynq/target_kasli_soc", "libconfig/target_kasli_soc"]
|
||||||
default = ["target_zc706"]
|
default = ["target_zc706"]
|
||||||
|
@ -15,10 +16,15 @@ default = ["target_zc706"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
byteorder = { version = "1.3", default-features = false }
|
byteorder = { version = "1.3", default-features = false }
|
||||||
core_io = { version = "0.1", features = ["collections"] }
|
|
||||||
|
|
||||||
libboard_zynq = { path = "../libboard_zynq" }
|
libboard_zynq = { path = "../libboard_zynq" }
|
||||||
libsupport_zynq = { path = "../libsupport_zynq" }
|
libsupport_zynq = { path = "../libsupport_zynq" }
|
||||||
libcortex_a9 = { path = "../libcortex_a9" }
|
libcortex_a9 = { path = "../libcortex_a9" }
|
||||||
libregister = { path = "../libregister" }
|
libregister = { path = "../libregister" }
|
||||||
libconfig = { path = "../libconfig" }
|
libconfig = { path = "../libconfig" }
|
||||||
|
|
||||||
|
[dependencies.fatfs]
|
||||||
|
git = "https://github.com/rafalh/rust-fatfs"
|
||||||
|
rev = "85f06e0"
|
||||||
|
default-features = false
|
||||||
|
features = ["alloc", "lfn"]
|
||||||
|
|
|
@ -8,7 +8,6 @@ mod netboot;
|
||||||
|
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use core_io::{Read, Seek};
|
|
||||||
use libboard_zynq::{
|
use libboard_zynq::{
|
||||||
self as zynq,
|
self as zynq,
|
||||||
clocks::source::{ArmPll, ClockSource, IoPll},
|
clocks::source::{ArmPll, ClockSource, IoPll},
|
||||||
|
@ -16,7 +15,7 @@ use libboard_zynq::{
|
||||||
logger, println, sdio, slcr,
|
logger, println, sdio, slcr,
|
||||||
timer::GlobalTimer,
|
timer::GlobalTimer,
|
||||||
};
|
};
|
||||||
use libconfig::{bootgen, sd_reader, Config};
|
use libconfig::{bootgen, sd_reader, Config, File};
|
||||||
use libcortex_a9::{
|
use libcortex_a9::{
|
||||||
asm::{dsb, isb},
|
asm::{dsb, isb},
|
||||||
cache::{bpiall, dcciall, iciallu},
|
cache::{bpiall, dcciall, iciallu},
|
||||||
|
@ -30,8 +29,8 @@ extern "C" {
|
||||||
static mut __runtime_end: usize;
|
static mut __runtime_end: usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn boot_sd<File: Read + Seek>(
|
fn boot_sd<'a>(
|
||||||
file: &mut Option<File>,
|
file: &mut Option<File<'a>>,
|
||||||
runtime_start: *mut u8,
|
runtime_start: *mut u8,
|
||||||
runtime_max: usize,
|
runtime_max: usize,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ()> {
|
||||||
|
@ -80,12 +79,15 @@ pub fn main_core0() {
|
||||||
);
|
);
|
||||||
info!("Simple Zynq Loader starting...");
|
info!("Simple Zynq Loader starting...");
|
||||||
|
|
||||||
#[cfg(not(feature = "target_kasli_soc"))]
|
#[cfg(not(any(feature = "target_kasli_soc", feature = "target_ebaz4205")))]
|
||||||
const CPU_FREQ: u32 = 800_000_000;
|
const CPU_FREQ: u32 = 800_000_000;
|
||||||
|
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
const CPU_FREQ: u32 = 1_000_000_000;
|
const CPU_FREQ: u32 = 1_000_000_000;
|
||||||
|
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
const CPU_FREQ: u32 = 666_666_666;
|
||||||
|
|
||||||
ArmPll::setup(2 * CPU_FREQ);
|
ArmPll::setup(2 * CPU_FREQ);
|
||||||
Clocks::set_cpu_freq(CPU_FREQ);
|
Clocks::set_cpu_freq(CPU_FREQ);
|
||||||
IoPll::setup(1_000_000_000);
|
IoPll::setup(1_000_000_000);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use byteorder::{ByteOrder, NetworkEndian};
|
use byteorder::{ByteOrder, NetworkEndian};
|
||||||
use core_io::{Read, Seek};
|
|
||||||
use libboard_zynq::{
|
use libboard_zynq::{
|
||||||
devc,
|
devc,
|
||||||
eth::Eth,
|
eth::Eth,
|
||||||
|
@ -13,7 +12,7 @@ use libboard_zynq::{
|
||||||
},
|
},
|
||||||
timer::GlobalTimer,
|
timer::GlobalTimer,
|
||||||
};
|
};
|
||||||
use libconfig::{bootgen, net_settings, Config};
|
use libconfig::{bootgen, net_settings, Config, File};
|
||||||
|
|
||||||
enum NetConnState {
|
enum NetConnState {
|
||||||
WaitCommand,
|
WaitCommand,
|
||||||
|
@ -48,7 +47,7 @@ impl NetConn {
|
||||||
self.gateware_downloaded = false;
|
self.gateware_downloaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn input_partial<File: Read + Seek>(
|
fn input_partial(
|
||||||
&mut self,
|
&mut self,
|
||||||
bootgen_file: &mut Option<File>,
|
bootgen_file: &mut Option<File>,
|
||||||
runtime_start: *mut u8,
|
runtime_start: *mut u8,
|
||||||
|
@ -284,9 +283,9 @@ impl NetConn {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn input<File: Read + Seek>(
|
fn input<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
bootgen_file: &mut Option<File>,
|
bootgen_file: &mut Option<File<'a>>,
|
||||||
runtime_start: *mut u8,
|
runtime_start: *mut u8,
|
||||||
runtime_max_len: usize,
|
runtime_max_len: usize,
|
||||||
buf: &[u8],
|
buf: &[u8],
|
||||||
|
@ -309,8 +308,8 @@ impl NetConn {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn netboot<File: Read + Seek>(
|
pub fn netboot<'a>(
|
||||||
bootgen_file: &mut Option<File>,
|
bootgen_file: &mut Option<File<'a>>,
|
||||||
cfg: Config,
|
cfg: Config,
|
||||||
runtime_start: *mut u8,
|
runtime_start: *mut u8,
|
||||||
runtime_max_len: usize,
|
runtime_max_len: usize,
|
||||||
|
|
Loading…
Reference in New Issue