Compare commits
17 Commits
master
...
bump_to_la
Author | SHA1 | Date | |
---|---|---|---|
0159c46946 | |||
e15d89da48 | |||
b05f679c9a | |||
fa3fe497e1 | |||
e894f502a4 | |||
cd56ef6d48 | |||
0a91f883bc | |||
3e59dcbc94 | |||
4138a65270 | |||
cb0ec48ef0 | |||
14dffaf49c | |||
bd0c45497e | |||
6dc831a8f8 | |||
aef7dcabae | |||
49a84da2ce | |||
b00f297cd0 | |||
526e80401a |
@ -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",
|
||||
]
|
||||
|
||||
|
34
Cargo.lock
generated
34
Cargo.lock
generated
@ -15,10 +15,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.3.0"
|
||||
name = "bitflags"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60f0b0d4c0a382d2734228fd12b5a6b5dac185c60e938026fd31b265b94f9bd2"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
@ -34,14 +40,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.49"
|
||||
version = "0.1.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20b1438ef42c655665a8ab2c1c6d605a305f031d38d9be689ddfef41a20f3aa2"
|
||||
|
||||
[[package]]
|
||||
name = "core_io"
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/rs-core_io.git?rev=e9d3edf027#e9d3edf0272502b0dd6c26e8a4869c2912657615"
|
||||
checksum = "f11973008a8cf741fe6d22f339eba21fd0ca81e2760a769ba8243ed6c21edd7e"
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal"
|
||||
@ -68,12 +69,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "fatfs"
|
||||
version = "0.3.6"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/rust-fatfs.git?rev=4b5e420084#4b5e420084fd1c4a9c105680b687523909b6469c"
|
||||
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",
|
||||
]
|
||||
|
||||
@ -108,7 +107,6 @@ dependencies = [
|
||||
name = "libconfig"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"core_io",
|
||||
"fatfs",
|
||||
"libboard_zynq",
|
||||
"log",
|
||||
@ -199,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",
|
||||
]
|
||||
@ -209,7 +207,7 @@ name = "szl"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"core_io",
|
||||
"fatfs",
|
||||
"libboard_zynq",
|
||||
"libconfig",
|
||||
"libcortex_a9",
|
||||
|
@ -9,6 +9,7 @@ members = [
|
||||
"experiments",
|
||||
"szl",
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
|
@ -1,4 +1,12 @@
|
||||
{
|
||||
"abi-blacklist": [
|
||||
"stdcall",
|
||||
"fastcall",
|
||||
"vectorcall",
|
||||
"thiscall",
|
||||
"win64",
|
||||
"sysv64"
|
||||
],
|
||||
"arch": "arm",
|
||||
"data-layout": "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
|
||||
"emit-debug-gdb-scripts": false,
|
||||
|
@ -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,9 +1,6 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(naked_functions)]
|
||||
#![feature(asm)]
|
||||
#![feature(inline_const)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
@ -45,6 +42,7 @@ use libsupport_zynq::{
|
||||
};
|
||||
use log::{info, warn};
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
use core::ptr::addr_of_mut;
|
||||
|
||||
const HWADDR: [u8; 6] = [0, 0x23, 0xde, 0xea, 0xbe, 0xef];
|
||||
|
||||
@ -73,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 u32);
|
||||
asm::enable_irq();
|
||||
CORE1_RESTART.store(false, Ordering::Relaxed);
|
||||
notify_spin_lock();
|
||||
|
49
flake.lock
generated
49
flake.lock
generated
@ -1,46 +1,41 @@
|
||||
{
|
||||
"nodes": {
|
||||
"mozilla-overlay": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1704373101,
|
||||
"narHash": "sha256-+gi59LRWRQmwROrmE1E2b3mtocwueCQqZ60CwLG+gbg=",
|
||||
"owner": "mozilla",
|
||||
"repo": "nixpkgs-mozilla",
|
||||
"rev": "9b11a87c0cc54e308fa83aac5b4ee1816d5418a2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "mozilla",
|
||||
"repo": "nixpkgs-mozilla",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1736867362,
|
||||
"narHash": "sha256-i/UJ5I7HoqmFMwZEH6vAvBxOrjjOJNU739lnZnhUln8=",
|
||||
"lastModified": 1729181673,
|
||||
"narHash": "sha256-LDiPhQ3l+fBjRATNtnuDZsBS7hqoBtPkKBkhpoBHv3I=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "9c6b49aeac36e2ed73a8c472f1546f6d9cf1addc",
|
||||
"rev": "4eb33fe664af7b41a4c446f87d20c9a0a6321fa3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-24.11",
|
||||
"ref": "nixos-24.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs",
|
||||
"rust-overlay": "rust-overlay"
|
||||
}
|
||||
},
|
||||
"rust-overlay": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1719454714,
|
||||
"narHash": "sha256-MojqG0lyUINkEk0b3kM2drsU5vyaF8DFZe/FAlZVOGs=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "d1c527659cf076ecc4b96a91c702d080b213801e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "oxalica",
|
||||
"ref": "snapshot/2024-08-01",
|
||||
"repo": "rust-overlay",
|
||||
"type": "github"
|
||||
"mozilla-overlay": "mozilla-overlay",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
50
flake.nix
50
flake.nix
@ -1,30 +1,31 @@
|
||||
{
|
||||
description = "Bare-metal Rust on Zynq-7000";
|
||||
|
||||
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-24.11;
|
||||
inputs.rust-overlay = {
|
||||
url = "github:oxalica/rust-overlay?ref=snapshot/2024-08-01";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-24.05;
|
||||
inputs.mozilla-overlay = { url = github:mozilla/nixpkgs-mozilla; flake = false; };
|
||||
|
||||
outputs = { self, nixpkgs, rust-overlay }:
|
||||
outputs = { self, nixpkgs, mozilla-overlay }:
|
||||
let
|
||||
pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ (import rust-overlay) crosspkgs-overlay ]; };
|
||||
pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ (import mozilla-overlay) crosspkgs-overlay ]; };
|
||||
|
||||
rust = pkgs.rust-bin.nightly."2021-09-01".default.override {
|
||||
extensions = [ "rust-src" ];
|
||||
targets = [ ];
|
||||
rustManifest = pkgs.fetchurl {
|
||||
url = "https://static.rust-lang.org/dist/2024-07-19/channel-rust-nightly.toml";
|
||||
sha256 = "sha256-MM2K43Kg+f83XQXT2lI7W/ZdQjLXhMUvA6eGtD+rqDY=";
|
||||
};
|
||||
rustPlatform = pkgs.makeRustPlatform {
|
||||
rustc = rust // {
|
||||
# https://github.com/oxalica/rust-overlay/commit/c48c2d76b68dd9ede0815fec53479375c61af857
|
||||
targetPlatforms = pkgs.lib.platforms.all;
|
||||
tier1TargetPlatforms = pkgs.lib.platforms.all;
|
||||
badTargetPlatforms = [ ];
|
||||
rustTargets = [];
|
||||
rustChannelOfTargets = _channel: _date: targets:
|
||||
(pkgs.lib.rustLib.fromManifestFile rustManifest {
|
||||
inherit (pkgs) stdenv lib fetchurl patchelf;
|
||||
}).rust.override {
|
||||
inherit targets;
|
||||
extensions = ["rust-src"];
|
||||
};
|
||||
rust = rustChannelOfTargets "nightly" null rustTargets;
|
||||
rustPlatform = pkgs.recurseIntoAttrs (pkgs.makeRustPlatform {
|
||||
rustc = rust;
|
||||
cargo = rust;
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
crosspkgs-overlay = (self: super: {
|
||||
pkgsCross = super.pkgsCross // {
|
||||
zynq-baremetal = import super.path {
|
||||
@ -95,9 +96,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}";
|
||||
@ -106,14 +105,13 @@
|
||||
baseNameOf path != "target"
|
||||
) ./.;
|
||||
cargoLock = {
|
||||
lockFile = ./Cargo.lock;
|
||||
lockFile = ./Cargo.lock;
|
||||
outputHashes = {
|
||||
"core_io-0.1.0" = "sha256-0HINFWRiJx8pjMgUOL/CS336ih7SENSRh3Kah9LPRrw=";
|
||||
"fatfs-0.3.6" = "sha256-Nz9hCq/1YgSXF8ltJ5ZawV0Hc8WV44KNK0tJdVnNb4U=";
|
||||
"fatfs-0.4.0" = "sha256-P7IgvhwTPXtNhcyv8cFqwO2UdaEcCGJY7UBG6+yBFSg=";
|
||||
};
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ cargo-xbuild pkgs.llvmPackages_13.clang-unwrapped ];
|
||||
nativeBuildInputs = [ cargo-xbuild pkgs.llvmPackages_18.clang-unwrapped ];
|
||||
buildPhase = ''
|
||||
export XARGO_RUST_SRC="${rust}/lib/rustlib/src/rust/library"
|
||||
export CARGO_HOME=$(mktemp -d cargo-home.XXX)
|
||||
@ -169,7 +167,7 @@
|
||||
|
||||
pkgs.openocd pkgs.gdb
|
||||
pkgs.openssh pkgs.rsync
|
||||
pkgs.llvmPackages_13.clang-unwrapped
|
||||
pkgs.llvmPackages_18.clang-unwrapped
|
||||
(pkgs.python3.withPackages(ps: [ ps.pyftdi ]))
|
||||
];
|
||||
};
|
||||
|
@ -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 = []
|
||||
|
@ -55,27 +55,7 @@ impl Status {
|
||||
pub fn get_link(&self) -> Option<Link> {
|
||||
if ! self.link_status() {
|
||||
None
|
||||
} else if self.cap_100base_tx_full() {
|
||||
Some(Link {
|
||||
speed: LinkSpeed::S100,
|
||||
duplex: LinkDuplex::Full,
|
||||
})
|
||||
} else if self.cap_100base_tx_half() {
|
||||
Some(Link {
|
||||
speed: LinkSpeed::S100,
|
||||
duplex: LinkDuplex::Half,
|
||||
})
|
||||
} else if self.cap_100base_t4() {
|
||||
Some(Link {
|
||||
speed: LinkSpeed::S100,
|
||||
duplex: LinkDuplex::Half,
|
||||
})
|
||||
} else if self.cap_10base_t2_full() {
|
||||
Some(Link {
|
||||
speed: LinkSpeed::S10,
|
||||
duplex: LinkDuplex::Full,
|
||||
})
|
||||
} else if self.cap_10base_t2_half() {
|
||||
} else if self.cap_10base_t_half() {
|
||||
Some(Link {
|
||||
speed: LinkSpeed::S10,
|
||||
duplex: LinkDuplex::Half,
|
||||
@ -85,11 +65,31 @@ impl Status {
|
||||
speed: LinkSpeed::S10,
|
||||
duplex: LinkDuplex::Full,
|
||||
})
|
||||
} else if self.cap_10base_t_half() {
|
||||
} else if self.cap_10base_t2_half() {
|
||||
Some(Link {
|
||||
speed: LinkSpeed::S10,
|
||||
duplex: LinkDuplex::Half,
|
||||
})
|
||||
} else if self.cap_10base_t2_full() {
|
||||
Some(Link {
|
||||
speed: LinkSpeed::S10,
|
||||
duplex: LinkDuplex::Full,
|
||||
})
|
||||
} else if self.cap_100base_t4() {
|
||||
Some(Link {
|
||||
speed: LinkSpeed::S100,
|
||||
duplex: LinkDuplex::Half,
|
||||
})
|
||||
} else if self.cap_100base_tx_half() {
|
||||
Some(Link {
|
||||
speed: LinkSpeed::S100,
|
||||
duplex: LinkDuplex::Half,
|
||||
})
|
||||
} else if self.cap_100base_tx_full() {
|
||||
Some(Link {
|
||||
speed: LinkSpeed::S100,
|
||||
duplex: LinkDuplex::Full,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -2,22 +2,17 @@
|
||||
name = "libconfig"
|
||||
version = "0.1.0"
|
||||
authors = ["M-Labs"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
libboard_zynq = { path = "../libboard_zynq" }
|
||||
log = "0.4"
|
||||
|
||||
[dependencies.core_io]
|
||||
git = "https://git.m-labs.hk/M-Labs/rs-core_io.git"
|
||||
rev = "e9d3edf027"
|
||||
features = ["collections"]
|
||||
|
||||
[dependencies.fatfs]
|
||||
git = "https://git.m-labs.hk/M-Labs/rust-fatfs.git"
|
||||
rev = "4b5e420084"
|
||||
git = "https://github.com/rafalh/rust-fatfs"
|
||||
rev = "85f06e0"
|
||||
default-features = false
|
||||
features = ["core_io"]
|
||||
features = ["alloc", "lfn"]
|
||||
|
||||
[features]
|
||||
target_zc706 = []
|
||||
|
@ -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 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 alloc::{rc::Rc, string::{FromUtf8Error, String}, vec::Vec};
|
||||
use sd_reader::SdReader;
|
||||
use core::{cmp, fmt};
|
||||
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,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>(
|
||||
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 read_buffer = read_to_string(&mut file)?;
|
||||
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 +134,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 +147,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) => read_to_end( &mut f, &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 +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)?)?)
|
||||
}
|
||||
|
||||
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()) {
|
||||
@ -124,19 +177,19 @@ impl Config {
|
||||
let prefix = [key, "="].concat().to_ascii_lowercase();
|
||||
match root_dir.create_file("/CONFIG.TXT") {
|
||||
Ok(mut f) => {
|
||||
let mut buffer = String::new();
|
||||
f.read_to_string(&mut buffer)?;
|
||||
let buffer = read_to_string(&mut f)?;
|
||||
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 +215,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,10 +1,6 @@
|
||||
#![no_std]
|
||||
#![feature(never_type)]
|
||||
#![feature(global_asm)]
|
||||
#![feature(asm)]
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(inline_const)]
|
||||
#![feature(const_fn_trait_bound)]
|
||||
#![feature(ptr_as_ref_unchecked)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
use bit_field::BitField;
|
||||
use core::ptr::{addr_of_mut, addr_of};
|
||||
use super::{regs::*, asm::*, cache::*};
|
||||
use libregister::RegisterW;
|
||||
|
||||
@ -134,9 +135,9 @@ pub struct L1Table {
|
||||
}
|
||||
|
||||
impl L1Table {
|
||||
pub fn get() -> &'static mut Self {
|
||||
pub fn get() -> *mut L1Table {
|
||||
unsafe {
|
||||
&mut L1_TABLE
|
||||
addr_of_mut!(L1_TABLE)
|
||||
}
|
||||
}
|
||||
|
||||
@ -391,7 +392,7 @@ pub fn with_mmu<F: FnMut() -> !>(l1table: &L1Table, mut f: F) -> ! {
|
||||
let domains = AccessDomains::all_manager();
|
||||
DACR.write(domains.into());
|
||||
|
||||
let table_base = &l1table.table as *const _ as u32;
|
||||
let table_base = addr_of!(l1table.table) as u32;
|
||||
assert!(table_base & 0x3fff == 0);
|
||||
TTBR0.write(
|
||||
TTBR0::zeroed()
|
||||
|
@ -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);
|
||||
let _ = 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);
|
||||
let _ = Box::from_raw(original);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -177,10 +177,7 @@ macro_rules! sync_channel {
|
||||
{
|
||||
use core::sync::atomic::{AtomicUsize, AtomicPtr};
|
||||
use $crate::sync_channel::{Sender, Receiver};
|
||||
const fn new_atomic() -> AtomicPtr<$t> {
|
||||
AtomicPtr::new(core::ptr::null_mut())
|
||||
}
|
||||
static LIST: [AtomicPtr<$t>; $cap + 1] = [const { new_atomic() }; $cap + 1];
|
||||
static LIST: [AtomicPtr<$t>; $cap + 1] = [const { AtomicPtr::new(core::ptr::null_mut()) }; $cap + 1];
|
||||
static WRITE: AtomicUsize = AtomicUsize::new(0);
|
||||
static READ: AtomicUsize = AtomicUsize::new(0);
|
||||
(Sender::new(&LIST, &WRITE, &READ), Receiver::new(&LIST, &WRITE, &READ))
|
||||
|
@ -23,18 +23,19 @@ impl<T> UncachedSlice<T> {
|
||||
assert_eq!(start & (L1_PAGE_SIZE - 1), 0);
|
||||
|
||||
for page_start in (start..(start + size)).step_by(L1_PAGE_SIZE) {
|
||||
// non-shareable device
|
||||
L1Table::get()
|
||||
.update(page_start as *const (), |l1_section| {
|
||||
l1_section.tex = 0b10;
|
||||
l1_section.cacheable = true;
|
||||
l1_section.bufferable = false;
|
||||
});
|
||||
unsafe {
|
||||
// non-shareable device
|
||||
L1Table::get()
|
||||
.as_mut_unchecked()
|
||||
.update(page_start as *const (), |l1_section| {
|
||||
l1_section.tex = 0b10;
|
||||
l1_section.cacheable = true;
|
||||
l1_section.bufferable = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
for e in slice.iter_mut() {
|
||||
*e = default();
|
||||
|
@ -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.49"
|
||||
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,5 @@
|
||||
use r0::zero_bss;
|
||||
use core::ptr::write_volatile;
|
||||
use core::ptr::{write_volatile, addr_of_mut};
|
||||
use core::arch::asm;
|
||||
use libregister::{
|
||||
VolatileCell,
|
||||
@ -43,10 +43,13 @@ 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();
|
||||
let mmu_table = unsafe {
|
||||
mmu::L1Table::get()
|
||||
.as_mut().unwrap()
|
||||
.setup_flat_layout()
|
||||
};
|
||||
mmu::with_mmu(mmu_table, || {
|
||||
mpcore.scu_control.start();
|
||||
ACTLR.enable_smp();
|
||||
@ -69,7 +72,11 @@ unsafe extern "C" fn boot_core1() -> ! {
|
||||
let mpcore = mpcore::RegisterBlock::mpcore();
|
||||
mpcore.scu_invalidate.invalidate_core1();
|
||||
|
||||
let mmu_table = mmu::L1Table::get();
|
||||
let mmu_table = unsafe {
|
||||
mmu::L1Table::get()
|
||||
.as_mut().unwrap()
|
||||
.setup_flat_layout()
|
||||
};
|
||||
mmu::with_mmu(mmu_table, || {
|
||||
ACTLR.enable_smp();
|
||||
ACTLR.enable_prefetch();
|
||||
|
@ -1,10 +1,7 @@
|
||||
#![no_std]
|
||||
|
||||
#![feature(alloc_error_handler)]
|
||||
#![feature(panic_info_message)]
|
||||
#![feature(naked_functions)]
|
||||
#![feature(global_asm)]
|
||||
#![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,14 +16,15 @@ default = ["target_zc706"]
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
byteorder = { version = "1.3", default-features = false }
|
||||
|
||||
libboard_zynq = { path = "../libboard_zynq" }
|
||||
libsupport_zynq = { path = "../libsupport_zynq" }
|
||||
libcortex_a9 = { path = "../libcortex_a9" }
|
||||
libregister = { path = "../libregister" }
|
||||
libconfig = { path = "../libconfig" }
|
||||
|
||||
[dependencies.core_io]
|
||||
git = "https://git.m-labs.hk/M-Labs/rs-core_io.git"
|
||||
rev = "e9d3edf027"
|
||||
features = ["collections"]
|
||||
|
||||
[dependencies.fatfs]
|
||||
git = "https://github.com/rafalh/rust-fatfs"
|
||||
rev = "85f06e0"
|
||||
default-features = false
|
||||
features = ["alloc", "lfn"]
|
||||
|
@ -7,8 +7,7 @@ extern crate log;
|
||||
mod netboot;
|
||||
|
||||
use alloc::rc::Rc;
|
||||
use core::mem;
|
||||
use core_io::{Read, Seek};
|
||||
use core::{mem, ptr::{addr_of, addr_of_mut}};
|
||||
use libboard_zynq::{
|
||||
self as zynq,
|
||||
clocks::source::{ArmPll, ClockSource, IoPll},
|
||||
@ -16,7 +15,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 +29,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 +115,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 usize - addr_of!(__runtime_start) 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).cast(),
|
||||
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).cast(),
|
||||
max_len,
|
||||
)
|
||||
.is_err()
|
||||
@ -137,7 +136,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).cast(),
|
||||
max_len,
|
||||
)
|
||||
}
|
||||
@ -148,7 +147,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).cast(),
|
||||
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
Block a user