forked from M-Labs/zynq-rs
Compare commits
23 Commits
e1b3312b8b
...
7a8df6e34f
Author | SHA1 | Date |
---|---|---|
Simon Renblad | 7a8df6e34f | |
Simon Renblad | f975183df5 | |
Simon Renblad | e05208ce70 | |
Simon Renblad | a0d807b55c | |
Simon Renblad | 09b1288872 | |
Simon Renblad | 916c72237b | |
Simon Renblad | 9a413c5a96 | |
Simon Renblad | b390222508 | |
Simon Renblad | 61f6355a73 | |
Simon Renblad | 0c5b0476ab | |
Simon Renblad | 0d2bbed9a0 | |
Simon Renblad | 00e625c802 | |
Simon Renblad | 42005a614e | |
Simon Renblad | c7a3197977 | |
Simon Renblad | ffb24e133b | |
Simon Renblad | f01a69df18 | |
Simon Renblad | fbf9dff15c | |
Simon Renblad | fd46cb9c8b | |
Simon Renblad | 259c0fe842 | |
Simon Renblad | e85263eff7 | |
Simon Renblad | 4736f7592b | |
Simon Renblad | e51af90ba4 | |
Simon Renblad | 2c70fdbeab |
|
@ -1,7 +1,7 @@
|
|||
[target.armv7-none-eabihf]
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
"-C", "target-feature=a9,armv7-a,neon",
|
||||
"-C", "target-feature=+a9,+armv7-a,+neon",
|
||||
"-C", "target-cpu=cortex-a9",
|
||||
]
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
version = "0.10.1"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
|
||||
checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
|
@ -13,37 +15,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
name = "bitflags"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.73"
|
||||
version = "1.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
checksum = "812acba72f0a070b003d3697490d2b55b837230ae7c6c6497f05cc2ddbb8d938"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.39"
|
||||
version = "0.1.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3748f82c7d366a0b4950257d19db685d4958d2fa27c6d164a3f069fec42b748b"
|
||||
|
||||
[[package]]
|
||||
name = "core_io"
|
||||
version = "0.1.20210325"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97f8932064288cc79feb4d343a399d353a6f6f001e586ece47fe518a9e8507df"
|
||||
dependencies = [
|
||||
"rustc_version",
|
||||
]
|
||||
checksum = "f11973008a8cf741fe6d22f339eba21fd0ca81e2760a769ba8243ed6c21edd7e"
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal"
|
||||
|
@ -70,13 +66,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "fatfs"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e18f80a87439240dac45d927fd8f8081b6f1e34c03e97271189fa8a8c2e96c8f"
|
||||
version = "0.4.0"
|
||||
source = "git+https://github.com/rafalh/rust-fatfs?rev=85f06e0#85f06e08edbd3368e1b0562f2fc1b6d178bf7b8a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"core_io",
|
||||
"bitflags 2.6.0",
|
||||
"log",
|
||||
]
|
||||
|
||||
|
@ -86,7 +79,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"embedded-hal",
|
||||
"libcortex_a9",
|
||||
"nb 1.0.0",
|
||||
"nb 1.1.0",
|
||||
"pin-utils",
|
||||
"smoltcp",
|
||||
]
|
||||
|
@ -111,7 +104,6 @@ dependencies = [
|
|||
name = "libconfig"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"core_io",
|
||||
"fatfs",
|
||||
"libboard_zynq",
|
||||
"log",
|
||||
|
@ -156,12 +148,9 @@ checksum = "822add9edb1860698b79522510da17bef885171f75aa395cff099d770c609c24"
|
|||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.14"
|
||||
version = "0.4.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||
|
||||
[[package]]
|
||||
name = "managed"
|
||||
|
@ -175,14 +164,14 @@ version = "0.1.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
|
||||
dependencies = [
|
||||
"nb 1.0.0",
|
||||
"nb 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nb"
|
||||
version = "1.0.0"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae"
|
||||
checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
|
@ -197,19 +186,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.1.7"
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
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"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "smoltcp"
|
||||
|
@ -217,7 +197,7 @@ version = "0.7.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e4a069bef843d170df47e7c0a8bf8d037f217d9f5b325865acc3e466ffe40d3"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 1.3.2",
|
||||
"byteorder",
|
||||
"managed",
|
||||
]
|
||||
|
@ -227,7 +207,7 @@ name = "szl"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"core_io",
|
||||
"fatfs",
|
||||
"libboard_zynq",
|
||||
"libconfig",
|
||||
"libcortex_a9",
|
||||
|
@ -250,9 +230,9 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
|||
|
||||
[[package]]
|
||||
name = "volatile-register"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6"
|
||||
checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc"
|
||||
dependencies = [
|
||||
"vcell",
|
||||
]
|
||||
|
|
|
@ -9,6 +9,7 @@ members = [
|
|||
"experiments",
|
||||
"szl",
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
|
|
|
@ -3,7 +3,7 @@ name = "experiments"
|
|||
description = "Developing bare-metal Rust on Zynq"
|
||||
version = "0.0.0"
|
||||
authors = ["M-Labs"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
target_zc706 = ["libboard_zynq/target_zc706", "libsupport_zynq/target_zc706"]
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(const_in_array_repeat_expressions)]
|
||||
#![feature(naked_functions)]
|
||||
#![feature(asm)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::collections::BTreeMap;
|
||||
use core::arch::asm;
|
||||
use core::ptr::addr_of_mut;
|
||||
use libasync::{
|
||||
delay,
|
||||
smoltcp::{Sockets, TcpStream},
|
||||
|
@ -71,7 +71,7 @@ interrupt_handler!(IRQ, irq, __irq_stack0_start, __irq_stack1_start, {
|
|||
if id.0 == 0 {
|
||||
gic.end_interrupt(id);
|
||||
asm::exit_irq();
|
||||
SP.write(&mut __stack1_start as *mut _ as u32);
|
||||
SP.write(addr_of_mut!(__stack1_start) as *mut _ as u32);
|
||||
asm::enable_irq();
|
||||
CORE1_RESTART.store(false, Ordering::Relaxed);
|
||||
notify_spin_lock();
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1727540905,
|
||||
"narHash": "sha256-40J9tW7Y794J7Uw4GwcAKlMxlX2xISBl6IBigo83ih8=",
|
||||
"lastModified": 1727907660,
|
||||
"narHash": "sha256-QftbyPoieM5M50WKUMzQmWtBWib/ZJbHo7mhj5riQec=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "fbca5e745367ae7632731639de5c21f29c8744ed",
|
||||
"rev": "5966581aa04be7eff830b9e1457d56dc70a0b798",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
15
flake.nix
15
flake.nix
|
@ -9,8 +9,8 @@
|
|||
pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ (import mozilla-overlay) crosspkgs-overlay ]; };
|
||||
|
||||
rustManifest = pkgs.fetchurl {
|
||||
url = "https://static.rust-lang.org/dist/2021-01-29/channel-rust-nightly.toml";
|
||||
sha256 = "sha256-EZKgw89AH4vxaJpUHmIMzMW/80wAFQlfcxRoBD9nz0c=";
|
||||
url = "https://static.rust-lang.org/dist/2024-07-19/channel-rust-nightly.toml";
|
||||
sha256 = "sha256-MM2K43Kg+f83XQXT2lI7W/ZdQjLXhMUvA6eGtD+rqDY=";
|
||||
};
|
||||
rustTargets = [];
|
||||
rustChannelOfTargets = _channel: _date: targets:
|
||||
|
@ -104,9 +104,7 @@
|
|||
dontFixup = true;
|
||||
};
|
||||
|
||||
cargo-xbuild = pkgs.cargo-xbuild.overrideAttrs(oa: {
|
||||
postPatch = "substituteInPlace src/sysroot.rs --replace 2021 2018";
|
||||
});
|
||||
cargo-xbuild = pkgs.cargo-xbuild;
|
||||
|
||||
build-crate = name: crate: features: rustPlatform.buildRustPackage rec {
|
||||
name = "${crate}";
|
||||
|
@ -114,7 +112,12 @@
|
|||
src = builtins.filterSource (path: type:
|
||||
baseNameOf path != "target"
|
||||
) ./.;
|
||||
cargoLock = { lockFile = ./Cargo.lock; };
|
||||
cargoLock = {
|
||||
lockFile = ./Cargo.lock;
|
||||
outputHashes = {
|
||||
"fatfs-0.4.0" = "sha256-P7IgvhwTPXtNhcyv8cFqwO2UdaEcCGJY7UBG6+yBFSg=";
|
||||
};
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ cargo-xbuild llvmPackages_11.clang-unwrapped ];
|
||||
buildPhase = ''
|
||||
|
|
|
@ -3,7 +3,7 @@ name = "libasync"
|
|||
description = "low-level async support"
|
||||
version = "0.0.0"
|
||||
authors = ["M-Labs"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
#futures = { version = "0.3", default-features = false }
|
||||
|
|
|
@ -3,7 +3,7 @@ name = "libboard_zynq"
|
|||
description = "Drivers for peripherals in the Zynq PS"
|
||||
version = "0.0.0"
|
||||
authors = ["M-Labs"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
target_zc706 = []
|
||||
|
|
|
@ -2,14 +2,17 @@
|
|||
name = "libconfig"
|
||||
version = "0.1.0"
|
||||
authors = ["M-Labs"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
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"
|
||||
|
||||
[dependencies.fatfs]
|
||||
git = "https://github.com/rafalh/rust-fatfs"
|
||||
rev = "85f06e0"
|
||||
default-features = false
|
||||
|
||||
[features]
|
||||
target_zc706 = []
|
||||
target_coraz7 = []
|
||||
|
@ -17,4 +20,4 @@ target_ebaz4205 = []
|
|||
target_redpitaya = []
|
||||
target_kasli_soc = []
|
||||
ipv6 = []
|
||||
fat_lfn = [ "fatfs/alloc" ]
|
||||
fat_lfn = [ "fatfs/alloc" ]
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
use alloc::vec::Vec;
|
||||
use core_io::{Error, Read, Seek, SeekFrom};
|
||||
use fatfs::{self, Read, Seek, SeekFrom};
|
||||
use libboard_zynq::devc;
|
||||
use crate::sd_reader;
|
||||
use crate::File;
|
||||
use log::debug;
|
||||
|
||||
type Error = fatfs::Error<sd_reader::Error>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BootgenLoadingError {
|
||||
InvalidBootImageHeader,
|
||||
|
@ -58,7 +62,7 @@ struct PartitionHeader {
|
|||
}
|
||||
|
||||
/// 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];
|
||||
reader.read_exact(&mut buffer)?;
|
||||
let mut result: u32 = 0;
|
||||
|
@ -69,8 +73,8 @@ fn read_u32<Reader: Read>(reader: &mut Reader) -> Result<u32, BootgenLoadingErro
|
|||
}
|
||||
|
||||
/// Load PL partition header.
|
||||
fn load_pl_header<File: Read + Seek>(
|
||||
file: &mut File,
|
||||
fn load_pl_header<'a>(
|
||||
file: &mut File<'a>,
|
||||
) -> Result<Option<PartitionHeader>, BootgenLoadingError> {
|
||||
let mut buffer: [u8; 0x40] = [0; 0x40];
|
||||
file.read_exact(&mut buffer)?;
|
||||
|
@ -82,8 +86,8 @@ fn load_pl_header<File: Read + Seek>(
|
|||
}
|
||||
}
|
||||
|
||||
fn load_ps_header<File: Read + Seek>(
|
||||
file: &mut File,
|
||||
fn load_ps_header<'a>(
|
||||
file: &mut File<'a>,
|
||||
) -> Result<Option<PartitionHeader>, BootgenLoadingError> {
|
||||
let mut buffer: [u8; 0x40] = [0; 0x40];
|
||||
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.
|
||||
/// This function would seek the file to the location of the partition.
|
||||
fn locate<
|
||||
File: Read + Seek,
|
||||
F: Fn(&mut File) -> Result<Option<PartitionHeader>, BootgenLoadingError>,
|
||||
'a,
|
||||
F: Fn(&mut File<'a>) -> Result<Option<PartitionHeader>, BootgenLoadingError>,
|
||||
>(
|
||||
file: &mut File,
|
||||
file: &mut File<'a>,
|
||||
f: F,
|
||||
) -> Result<usize, BootgenLoadingError> {
|
||||
file.seek(SeekFrom::Start(0))?;
|
||||
|
@ -149,7 +153,7 @@ fn locate<
|
|||
/// Load bitstream from bootgen file.
|
||||
/// 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.
|
||||
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)?;
|
||||
unsafe {
|
||||
// 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 mut buffer = Vec::with_capacity(size);
|
||||
unsafe {
|
||||
|
|
|
@ -1,19 +1,24 @@
|
|||
#![no_std]
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::{rc::Rc, string::FromUtf8Error, string::String, vec::Vec};
|
||||
use sd_reader::SdReader;
|
||||
use core::fmt;
|
||||
use alloc::{string::FromUtf8Error, string::String, vec::Vec, rc::Rc};
|
||||
use core_io::{self as io, BufRead, BufReader, Read, Write, Seek, SeekFrom};
|
||||
use fatfs::{self, Read, Seek, SeekFrom, Write};
|
||||
use libboard_zynq::sdio;
|
||||
|
||||
pub mod sd_reader;
|
||||
pub mod net_settings;
|
||||
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)]
|
||||
pub enum Error<'a> {
|
||||
SdError(sdio::sd_card::CardInitializationError),
|
||||
IoError(io::Error),
|
||||
IoError(SdReadError),
|
||||
Utf8Error(FromUtf8Error),
|
||||
KeyNotFoundError(&'a str),
|
||||
NoConfig,
|
||||
|
@ -39,8 +44,8 @@ impl<'a> From<sdio::sd_card::CardInitializationError> for Error<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> From<io::Error> for Error<'a> {
|
||||
fn from(error: io::Error) -> Self {
|
||||
impl<'a> From<SdReadError> for Error<'a> {
|
||||
fn from(error: SdReadError) -> Self {
|
||||
Error::IoError(error)
|
||||
}
|
||||
}
|
||||
|
@ -51,14 +56,33 @@ impl<'a> From<FromUtf8Error> for Error<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn read_to_string<'a>(file: &mut File<'a>, read_str: &mut String) -> Result<'a, ()> {
|
||||
let mut buffer = Vec::new();
|
||||
let mut temp_buffer = [0; 500];
|
||||
loop {
|
||||
let read_bytes = file.read(&mut temp_buffer)?;
|
||||
if read_bytes != buffer.len() {
|
||||
buffer.extend_from_slice(&temp_buffer[..read_bytes]);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
buffer.extend_from_slice(&temp_buffer);
|
||||
}
|
||||
}
|
||||
read_str.extend(String::from_utf8(buffer));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_config<'a>(
|
||||
key: &'a str,
|
||||
buffer: &mut Vec<u8>,
|
||||
file: fatfs::File<sd_reader::SdReader>,
|
||||
mut file: File<'a>,
|
||||
) -> Result<'a, ()> {
|
||||
let prefix = [key, "="].concat().to_ascii_lowercase();
|
||||
for line in BufReader::new(file).lines() {
|
||||
let line = line?.to_ascii_lowercase();
|
||||
let mut read_buffer = String::new();
|
||||
read_to_string(&mut file, &mut read_buffer)?;
|
||||
for line in read_buffer.lines() {
|
||||
let line = line.to_ascii_lowercase();
|
||||
if line.starts_with(&prefix) {
|
||||
buffer.extend(line[prefix.len()..].as_bytes());
|
||||
return Ok(());
|
||||
|
@ -83,7 +107,9 @@ impl Config {
|
|||
let reader = sd_reader::SdReader::new(sd);
|
||||
|
||||
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 {
|
||||
|
@ -94,12 +120,12 @@ impl Config {
|
|||
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 {
|
||||
let root_dir = fs.root_dir();
|
||||
let mut buffer: Vec<u8> = Vec::new();
|
||||
match root_dir.open_file(&["/CONFIG/", key, ".BIN"].concat()) {
|
||||
Ok(mut f) => f.read_to_end(&mut buffer).map(|_| ())?,
|
||||
Ok(mut f) => f.read(&mut buffer).map(|_| ())?,
|
||||
Err(_) => match root_dir.open_file("/CONFIG.TXT") {
|
||||
Ok(f) => parse_config(key, &mut buffer, f)?,
|
||||
Err(_) => return Err(Error::KeyNotFoundError(key)),
|
||||
|
@ -111,11 +137,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)?)?)
|
||||
}
|
||||
|
||||
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 {
|
||||
let root_dir = fs.root_dir();
|
||||
match root_dir.remove(&["/CONFIG/", key, ".BIN"].concat()) {
|
||||
|
@ -125,18 +151,19 @@ impl Config {
|
|||
match root_dir.create_file("/CONFIG.TXT") {
|
||||
Ok(mut f) => {
|
||||
let mut buffer = String::new();
|
||||
f.read_to_string(&mut buffer)?;
|
||||
read_to_string(&mut f, &mut buffer)?;
|
||||
f.seek(SeekFrom::Start(0))?;
|
||||
f.truncate()?;
|
||||
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(NEWLINE)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
Err(_) => Err(Error::KeyNotFoundError(key))
|
||||
}
|
||||
Err(_) => Err(Error::KeyNotFoundError(key)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -162,7 +189,10 @@ impl Config {
|
|||
if is_str {
|
||||
let mut f = root_dir.create_file("/CONFIG.TXT")?;
|
||||
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 {
|
||||
let dir = root_dir.create_dir("/CONFIG")?;
|
||||
let mut f = dir.create_file(&[key, ".BIN"].concat())?;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use core_io::{BufRead, Error, ErrorKind, Read, Result as IoResult, Seek, SeekFrom, Write};
|
||||
use fatfs;
|
||||
use alloc::vec::Vec;
|
||||
use core::fmt;
|
||||
use fatfs::{self, IoBase, IoError, Read, Seek, SeekFrom, Write};
|
||||
use libboard_zynq::sdio::{sd_card::SdCard, CmdTransferError};
|
||||
use log::debug;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
const MBR_SIGNATURE: [u8; 2] = [0x55, 0xAA];
|
||||
const PARTID_FAT12: u8 = 0x01;
|
||||
|
@ -12,13 +12,46 @@ const PARTID_FAT32: u8 = 0x0B;
|
|||
const PARTID_FAT32_LBA: u8 = 0x0C;
|
||||
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;
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// Implementation: all read/writes would be split into unaligned and block-aligned parts,
|
||||
|
@ -43,6 +76,10 @@ pub struct SdReader {
|
|||
offset: u32,
|
||||
}
|
||||
|
||||
impl IoBase for SdReader {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[allow(unused)]
|
||||
// Partition entry enum, normally we would use entry1.
|
||||
|
@ -72,7 +109,7 @@ impl SdReader {
|
|||
|
||||
/// Internal read function for unaligned read.
|
||||
/// 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 {
|
||||
return Ok(0);
|
||||
}
|
||||
|
@ -86,7 +123,7 @@ impl SdReader {
|
|||
|
||||
/// Internal write function for unaligned write.
|
||||
/// 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 {
|
||||
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.
|
||||
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.seek(SeekFrom::Start(0))
|
||||
}
|
||||
|
@ -145,29 +182,28 @@ impl SdReader {
|
|||
/// 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,
|
||||
/// 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];
|
||||
self.seek(SeekFrom::Start(0x1FE))?;
|
||||
self.read_exact(&mut buffer[..2])?;
|
||||
// check MBR signature
|
||||
if buffer[..2] != MBR_SIGNATURE {
|
||||
return Err(Error::new(
|
||||
ErrorKind::InvalidData,
|
||||
"Incorrect signature for MBR sector.",
|
||||
));
|
||||
return Err(fatfs::Error::Io(Error::new("Incorrect signature for MBR sector.")));
|
||||
}
|
||||
// Read partition ID.
|
||||
self.seek(SeekFrom::Start(entry as u64 + 0x4))?;
|
||||
self.read_exact(&mut buffer[..1])?;
|
||||
debug!("Partition ID: {:0X}", buffer[0]);
|
||||
match buffer[0] {
|
||||
PARTID_FAT12 | PARTID_FAT16_LESS32M | PARTID_FAT16 |
|
||||
PARTID_FAT16_LBA | PARTID_FAT32 | PARTID_FAT32_LBA => {}
|
||||
PARTID_FAT12 | PARTID_FAT16_LESS32M | PARTID_FAT16 | PARTID_FAT16_LBA
|
||||
| PARTID_FAT32 | PARTID_FAT32_LBA => {}
|
||||
_ => {
|
||||
return Err(Error::new(
|
||||
ErrorKind::InvalidData,
|
||||
return Err(fatfs::Error::Io(Error::new(
|
||||
"No FAT partition found for the specified entry.",
|
||||
));
|
||||
)));
|
||||
}
|
||||
}
|
||||
// Read LBA
|
||||
|
@ -183,10 +219,29 @@ impl SdReader {
|
|||
// setup fatfs
|
||||
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 {
|
||||
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 (a, b, c) = self.block_align_mut(buf);
|
||||
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 {
|
||||
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);
|
||||
self.write_unaligned(a)?;
|
||||
if b.len() > 0 {
|
||||
|
@ -255,12 +288,10 @@ impl Write for SdReader {
|
|||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> IoResult<()> {
|
||||
fn flush(&mut self) -> Result<(), Error> {
|
||||
if self.dirty {
|
||||
let block_addr = (self.byte_addr - self.index as u32) / (BLOCK_SIZE as u32);
|
||||
self.sd
|
||||
.write_block(block_addr, 1, &self.buffer)
|
||||
.map_err(cmd_error_to_io_error)?;
|
||||
self.sd.write_block(block_addr, 1, &self.buffer)?;
|
||||
self.dirty = false;
|
||||
}
|
||||
Ok(())
|
||||
|
@ -268,14 +299,14 @@ impl Write 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 {
|
||||
SeekFrom::Start(x) => self.offset as i64 + x as i64,
|
||||
SeekFrom::Current(x) => self.byte_addr as i64 + x,
|
||||
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 {
|
||||
return Err(Error::new(ErrorKind::InvalidInput, "Invalid address"));
|
||||
return Err(Error::new("Invalid address"));
|
||||
}
|
||||
let target_byte_addr = raw_target as u32;
|
||||
let address_same_block =
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
name = "libcortex_a9"
|
||||
version = "0.0.0"
|
||||
authors = ["M-Labs"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
power_saving = []
|
||||
|
|
|
@ -1,59 +1,60 @@
|
|||
use core::arch::asm;
|
||||
|
||||
/// The classic no-op
|
||||
#[inline]
|
||||
pub fn nop() {
|
||||
unsafe { llvm_asm!("nop" :::: "volatile") }
|
||||
unsafe { asm!("nop") }
|
||||
}
|
||||
|
||||
/// Wait For Event
|
||||
#[inline]
|
||||
pub fn wfe() {
|
||||
unsafe { llvm_asm!("wfe" :::: "volatile") }
|
||||
unsafe { asm!("wfe") }
|
||||
}
|
||||
|
||||
/// Send Event
|
||||
#[inline]
|
||||
pub fn sev() {
|
||||
unsafe { llvm_asm!("sev" :::: "volatile") }
|
||||
unsafe { asm!("sev") }
|
||||
}
|
||||
|
||||
/// Data Memory Barrier
|
||||
#[inline]
|
||||
pub fn dmb() {
|
||||
unsafe { llvm_asm!("dmb" :::: "volatile") }
|
||||
unsafe { asm!("dmb") }
|
||||
}
|
||||
|
||||
/// Data Synchronization Barrier
|
||||
#[inline]
|
||||
pub fn dsb() {
|
||||
unsafe { llvm_asm!("dsb" :::: "volatile") }
|
||||
unsafe { asm!("dsb") }
|
||||
}
|
||||
|
||||
/// Instruction Synchronization Barrier
|
||||
#[inline]
|
||||
pub fn isb() {
|
||||
unsafe { llvm_asm!("isb" :::: "volatile") }
|
||||
unsafe { asm!("isb") }
|
||||
}
|
||||
|
||||
/// Enable FIQ
|
||||
#[inline]
|
||||
pub unsafe fn enable_fiq() {
|
||||
llvm_asm!("cpsie f":::: "volatile");
|
||||
asm!("cpsie f");
|
||||
}
|
||||
|
||||
/// Enable IRQ
|
||||
#[inline]
|
||||
pub unsafe fn enable_irq() {
|
||||
llvm_asm!("cpsie i":::: "volatile");
|
||||
asm!("cpsie i");
|
||||
}
|
||||
|
||||
/// Disable IRQ, return if IRQ was originally enabled.
|
||||
#[inline]
|
||||
pub unsafe fn enter_critical() -> bool {
|
||||
let mut cpsr: u32;
|
||||
llvm_asm!(
|
||||
"mrs $0, cpsr
|
||||
cpsid i"
|
||||
: "=r"(cpsr) ::: "volatile");
|
||||
asm!(
|
||||
"mrs {}, cpsr
|
||||
cpsid i", lateout(reg) cpsr);
|
||||
(cpsr & (1 << 7)) == 0
|
||||
}
|
||||
|
||||
|
@ -65,18 +66,18 @@ pub unsafe fn exit_critical(enable: bool) {
|
|||
} else {
|
||||
0
|
||||
};
|
||||
llvm_asm!(
|
||||
asm!(
|
||||
"mrs r1, cpsr
|
||||
bic r1, r1, $0
|
||||
bic r1, r1, {}
|
||||
msr cpsr_c, r1"
|
||||
:: "r"(mask) : "r1");
|
||||
, in(reg) mask, out("r1") _);
|
||||
}
|
||||
|
||||
/// Exiting IRQ
|
||||
#[inline]
|
||||
pub unsafe fn exit_irq() {
|
||||
llvm_asm!("
|
||||
asm!("
|
||||
mrs r0, SPSR
|
||||
msr CPSR, r0
|
||||
" ::: "r0");
|
||||
", out("r0") _);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
use super::asm::{dmb, dsb};
|
||||
use super::l2c::*;
|
||||
use core::arch::asm;
|
||||
|
||||
/// Invalidate TLBs
|
||||
#[inline(always)]
|
||||
pub fn tlbiall() {
|
||||
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)]
|
||||
pub fn iciallu() {
|
||||
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)]
|
||||
pub fn bpiall() {
|
||||
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)]
|
||||
pub fn dccsw(setway: u32) {
|
||||
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
|
||||
// analogous) "Example code for cache maintenance operations"
|
||||
// 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)]
|
||||
pub fn dccisw(setway: u32) {
|
||||
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
|
||||
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
|
||||
|
@ -104,7 +105,7 @@ pub fn dcciall_l1() {
|
|||
|
||||
// select L1 data cache
|
||||
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
|
||||
|
@ -156,7 +157,7 @@ fn slice_cache_line_addrs<T>(slice: &[T]) -> impl Iterator<Item = usize> {
|
|||
#[inline(always)]
|
||||
pub fn dccimvac(addr: usize) {
|
||||
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)]
|
||||
pub fn dccmvac(addr: usize) {
|
||||
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.
|
||||
pub fn dcc<T>(object: &T) {
|
||||
dmb();
|
||||
|
@ -239,7 +239,7 @@ pub fn dcc_slice<T>(slice: &[T]) {
|
|||
/// affecting more data than intended.
|
||||
#[inline(always)]
|
||||
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.
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use core::arch::asm;
|
||||
/// Enable FPU in the current core.
|
||||
pub fn enable_fpu() {
|
||||
unsafe {
|
||||
llvm_asm!("
|
||||
asm!("
|
||||
mrc p15, 0, r1, c1, c0, 2
|
||||
orr r1, r1, (0b1111<<20)
|
||||
mcr p15, 0, r1, c1, c0, 2
|
||||
|
@ -9,6 +10,6 @@ pub fn enable_fpu() {
|
|||
vmrs r1, fpexc
|
||||
orr r1, r1, (1<<30)
|
||||
vmsr fpexc, r1
|
||||
":::"r1");
|
||||
", out("r1") _);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#![no_std]
|
||||
#![feature(llvm_asm, global_asm)]
|
||||
#![feature(never_type)]
|
||||
#![feature(const_fn)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
|
@ -17,6 +15,7 @@ pub mod sync_channel;
|
|||
mod uncached;
|
||||
pub use fpu::enable_fpu;
|
||||
pub use uncached::UncachedSlice;
|
||||
use core::arch::global_asm;
|
||||
|
||||
global_asm!(include_str!("exceptions.s"));
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use bit_field::BitField;
|
||||
use core::ptr::addr_of_mut;
|
||||
use super::{regs::*, asm::*, cache::*};
|
||||
use libregister::RegisterW;
|
||||
|
||||
|
@ -136,7 +137,7 @@ pub struct L1Table {
|
|||
impl L1Table {
|
||||
pub fn get() -> &'static mut Self {
|
||||
unsafe {
|
||||
&mut L1_TABLE
|
||||
&mut *addr_of_mut!(L1_TABLE)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ use libregister::{
|
|||
register_bit, register_bits,
|
||||
RegisterR, RegisterW, RegisterRW,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
macro_rules! def_reg_r {
|
||||
($name:tt, $type: ty, $asm_instr:tt) => {
|
||||
|
@ -11,7 +12,7 @@ macro_rules! def_reg_r {
|
|||
#[inline]
|
||||
fn read(&self) -> Self::R {
|
||||
let mut value: u32;
|
||||
unsafe { llvm_asm!($asm_instr : "=r" (value) ::: "volatile") }
|
||||
unsafe { asm!($asm_instr, lateout(reg) value) }
|
||||
value.into()
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +27,7 @@ macro_rules! def_reg_w {
|
|||
#[inline]
|
||||
fn write(&mut self, value: Self::W) {
|
||||
let value: u32 = value.into();
|
||||
unsafe { llvm_asm!($asm_instr :: "r" (value) :: "volatile") }
|
||||
unsafe { asm!($asm_instr, in(reg) value) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -71,29 +72,29 @@ macro_rules! wrap_reg {
|
|||
|
||||
/// Stack Pointer
|
||||
pub struct SP;
|
||||
def_reg_r!(SP, u32, "mov $0, sp");
|
||||
def_reg_w!(SP, u32, "mov sp, $0");
|
||||
def_reg_r!(SP, u32, "mov {}, sp");
|
||||
def_reg_w!(SP, u32, "mov sp, {}");
|
||||
|
||||
/// Link register (function call return address)
|
||||
pub struct LR;
|
||||
def_reg_r!(LR, u32, "mov $0, lr");
|
||||
def_reg_w!(LR, u32, "mov lr, $0");
|
||||
def_reg_r!(LR, u32, "mov {}, lr");
|
||||
def_reg_w!(LR, u32, "mov lr, {}");
|
||||
|
||||
pub struct VBAR;
|
||||
def_reg_r!(VBAR, u32, "mrc p15, 0, $0, c12, c0, 0");
|
||||
def_reg_w!(VBAR, u32, "mcr 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, {}, c12, c0, 0");
|
||||
|
||||
pub struct MVBAR;
|
||||
def_reg_r!(MVBAR, u32, "mrc p15, 0, $0, c12, c0, 1");
|
||||
def_reg_w!(MVBAR, u32, "mcr 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, {}, c12, c0, 1");
|
||||
|
||||
pub struct HVBAR;
|
||||
def_reg_r!(HVBAR, u32, "mrc p15, 4, $0, c12, c0, 0");
|
||||
def_reg_w!(HVBAR, u32, "mcr 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, {}, c12, c0, 0");
|
||||
|
||||
/// Multiprocess Affinity Register
|
||||
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);
|
||||
register_bits!(mpidr,
|
||||
/// CPU core index
|
||||
|
@ -106,15 +107,15 @@ register_bit!(mpidr,
|
|||
u, 30);
|
||||
|
||||
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;
|
||||
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;
|
||||
wrap_reg!(sctlr);
|
||||
def_reg_r!(SCTLR, sctlr::Read, "mrc p15, 0, $0, c1, c0, 0");
|
||||
def_reg_w!(SCTLR, sctlr::Write, "mcr 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, {}, c1, c0, 0");
|
||||
register_bit!(sctlr,
|
||||
/// Enables MMU
|
||||
m, 0);
|
||||
|
@ -147,8 +148,8 @@ register_bit!(sctlr,
|
|||
/// Auxiliary Control Register
|
||||
pub struct ACTLR;
|
||||
wrap_reg!(actlr);
|
||||
def_reg_r!(ACTLR, actlr::Read, "mrc p15, 0, $0, c1, c0, 1");
|
||||
def_reg_w!(ACTLR, actlr::Write, "mcr 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, {}, c1, c0, 1");
|
||||
// SMP bit
|
||||
register_bit!(actlr, parity_on, 9);
|
||||
register_bit!(actlr, alloc_one_way, 8);
|
||||
|
@ -183,17 +184,17 @@ impl ACTLR {
|
|||
|
||||
/// Domain Access Control Register
|
||||
pub struct DACR;
|
||||
def_reg_r!(DACR, u32, "mrc p15, 0, $0, c3, c0, 0");
|
||||
def_reg_w!(DACR, u32, "mcr 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, {}, c3, c0, 0");
|
||||
|
||||
/// Translation Table Base Register 0
|
||||
pub struct TTBR0;
|
||||
/// Translation Table Base Register 1
|
||||
pub struct TTBR1;
|
||||
def_reg_r!(TTBR0, ttbr::Read, "mrc p15, 0, $0, c2, c0, 0");
|
||||
def_reg_w!(TTBR0, ttbr::Write, "mcr p15, 0, $0, c2, c0, 0");
|
||||
def_reg_r!(TTBR1, ttbr::Read, "mrc p15, 0, $0, c2, c0, 1");
|
||||
def_reg_w!(TTBR1, ttbr::Write, "mcr p15, 0, $0, c2, c0, 1");
|
||||
def_reg_r!(TTBR0, ttbr::Read, "mrc p15, 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, {}, c2, c0, 1");
|
||||
def_reg_w!(TTBR1, ttbr::Write, "mcr p15, 0, {}, c2, c0, 1");
|
||||
wrap_reg!(ttbr);
|
||||
register_bits!(ttbr, table_base, u32, 14, 31);
|
||||
register_bit!(ttbr, irgn0, 6);
|
||||
|
|
|
@ -37,7 +37,7 @@ impl<'a, T> Sender<'a, T> where T: Clone {
|
|||
notify_spin_lock();
|
||||
if !prev.is_null() {
|
||||
unsafe {
|
||||
Box::from_raw(prev);
|
||||
drop(Box::from_raw(prev));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -91,7 +91,7 @@ impl<'a, T> Sender<'a, T> where T: Clone {
|
|||
for v in self.list.iter() {
|
||||
let original = v.swap(core::ptr::null_mut(), Ordering::Relaxed);
|
||||
if !original.is_null() {
|
||||
Box::from_raw(original);
|
||||
drop(Box::from_raw(original));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -178,7 +178,8 @@ macro_rules! sync_channel {
|
|||
{
|
||||
use core::sync::atomic::{AtomicUsize, AtomicPtr};
|
||||
use $crate::sync_channel::{Sender, Receiver};
|
||||
static LIST: [AtomicPtr<$t>; $cap + 1] = [AtomicPtr::new(core::ptr::null_mut()); $cap + 1];
|
||||
const cnst_ptr: AtomicPtr<$t> = AtomicPtr::new(core::ptr::null_mut());
|
||||
static LIST: [AtomicPtr<$t>; $cap + 1] = [cnst_ptr; $cap + 1];
|
||||
static WRITE: AtomicUsize = AtomicUsize::new(0);
|
||||
static READ: AtomicUsize = AtomicUsize::new(0);
|
||||
(Sender::new(&LIST, &WRITE, &READ), Receiver::new(&LIST, &WRITE, &READ))
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
name = "libregister"
|
||||
version = "0.0.0"
|
||||
authors = ["M-Labs"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
vcell = "0.1"
|
||||
|
|
|
@ -3,7 +3,7 @@ name = "libsupport_zynq"
|
|||
description = "Software support for running in the Zynq PS"
|
||||
version = "0.0.0"
|
||||
authors = ["M-Labs"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
target_zc706 = ["libboard_zynq/target_zc706"]
|
||||
|
@ -20,7 +20,7 @@ default = ["panic_handler", "dummy_irq_handler", "dummy_fiq_handler"]
|
|||
|
||||
[dependencies]
|
||||
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"] }
|
||||
libregister = { path = "../libregister" }
|
||||
libcortex_a9 = { path = "../libcortex_a9" }
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use r0::zero_bss;
|
||||
use core::ptr::write_volatile;
|
||||
use core::ptr::{write_volatile, addr_of_mut, addr_of};
|
||||
use core::arch::asm;
|
||||
use libregister::{
|
||||
VolatileCell,
|
||||
RegisterR, RegisterRW,
|
||||
|
@ -42,7 +43,7 @@ unsafe extern "C" fn boot_core0() -> ! {
|
|||
let mpcore = mpcore::RegisterBlock::mpcore();
|
||||
mpcore.scu_invalidate.invalidate_all_cores();
|
||||
|
||||
zero_bss(&mut __bss_start, &mut __bss_end);
|
||||
zero_bss(addr_of_mut!(__bss_start), addr_of_mut!(__bss_end));
|
||||
|
||||
let mmu_table = mmu::L1Table::get()
|
||||
.setup_flat_layout();
|
||||
|
@ -131,7 +132,9 @@ impl Core1 {
|
|||
CORE1_ENABLED.set(true);
|
||||
}
|
||||
// Flush cache-line
|
||||
cache::dcc(unsafe { &CORE1_ENABLED });
|
||||
unsafe {
|
||||
cache::dcc(&*addr_of!(CORE1_ENABLED) );
|
||||
}
|
||||
if sdram {
|
||||
cache::dccmvac(0);
|
||||
asm::dsb();
|
||||
|
@ -152,7 +155,7 @@ impl Core1 {
|
|||
pub fn disable(&self) {
|
||||
unsafe {
|
||||
CORE1_ENABLED.set(false);
|
||||
cache::dccmvac(&CORE1_ENABLED as *const _ as usize);
|
||||
cache::dccmvac(addr_of!(CORE1_ENABLED) as *const _ as usize);
|
||||
asm::dsb();
|
||||
}
|
||||
self.restart();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use libregister::{RegisterR, RegisterW};
|
||||
use libcortex_a9::{regs::{DFSR, MPIDR, VBAR}, interrupt_handler};
|
||||
use libboard_zynq::{println, stdio};
|
||||
use core::arch::asm;
|
||||
|
||||
pub fn set_vector_table(base_addr: u32){
|
||||
VBAR.write(base_addr);
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#![no_std]
|
||||
|
||||
#![feature(alloc_error_handler)]
|
||||
#![feature(panic_info_message)]
|
||||
#![feature(naked_functions)]
|
||||
#![feature(asm)]
|
||||
|
||||
pub extern crate alloc;
|
||||
pub extern crate compiler_builtins;
|
||||
|
|
|
@ -10,7 +10,7 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
|
|||
} else {
|
||||
print!("unknown location");
|
||||
}
|
||||
if let Some(message) = info.message() {
|
||||
if let Some(message) = info.message().as_str() {
|
||||
println!(": {}", message);
|
||||
} else {
|
||||
println!("");
|
||||
|
|
|
@ -3,7 +3,7 @@ name = "szl"
|
|||
description = "Simple Zynq Loader"
|
||||
version = "0.1.0"
|
||||
authors = ["M-Labs"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
target_zc706 = ["libboard_zynq/target_zc706", "libsupport_zynq/target_zc706", "libconfig/target_zc706"]
|
||||
|
@ -16,10 +16,14 @@ default = ["target_zc706"]
|
|||
[dependencies]
|
||||
log = "0.4"
|
||||
byteorder = { version = "1.3", default-features = false }
|
||||
core_io = { version = "0.1", features = ["collections"] }
|
||||
|
||||
libboard_zynq = { path = "../libboard_zynq" }
|
||||
libsupport_zynq = { path = "../libsupport_zynq" }
|
||||
libcortex_a9 = { path = "../libcortex_a9" }
|
||||
libregister = { path = "../libregister" }
|
||||
libconfig = { path = "../libconfig" }
|
||||
|
||||
[dependencies.fatfs]
|
||||
git = "https://github.com/rafalh/rust-fatfs"
|
||||
rev = "85f06e0"
|
||||
default-features = false
|
||||
|
|
|
@ -8,7 +8,7 @@ mod netboot;
|
|||
|
||||
use alloc::rc::Rc;
|
||||
use core::mem;
|
||||
use core_io::{Read, Seek};
|
||||
use core::ptr::{addr_of_mut, addr_of};
|
||||
use libboard_zynq::{
|
||||
self as zynq,
|
||||
clocks::source::{ArmPll, ClockSource, IoPll},
|
||||
|
@ -16,7 +16,7 @@ use libboard_zynq::{
|
|||
logger, println, sdio, slcr,
|
||||
timer::GlobalTimer,
|
||||
};
|
||||
use libconfig::{bootgen, sd_reader, Config};
|
||||
use libconfig::{bootgen, sd_reader, Config, File};
|
||||
use libcortex_a9::{
|
||||
asm::{dsb, isb},
|
||||
cache::{bpiall, dcciall, iciallu},
|
||||
|
@ -30,8 +30,8 @@ extern "C" {
|
|||
static mut __runtime_end: usize;
|
||||
}
|
||||
|
||||
fn boot_sd<File: Read + Seek>(
|
||||
file: &mut Option<File>,
|
||||
fn boot_sd<'a>(
|
||||
file: &mut Option<File<'a>>,
|
||||
runtime_start: *mut u8,
|
||||
runtime_max: usize,
|
||||
) -> Result<(), ()> {
|
||||
|
@ -116,18 +116,18 @@ pub fn main_core0() {
|
|||
|
||||
unsafe {
|
||||
let max_len =
|
||||
&__runtime_end as *const usize as usize - &__runtime_start as *const usize as usize;
|
||||
addr_of!(__runtime_end) as *const usize as usize - addr_of!(__runtime_start) as *const usize as usize;
|
||||
match slcr::RegisterBlock::unlocked(|slcr| slcr.boot_mode.read().boot_mode_pins()) {
|
||||
slcr::BootModePins::Jtag => netboot::netboot(
|
||||
&mut bootgen_file,
|
||||
config,
|
||||
&mut __runtime_start as *mut usize as *mut u8,
|
||||
addr_of_mut!(__runtime_start) as *mut usize as *mut u8,
|
||||
max_len,
|
||||
),
|
||||
slcr::BootModePins::SdCard => {
|
||||
if boot_sd(
|
||||
&mut bootgen_file,
|
||||
&mut __runtime_start as *mut usize as *mut u8,
|
||||
addr_of_mut!(__runtime_start) as *mut usize as *mut u8,
|
||||
max_len,
|
||||
)
|
||||
.is_err()
|
||||
|
@ -137,7 +137,7 @@ pub fn main_core0() {
|
|||
netboot::netboot(
|
||||
&mut bootgen_file,
|
||||
config,
|
||||
&mut __runtime_start as *mut usize as *mut u8,
|
||||
addr_of_mut!(__runtime_start) as *mut usize as *mut u8,
|
||||
max_len,
|
||||
)
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ pub fn main_core0() {
|
|||
netboot::netboot(
|
||||
&mut bootgen_file,
|
||||
config,
|
||||
&mut __runtime_start as *mut usize as *mut u8,
|
||||
addr_of_mut!(__runtime_start) as *mut usize as *mut u8,
|
||||
max_len,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
use byteorder::{ByteOrder, NetworkEndian};
|
||||
use core_io::{Read, Seek};
|
||||
use libboard_zynq::{
|
||||
devc,
|
||||
eth::Eth,
|
||||
|
@ -13,7 +12,7 @@ use libboard_zynq::{
|
|||
},
|
||||
timer::GlobalTimer,
|
||||
};
|
||||
use libconfig::{bootgen, net_settings, Config};
|
||||
use libconfig::{bootgen, net_settings, Config, File};
|
||||
|
||||
enum NetConnState {
|
||||
WaitCommand,
|
||||
|
@ -48,7 +47,7 @@ impl NetConn {
|
|||
self.gateware_downloaded = false;
|
||||
}
|
||||
|
||||
fn input_partial<File: Read + Seek>(
|
||||
fn input_partial(
|
||||
&mut self,
|
||||
bootgen_file: &mut Option<File>,
|
||||
runtime_start: *mut u8,
|
||||
|
@ -284,9 +283,9 @@ impl NetConn {
|
|||
}
|
||||
}
|
||||
|
||||
fn input<File: Read + Seek>(
|
||||
fn input<'a>(
|
||||
&mut self,
|
||||
bootgen_file: &mut Option<File>,
|
||||
bootgen_file: &mut Option<File<'a>>,
|
||||
runtime_start: *mut u8,
|
||||
runtime_max_len: usize,
|
||||
buf: &[u8],
|
||||
|
@ -309,8 +308,8 @@ impl NetConn {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn netboot<File: Read + Seek>(
|
||||
bootgen_file: &mut Option<File>,
|
||||
pub fn netboot<'a>(
|
||||
bootgen_file: &mut Option<File<'a>>,
|
||||
cfg: Config,
|
||||
runtime_start: *mut u8,
|
||||
runtime_max_len: usize,
|
||||
|
|
Loading…
Reference in New Issue