Compare commits
No commits in common. "master" and "master" have entirely different histories.
@ -1,6 +1,7 @@
|
||||
[target.armv7-none-eabihf]
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
"-C", "target-feature=a9,armv7-a,neon",
|
||||
"-C", "target-cpu=cortex-a9",
|
||||
]
|
||||
|
||||
|
11
Cargo.lock
generated
11
Cargo.lock
generated
@ -34,9 +34,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.108"
|
||||
version = "0.1.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d68bc55329711cd719c2687bb147bc06211b0521f97ef398280108ccb23227e9"
|
||||
checksum = "20b1438ef42c655665a8ab2c1c6d605a305f031d38d9be689ddfef41a20f3aa2"
|
||||
|
||||
[[package]]
|
||||
name = "core_io"
|
||||
@ -84,6 +84,7 @@ dependencies = [
|
||||
"embedded-hal",
|
||||
"libcortex_a9",
|
||||
"nb 1.0.0",
|
||||
"pin-utils",
|
||||
"smoltcp",
|
||||
]
|
||||
|
||||
@ -180,6 +181,12 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "r0"
|
||||
version = "1.0.0"
|
||||
|
@ -4,7 +4,7 @@
|
||||
"emit-debug-gdb-scripts": false,
|
||||
"env": "",
|
||||
"executables": true,
|
||||
"features": "+v7,+vfp3,-d32,+thumb2,+neon,+a9,+armv7-a",
|
||||
"features": "+v7,+vfp3,-d32,+thumb2,-neon",
|
||||
"is-builtin": false,
|
||||
"linker": "rust-lld",
|
||||
"linker-flavor": "ld.lld",
|
||||
|
@ -1,9 +1,9 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(naked_functions)]
|
||||
#![feature(asm)]
|
||||
#![feature(inline_const)]
|
||||
#![feature(strict_provenance)]
|
||||
#![feature(raw_ref_op)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
@ -73,7 +73,7 @@ interrupt_handler!(IRQ, irq, __irq_stack0_start, __irq_stack1_start, {
|
||||
if id.0 == 0 {
|
||||
gic.end_interrupt(id);
|
||||
asm::exit_irq();
|
||||
SP.write((&raw mut __stack1_start).addr() as u32);
|
||||
SP.write(&mut __stack1_start as *mut _ as u32);
|
||||
asm::enable_irq();
|
||||
CORE1_RESTART.store(false, Ordering::Relaxed);
|
||||
notify_spin_lock();
|
||||
|
6
flake.lock
generated
6
flake.lock
generated
@ -2,11 +2,11 @@
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1739206421,
|
||||
"narHash": "sha256-PwQASeL2cGVmrtQYlrBur0U20Xy07uSWVnFup2PHnDs=",
|
||||
"lastModified": 1736867362,
|
||||
"narHash": "sha256-i/UJ5I7HoqmFMwZEH6vAvBxOrjjOJNU739lnZnhUln8=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "44534bc021b85c8d78e465021e21f33b856e2540",
|
||||
"rev": "9c6b49aeac36e2ed73a8c472f1546f6d9cf1addc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
15
flake.nix
15
flake.nix
@ -11,7 +11,7 @@
|
||||
let
|
||||
pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ (import rust-overlay) crosspkgs-overlay ]; };
|
||||
|
||||
rust = pkgs.rust-bin.nightly."2024-04-06".default.override {
|
||||
rust = pkgs.rust-bin.nightly."2021-09-01".default.override {
|
||||
extensions = [ "rust-src" ];
|
||||
targets = [ ];
|
||||
};
|
||||
@ -95,6 +95,10 @@
|
||||
dontFixup = true;
|
||||
};
|
||||
|
||||
cargo-xbuild = pkgs.cargo-xbuild.overrideAttrs(oa: {
|
||||
postPatch = "substituteInPlace src/sysroot.rs --replace 2021 2018";
|
||||
});
|
||||
|
||||
build-crate = name: crate: features: rustPlatform.buildRustPackage rec {
|
||||
name = "${crate}";
|
||||
|
||||
@ -109,8 +113,7 @@
|
||||
};
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ pkgs.cargo-xbuild pkgs.llvmPackages_18.clang-unwrapped ];
|
||||
|
||||
nativeBuildInputs = [ cargo-xbuild pkgs.llvmPackages_13.clang-unwrapped ];
|
||||
buildPhase = ''
|
||||
export XARGO_RUST_SRC="${rust}/lib/rustlib/src/rust/library"
|
||||
export CARGO_HOME=$(mktemp -d cargo-home.XXX)
|
||||
@ -149,7 +152,7 @@
|
||||
) "mkdir $out\n" targets);
|
||||
in rec {
|
||||
packages.x86_64-linux = {
|
||||
inherit szl mkbootimage;
|
||||
inherit cargo-xbuild szl mkbootimage;
|
||||
zc706-fsbl = fsbl { board = "zc706"; };
|
||||
} // allTargetCrates ;
|
||||
|
||||
@ -161,12 +164,12 @@
|
||||
name = "zynq-rs-dev-shell";
|
||||
buildInputs = [
|
||||
rust
|
||||
pkgs.cargo-xbuild
|
||||
cargo-xbuild
|
||||
mkbootimage
|
||||
|
||||
pkgs.openocd pkgs.gdb
|
||||
pkgs.openssh pkgs.rsync
|
||||
pkgs.llvmPackages_18.clang-unwrapped
|
||||
pkgs.llvmPackages_13.clang-unwrapped
|
||||
(pkgs.python3.withPackages(ps: [ ps.pyftdi ]))
|
||||
];
|
||||
};
|
||||
|
@ -7,6 +7,7 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
#futures = { version = "0.3", default-features = false }
|
||||
pin-utils = "0.1.0-alpha.4"
|
||||
embedded-hal = "0.2"
|
||||
nb = "1.0"
|
||||
libcortex_a9 = { path = "../libcortex_a9" }
|
||||
|
@ -1,12 +1,14 @@
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
use core::{
|
||||
cell::{RefCell, Cell},
|
||||
cell::{RefCell, UnsafeCell},
|
||||
future::Future,
|
||||
mem::MaybeUninit,
|
||||
pin::{pin, Pin},
|
||||
pin::Pin,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
|
||||
};
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
//use futures::future::FutureExt;
|
||||
use pin_utils::pin_mut;
|
||||
|
||||
// NOTE `*const ()` is &AtomicBool
|
||||
static VTABLE: RawWakerVTable = {
|
||||
@ -37,7 +39,7 @@ fn wrap_waker(ready: &AtomicBool) -> Waker {
|
||||
/// This is a singleton
|
||||
pub struct Executor {
|
||||
// Entered block_on() already?
|
||||
in_block_on: Cell<bool>,
|
||||
in_block_on: RefCell<bool>,
|
||||
|
||||
/// Tasks reside on the heap, so that we just queue pointers. They
|
||||
/// must also be pinned in memory because our RawWaker is a pointer
|
||||
@ -49,7 +51,7 @@ impl Executor {
|
||||
/// Creates a new instance of the executor
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
in_block_on: Cell::new(false),
|
||||
in_block_on: RefCell::new(false),
|
||||
tasks: RefCell::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
@ -59,12 +61,15 @@ impl Executor {
|
||||
// below has to become more complex. It's also likely that the
|
||||
// application will only call `block_on` once on an infinite task
|
||||
// (`Future<Output = !>`)
|
||||
if self.in_block_on.get() {
|
||||
panic!("nested `block_on`");
|
||||
{
|
||||
let mut in_block_on = self.in_block_on.borrow_mut();
|
||||
if *in_block_on {
|
||||
panic!("nested `block_on`");
|
||||
}
|
||||
*in_block_on = true;
|
||||
}
|
||||
self.in_block_on.replace(true);
|
||||
|
||||
let mut pinned_f = pin!(f);
|
||||
pin_mut!(f);
|
||||
let ready = AtomicBool::new(true);
|
||||
let waker = wrap_waker(&ready);
|
||||
let mut backup = Vec::new();
|
||||
@ -72,10 +77,13 @@ impl Executor {
|
||||
// advance the main task
|
||||
if ready.load(Ordering::Relaxed) {
|
||||
ready.store(false, Ordering::Relaxed);
|
||||
|
||||
// println!("run block_on");
|
||||
let mut cx = Context::from_waker(&waker);
|
||||
if let Poll::Ready(val) = pinned_f.as_mut().poll(&mut cx) {
|
||||
if let Poll::Ready(val) = f.as_mut().poll(&mut cx) {
|
||||
break val;
|
||||
}
|
||||
// println!("ran block_on");
|
||||
}
|
||||
|
||||
// advance all tasks
|
||||
@ -100,12 +108,16 @@ impl Executor {
|
||||
// Requeue
|
||||
self.tasks.borrow_mut().push(task);
|
||||
}
|
||||
|
||||
// // try to sleep; this will be a no-op if any of the previous tasks generated a SEV or an
|
||||
// // interrupt ran (regardless of whether it generated a wake-up or not)
|
||||
// asm::wfe();
|
||||
};
|
||||
self.in_block_on.replace(false);
|
||||
val
|
||||
}
|
||||
|
||||
pub fn spawn(&self, f: impl Future<Output = ()> + 'static) {
|
||||
pub fn spawn(&self, f: impl Future + 'static) {
|
||||
let task = Box::pin(Task::new(f));
|
||||
self.tasks.borrow_mut().push(task);
|
||||
}
|
||||
@ -117,10 +129,10 @@ pub struct Task {
|
||||
}
|
||||
|
||||
impl Task {
|
||||
fn new(f: impl Future<Output = ()> + 'static) -> Self {
|
||||
fn new(f: impl Future + 'static) -> Self {
|
||||
Task {
|
||||
ready: AtomicBool::new(true),
|
||||
f: Box::pin(f),
|
||||
f: Box::pin(async { f.await; }),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -130,15 +142,16 @@ impl Task {
|
||||
/// This lazily initializes the executor and allocator when first called
|
||||
pub(crate) fn current() -> &'static Executor {
|
||||
static INIT: AtomicBool = AtomicBool::new(false);
|
||||
static mut EXECUTOR: MaybeUninit<Executor> = MaybeUninit::uninit();
|
||||
static mut EXECUTOR: UnsafeCell<MaybeUninit<Executor>> = UnsafeCell::new(MaybeUninit::uninit());
|
||||
|
||||
if INIT.load(Ordering::Relaxed) {
|
||||
unsafe { EXECUTOR.assume_init_ref() }
|
||||
unsafe { &*(EXECUTOR.get() as *const Executor) }
|
||||
} else {
|
||||
unsafe {
|
||||
let executor = EXECUTOR.write(Executor::new());
|
||||
let executorp = EXECUTOR.get() as *mut Executor;
|
||||
executorp.write(Executor::new());
|
||||
INIT.store(true, Ordering::Relaxed);
|
||||
&*executor
|
||||
&*executorp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ pub fn block_on<T>(f: impl Future<Output = T>) -> T {
|
||||
/// Spawns a task onto the executor
|
||||
///
|
||||
/// The spawned task will not make any progress until `block_on` is called.
|
||||
pub fn spawn(f: impl Future<Output = ()> + 'static) {
|
||||
pub fn spawn(f: impl Future + 'static) {
|
||||
executor::current().spawn(f)
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{I2c, Error};
|
||||
use super::I2c;
|
||||
use crate::time::Milliseconds;
|
||||
use embedded_hal::timer::CountDown;
|
||||
|
||||
@ -35,25 +35,25 @@ impl<'a> EEPROM<'a> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "target_zc706")]
|
||||
fn select(&mut self) -> Result<(), Error> {
|
||||
fn select(&mut self) -> Result<(), &'static str> {
|
||||
self.i2c.pca954x_select(0b1110100, Some(self.port))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "target_kasli_soc")]
|
||||
fn select(&mut self) -> Result<(), Error> {
|
||||
fn select(&mut self) -> Result<(), &'static str> {
|
||||
// tca9548 is compatible with pca9548
|
||||
self.i2c.pca954x_select(0b1110001, Some(self.port))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "target_ebaz4205")]
|
||||
fn select(&mut self) -> Result<(), Error> {
|
||||
fn select(&mut self) -> Result<(), &'static str> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Random read
|
||||
pub fn read<'r>(&mut self, addr: u8, buf: &'r mut [u8]) -> Result<(), Error> {
|
||||
pub fn read<'r>(&mut self, addr: u8, buf: &'r mut [u8]) -> Result<(), &'static str> {
|
||||
self.select()?;
|
||||
|
||||
self.i2c.start()?;
|
||||
@ -78,7 +78,7 @@ impl<'a> EEPROM<'a> {
|
||||
/// (i.e. `addr+buf.len()` < `addr/self.page_size+1`); otherwise, a roll-oever occurs,
|
||||
/// where bytes beyond the page end. This smart function takes care of the scenario to avoid
|
||||
/// any roll-over when writing ambiguous memory regions.
|
||||
pub fn write(&mut self, addr: u8, buf: &[u8]) -> Result<(), Error> {
|
||||
pub fn write(&mut self, addr: u8, buf: &[u8]) -> Result<(), &'static str> {
|
||||
self.select()?;
|
||||
|
||||
let buf_len = buf.len();
|
||||
@ -103,28 +103,26 @@ impl<'a> EEPROM<'a> {
|
||||
}
|
||||
|
||||
/// Poll
|
||||
pub fn poll(&mut self, timeout_ms: u64) -> Result<(), Error> {
|
||||
pub fn poll(&mut self, timeout_ms: u64) -> Result<(), &'static str> {
|
||||
self.select()?;
|
||||
|
||||
self.count_down.start(Milliseconds(timeout_ms));
|
||||
loop {
|
||||
self.i2c.start()?;
|
||||
let res = self.i2c.write(self.address << 1);
|
||||
let ack = self.i2c.write(self.address << 1)?;
|
||||
self.i2c.stop()?;
|
||||
match res {
|
||||
Ok(()) => break,
|
||||
Err(Error::Nack) => (),
|
||||
Err(e) => return Err(e)
|
||||
}
|
||||
if ack {
|
||||
break
|
||||
};
|
||||
if !self.count_down.waiting() {
|
||||
return Err(Error::PollingTimeout)
|
||||
return Err("I2C polling timeout")
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_eui48<'r>(&mut self) -> Result<[u8; 6], Error> {
|
||||
pub fn read_eui48<'r>(&mut self) -> Result<[u8; 6], &'static str> {
|
||||
let mut buffer = [0u8; 6];
|
||||
self.read(0xFA, &mut buffer)?;
|
||||
Ok(buffer)
|
||||
|
@ -11,7 +11,6 @@ use libregister::{RegisterR, RegisterRW};
|
||||
use libregister::RegisterW;
|
||||
#[cfg(feature = "target_kasli_soc")]
|
||||
use log::info;
|
||||
use log::error;
|
||||
|
||||
pub enum I2cMultiplexer {
|
||||
PCA9548 = 0,
|
||||
@ -19,31 +18,6 @@ pub enum I2cMultiplexer {
|
||||
PCA9547 = 1,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Nack,
|
||||
SCLLow,
|
||||
SDALow,
|
||||
ArbitrationLost,
|
||||
UnknownSwitch,
|
||||
PollingTimeout,
|
||||
OtherError,
|
||||
}
|
||||
|
||||
impl From<Error> for &str {
|
||||
fn from(err: Error) -> &'static str {
|
||||
match err {
|
||||
Error::Nack => "I2C write was not ACKed",
|
||||
Error::SCLLow => "SCL stuck low",
|
||||
Error::SDALow => "SDA stuck low",
|
||||
Error::ArbitrationLost => "SDA arbitration lost",
|
||||
Error::UnknownSwitch => "Unknown response for PCA954X autodetect",
|
||||
Error::PollingTimeout => "I2C polling timeout",
|
||||
Error::OtherError => "other error",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct I2c {
|
||||
regs: regs::RegisterBlock,
|
||||
count_down: super::timer::global::CountDown<Microseconds>,
|
||||
@ -174,7 +148,7 @@ impl I2c {
|
||||
}
|
||||
|
||||
#[cfg(feature = "target_kasli_soc")]
|
||||
fn pca_autodetect(&mut self) -> Result<I2cMultiplexer, Error> {
|
||||
fn pca_autodetect(&mut self) -> Result<I2cMultiplexer, &'static str> {
|
||||
// start with resetting the PCA954X
|
||||
// SDA must be clear (before start)
|
||||
// reset time is 500ns, unit_delay (100us) to account for propagation
|
||||
@ -187,26 +161,21 @@ impl I2c {
|
||||
|
||||
self.start()?;
|
||||
// read the config register
|
||||
self.write(pca954x_read_addr).map_err(|err| {
|
||||
match err {
|
||||
Error::Nack => error!("PCA954X failed to ack read address"),
|
||||
_ => ()
|
||||
}
|
||||
err
|
||||
}
|
||||
)?;
|
||||
if !self.write(pca954x_read_addr)? {
|
||||
return Err("PCA954X failed to ack read address");
|
||||
}
|
||||
let config = self.read(false)?;
|
||||
|
||||
let pca = match config {
|
||||
0x00 => { info!("PCA9548 detected"); I2cMultiplexer::PCA9548 },
|
||||
0x08 => { info!("PCA9547 detected"); I2cMultiplexer::PCA9547 },
|
||||
_ => { return Err(Error::UnknownSwitch)},
|
||||
_ => { return Err("Unknown response for PCA954X autodetect")},
|
||||
};
|
||||
self.stop()?;
|
||||
Ok(pca)
|
||||
}
|
||||
|
||||
pub fn init(&mut self) -> Result<(), Error> {
|
||||
pub fn init(&mut self) -> Result<(), &'static str> {
|
||||
self.scl_oe(false);
|
||||
self.sda_oe(false);
|
||||
self.scl_o(false);
|
||||
@ -226,10 +195,10 @@ impl I2c {
|
||||
}
|
||||
|
||||
if !self.sda_i() {
|
||||
return Err(Error::SDALow);
|
||||
return Err("SDA is stuck low and doesn't get unstuck");
|
||||
}
|
||||
if !self.scl_i() {
|
||||
return Err(Error::SCLLow);
|
||||
return Err("SCL is stuck low");
|
||||
}
|
||||
// postcondition: SCL and SDA high
|
||||
|
||||
@ -242,13 +211,13 @@ impl I2c {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn start(&mut self) -> Result<(), Error> {
|
||||
pub fn start(&mut self) -> Result<(), &'static str> {
|
||||
// precondition: SCL and SDA high
|
||||
if !self.scl_i() {
|
||||
return Err(Error::SCLLow);
|
||||
return Err("SCL is stuck low");
|
||||
}
|
||||
if !self.sda_i() {
|
||||
return Err(Error::ArbitrationLost);
|
||||
return Err("SDA arbitration lost");
|
||||
}
|
||||
self.sda_oe(true);
|
||||
self.unit_delay();
|
||||
@ -258,7 +227,7 @@ impl I2c {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn restart(&mut self) -> Result<(), Error> {
|
||||
pub fn restart(&mut self) -> Result<(), &'static str> {
|
||||
// precondition SCL and SDA low
|
||||
self.sda_oe(false);
|
||||
self.unit_delay();
|
||||
@ -269,7 +238,7 @@ impl I2c {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn stop(&mut self) -> Result<(), Error> {
|
||||
pub fn stop(&mut self) -> Result<(), &'static str> {
|
||||
// precondition: SCL and SDA low
|
||||
self.unit_delay();
|
||||
self.scl_oe(false);
|
||||
@ -277,13 +246,13 @@ impl I2c {
|
||||
self.sda_oe(false);
|
||||
self.unit_delay();
|
||||
if !self.sda_i() {
|
||||
return Err(Error::ArbitrationLost);
|
||||
return Err("SDA arbitration lost");
|
||||
}
|
||||
// postcondition: SCL and SDA high
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write(&mut self, data: u8) -> Result<(), Error> {
|
||||
pub fn write(&mut self, data: u8) -> Result<bool, &'static str> {
|
||||
// precondition: SCL and SDA low
|
||||
// MSB first
|
||||
for bit in (0..8).rev() {
|
||||
@ -305,10 +274,10 @@ impl I2c {
|
||||
self.sda_oe(true);
|
||||
// postcondition: SCL and SDA low
|
||||
|
||||
if ack { Ok(()) } else { Err(Error::Nack) }
|
||||
Ok(ack)
|
||||
}
|
||||
|
||||
pub fn read(&mut self, ack: bool) -> Result<u8, Error> {
|
||||
pub fn read(&mut self, ack: bool) -> Result<u8, &'static str> {
|
||||
// precondition: SCL and SDA low
|
||||
self.sda_oe(false);
|
||||
|
||||
@ -334,7 +303,7 @@ impl I2c {
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
pub fn pca954x_select(&mut self, address: u8, channel: Option<u8>) -> Result<(), Error> {
|
||||
pub fn pca954x_select(&mut self, address: u8, channel: Option<u8>) -> Result<(), &'static str> {
|
||||
self.start()?;
|
||||
// PCA9547 supports only one channel at a time
|
||||
// for compatibility, PCA9548 is treated as such too
|
||||
@ -355,16 +324,13 @@ impl I2c {
|
||||
}
|
||||
};
|
||||
|
||||
let write_res = self.write(address << 1).or_else( |err| {
|
||||
error!("PCA954X write address fail: {:?}", err);
|
||||
Err(err)
|
||||
}).and_then(|_| self.write(setting).or_else(|err| {
|
||||
error!("PCA954X control word fail: {:?}", err);
|
||||
Err(err)
|
||||
})
|
||||
);
|
||||
let stop_res = self.stop();
|
||||
|
||||
write_res.and(stop_res)
|
||||
if !self.write(address << 1)? {
|
||||
return Err("PCA954X failed to ack write address")
|
||||
}
|
||||
if !self.write(setting)? {
|
||||
return Err("PCA954X failed to ack control word")
|
||||
}
|
||||
self.stop()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ use super::time::Milliseconds;
|
||||
use embedded_hal::timer::CountDown;
|
||||
use libregister::{RegisterR, RegisterRW, RegisterW};
|
||||
use log::{trace, debug};
|
||||
use nb;
|
||||
|
||||
/// Basic SDIO Struct with common low-level functions.
|
||||
pub struct Sdio {
|
||||
|
@ -1,4 +1,5 @@
|
||||
use core_io::{BufRead, Error, ErrorKind, Read, Result as IoResult, Seek, SeekFrom, Write};
|
||||
use fatfs;
|
||||
use libboard_zynq::sdio::{sd_card::SdCard, CmdTransferError};
|
||||
use log::debug;
|
||||
use alloc::vec::Vec;
|
||||
|
@ -137,15 +137,15 @@ fn cache_line_addrs(first_addr: usize, beyond_addr: usize) -> impl Iterator<Item
|
||||
(first_addr..beyond_addr).step_by(CACHE_LINE)
|
||||
}
|
||||
|
||||
fn object_cache_line_addrs<T>(object: *const T) -> impl Iterator<Item = usize> {
|
||||
let first_addr = object.addr();
|
||||
let beyond_addr = object.addr() + core::mem::size_of::<T>();
|
||||
fn object_cache_line_addrs<T>(object: &T) -> impl Iterator<Item = usize> {
|
||||
let first_addr = object as *const _ as usize;
|
||||
let beyond_addr = (object as *const _ as usize) + core::mem::size_of_val(object);
|
||||
cache_line_addrs(first_addr, beyond_addr)
|
||||
}
|
||||
|
||||
fn slice_cache_line_addrs<T>(slice: &[T]) -> impl Iterator<Item = usize> {
|
||||
let first_addr = (&raw const slice[0]).addr();
|
||||
let beyond_addr = (&raw const slice[slice.len() - 1]).addr() +
|
||||
let first_addr = &slice[0] as *const _ as usize;
|
||||
let beyond_addr = (&slice[slice.len() - 1] as *const _ as usize) +
|
||||
core::mem::size_of_val(&slice[slice.len() - 1]);
|
||||
cache_line_addrs(first_addr, beyond_addr)
|
||||
}
|
||||
@ -162,7 +162,7 @@ pub fn dccimvac(addr: usize) {
|
||||
}
|
||||
|
||||
/// Data cache clean and invalidate for an object.
|
||||
pub fn dcci<T>(object: *const T) {
|
||||
pub fn dcci<T>(object: &T) {
|
||||
// ref: L2C310 TRM 3.3.10
|
||||
dmb();
|
||||
for addr in object_cache_line_addrs(object) {
|
||||
@ -203,7 +203,7 @@ pub fn dccmvac(addr: usize) {
|
||||
}
|
||||
}
|
||||
/// Data cache clean for an object.
|
||||
pub fn dcc<T>(object: *const T) {
|
||||
pub fn dcc<T>(object: &T) {
|
||||
dmb();
|
||||
for addr in object_cache_line_addrs(object) {
|
||||
dccmvac(addr);
|
||||
|
@ -1,8 +1,10 @@
|
||||
#![no_std]
|
||||
#![feature(never_type)]
|
||||
#![feature(global_asm)]
|
||||
#![feature(asm)]
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(inline_const)]
|
||||
#![feature(strict_provenance)]
|
||||
#![feature(raw_ref_op)]
|
||||
#![feature(const_fn_trait_bound)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
use core::cell::UnsafeCell;
|
||||
use bit_field::BitField;
|
||||
use super::{regs::*, asm::*, cache::*};
|
||||
use libregister::RegisterW;
|
||||
@ -125,9 +124,9 @@ impl L1Entry {
|
||||
}
|
||||
|
||||
const L1_TABLE_SIZE: usize = 4096;
|
||||
static mut L1_TABLE: UnsafeCell<L1Table> = UnsafeCell::new(L1Table {
|
||||
static mut L1_TABLE: L1Table = L1Table {
|
||||
table: [L1Entry(0); L1_TABLE_SIZE]
|
||||
});
|
||||
};
|
||||
|
||||
#[repr(C, align(16384))]
|
||||
pub struct L1Table {
|
||||
@ -136,7 +135,9 @@ pub struct L1Table {
|
||||
|
||||
impl L1Table {
|
||||
pub fn get() -> &'static mut Self {
|
||||
unsafe { L1_TABLE.get_mut() }
|
||||
unsafe {
|
||||
&mut L1_TABLE
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setup_flat_layout(&mut self) -> &Self {
|
||||
|
@ -37,7 +37,7 @@ impl<'a, T> Sender<'a, T> where T: Clone {
|
||||
notify_spin_lock();
|
||||
if !prev.is_null() {
|
||||
unsafe {
|
||||
let _ = Box::from_raw(prev);
|
||||
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() {
|
||||
let _ = Box::from_raw(original);
|
||||
Box::from_raw(original);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -177,7 +177,10 @@ macro_rules! sync_channel {
|
||||
{
|
||||
use core::sync::atomic::{AtomicUsize, AtomicPtr};
|
||||
use $crate::sync_channel::{Sender, Receiver};
|
||||
static LIST: [AtomicPtr<$t>; $cap + 1] = [const { AtomicPtr::new(core::ptr::null_mut()) }; $cap + 1];
|
||||
const fn new_atomic() -> AtomicPtr<$t> {
|
||||
AtomicPtr::new(core::ptr::null_mut())
|
||||
}
|
||||
static LIST: [AtomicPtr<$t>; $cap + 1] = [const { new_atomic() }; $cap + 1];
|
||||
static WRITE: AtomicUsize = AtomicUsize::new(0);
|
||||
static READ: AtomicUsize = AtomicUsize::new(0);
|
||||
(Sender::new(&LIST, &WRITE, &READ), Receiver::new(&LIST, &WRITE, &READ))
|
||||
|
@ -20,7 +20,7 @@ default = ["panic_handler", "dummy_irq_handler", "dummy_fiq_handler"]
|
||||
|
||||
[dependencies]
|
||||
r0 = "1"
|
||||
compiler_builtins = "=0.1.108"
|
||||
compiler_builtins = "=0.1.49"
|
||||
linked_list_allocator = { version = "0.8", default-features = false, features = ["const_mut_refs"] }
|
||||
libregister = { path = "../libregister" }
|
||||
libcortex_a9 = { path = "../libcortex_a9" }
|
||||
|
@ -43,11 +43,10 @@ unsafe extern "C" fn boot_core0() -> ! {
|
||||
let mpcore = mpcore::RegisterBlock::mpcore();
|
||||
mpcore.scu_invalidate.invalidate_all_cores();
|
||||
|
||||
zero_bss(&raw mut __bss_start, &raw mut __bss_end);
|
||||
zero_bss(&mut __bss_start, &mut __bss_end);
|
||||
|
||||
let mmu_table = mmu::L1Table::get()
|
||||
.setup_flat_layout();
|
||||
cache::dcc(mmu_table);
|
||||
mmu::with_mmu(mmu_table, || {
|
||||
mpcore.scu_control.start();
|
||||
ACTLR.enable_smp();
|
||||
@ -67,7 +66,6 @@ unsafe extern "C" fn boot_core0() -> ! {
|
||||
unsafe extern "C" fn boot_core1() -> ! {
|
||||
l1_cache_init();
|
||||
|
||||
enable_fpu();
|
||||
let mpcore = mpcore::RegisterBlock::mpcore();
|
||||
mpcore.scu_invalidate.invalidate_core1();
|
||||
|
||||
@ -134,7 +132,7 @@ impl Core1 {
|
||||
CORE1_ENABLED.set(true);
|
||||
}
|
||||
// Flush cache-line
|
||||
cache::dcc(unsafe { &raw const CORE1_ENABLED });
|
||||
cache::dcc(unsafe { &CORE1_ENABLED });
|
||||
if sdram {
|
||||
cache::dccmvac(0);
|
||||
asm::dsb();
|
||||
@ -155,7 +153,7 @@ impl Core1 {
|
||||
pub fn disable(&self) {
|
||||
unsafe {
|
||||
CORE1_ENABLED.set(false);
|
||||
cache::dccmvac((&raw const CORE1_ENABLED).addr());
|
||||
cache::dccmvac(&CORE1_ENABLED as *const _ as usize);
|
||||
asm::dsb();
|
||||
}
|
||||
self.restart();
|
||||
|
@ -3,8 +3,8 @@
|
||||
#![feature(alloc_error_handler)]
|
||||
#![feature(panic_info_message)]
|
||||
#![feature(naked_functions)]
|
||||
#![feature(strict_provenance)]
|
||||
#![feature(raw_ref_op)]
|
||||
#![feature(global_asm)]
|
||||
#![feature(asm)]
|
||||
|
||||
pub extern crate alloc;
|
||||
pub extern crate compiler_builtins;
|
||||
|
@ -1,9 +1,6 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#![feature(strict_provenance)]
|
||||
#![feature(raw_ref_op)]
|
||||
|
||||
extern crate alloc;
|
||||
extern crate log;
|
||||
|
||||
@ -119,18 +116,18 @@ pub fn main_core0() {
|
||||
|
||||
unsafe {
|
||||
let max_len =
|
||||
(&raw const __runtime_end).addr() - (&raw const __runtime_start).addr();
|
||||
&__runtime_end as *const usize as usize - &__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,
|
||||
(&raw mut __runtime_start).cast(),
|
||||
&mut __runtime_start as *mut usize as *mut u8,
|
||||
max_len,
|
||||
),
|
||||
slcr::BootModePins::SdCard => {
|
||||
if boot_sd(
|
||||
&mut bootgen_file,
|
||||
(&raw mut __runtime_start).cast(),
|
||||
&mut __runtime_start as *mut usize as *mut u8,
|
||||
max_len,
|
||||
)
|
||||
.is_err()
|
||||
@ -140,7 +137,7 @@ pub fn main_core0() {
|
||||
netboot::netboot(
|
||||
&mut bootgen_file,
|
||||
config,
|
||||
(&raw mut __runtime_start).cast(),
|
||||
&mut __runtime_start as *mut usize as *mut u8,
|
||||
max_len,
|
||||
)
|
||||
}
|
||||
@ -151,7 +148,7 @@ pub fn main_core0() {
|
||||
netboot::netboot(
|
||||
&mut bootgen_file,
|
||||
config,
|
||||
(&raw mut __runtime_start).cast(),
|
||||
&mut __runtime_start as *mut usize as *mut u8,
|
||||
max_len,
|
||||
)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user