Compare commits

...

4 Commits

12 changed files with 207 additions and 11 deletions

4
Cargo.lock generated
View File

@ -38,6 +38,7 @@ dependencies = [
name = "experiments"
version = "0.0.0"
dependencies = [
"embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libasync 0.0.0",
"libboard_zynq 0.0.0",
"libcortex_a9 0.0.0",
@ -50,8 +51,10 @@ dependencies = [
name = "libasync"
version = "0.0.0"
dependencies = [
"embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libboard_zynq 0.0.0",
"libcortex_a9 0.0.0",
"nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)",
"smoltcp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -66,6 +69,7 @@ dependencies = [
"libregister 0.0.0",
"nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"smoltcp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

View File

@ -12,6 +12,7 @@ default = ["target_zc706"]
[dependencies]
log = "0.4"
embedded-hal = "0.2"
libregister = { path = "../libregister" }
libcortex_a9 = { path = "../libcortex_a9" }
libboard_zynq = { path = "../libboard_zynq" }

View File

@ -6,6 +6,8 @@ extern crate alloc;
use core::{mem::transmute, task::Poll};
use alloc::{borrow::ToOwned, collections::BTreeMap, format};
use log::info;
use embedded_hal::timer::CountDown;
use libregister::RegisterR;
use libcortex_a9::{mutex::Mutex, sync_channel::{self, sync_channel}};
use libboard_zynq::{
print, println,
@ -18,12 +20,13 @@ use libboard_zynq::{
socket::SocketSet,
socket::{TcpSocket, TcpSocketBuffer},
},
time::Milliseconds,
};
use libsupport_zynq::{
ram, alloc::{vec, vec::Vec},
boot,
};
use libasync::{smoltcp::{Sockets, TcpStream}, task};
use libasync::{delay, smoltcp::{Sockets, TcpStream}, task};
mod ps7_init;
@ -39,10 +42,7 @@ pub fn main_core0() {
libsupport_zynq::logger::init().unwrap();
log::set_max_level(log::LevelFilter::Trace);
{
use libregister::RegisterR;
info!("Boot mode: {:?}", zynq::slcr::RegisterBlock::new().boot_mode.read().boot_mode_pins());
}
info!("Boot mode: {:?}", zynq::slcr::RegisterBlock::new().boot_mode.read().boot_mode_pins());
#[cfg(feature = "target_zc706")]
const CPU_FREQ: u32 = 800_000_000;
@ -72,6 +72,8 @@ pub fn main_core0() {
}
let mut flash = flash.stop();
let timer = libboard_zynq::timer::GlobalTimer::new();
let mut ddr = zynq::ddr::DdrRam::new();
#[cfg(not(feature = "target_zc706"))]
ddr.memtest();
@ -262,10 +264,16 @@ pub fn main_core0() {
}
});
let mut time = 0u32;
let mut countdown = timer.countdown();
task::spawn(async move {
loop {
delay(&mut countdown, Milliseconds(1000)).await;
println!("time: {} ms", timer.get_time().0);
}
});
Sockets::run(&mut iface, || {
time += 1;
Instant::from_millis(time)
Instant::from_millis(timer.get_time().0 as i64)
})
}

View File

@ -8,6 +8,8 @@ edition = "2018"
[dependencies]
#futures = { version = "0.3", default-features = false }
pin-utils = "0.1.0-alpha.4"
embedded-hal = "0.2"
nb = "0.1"
libcortex_a9 = { path = "../libcortex_a9" }
[dependencies.smoltcp]

View File

@ -4,5 +4,33 @@ extern crate alloc;
pub mod task;
pub mod executor;
mod delay;
pub use delay::delay;
pub mod smoltcp;
/// Reexport for macro use
pub use nb;
/// The `nb` crate's `block!` macro adapted for async fns
///
/// Call `.await` on the result!
#[macro_export]
macro_rules! block_async {
($e:expr) => {
async {
loop {
#[allow(unreachable_patterns)]
match $e {
Err($crate::nb::Error::Other(e)) => {
#[allow(unreachable_code)]
break Err(e)
},
Err($crate::nb::Error::WouldBlock) =>
$crate::task::r#yield().await,
Ok(x) => break Ok(x),
}
}
}
}
}

View File

@ -14,6 +14,7 @@ volatile-register = "0.2"
bit_field = "0.10"
embedded-hal = "0.2"
nb = "0.1"
void = { version = "1", default-features = false }
libregister = { path = "../libregister" }
libcortex_a9 = { path = "../libcortex_a9" }

View File

@ -15,3 +15,5 @@ pub mod ddr;
pub mod mpcore;
pub mod flash;
pub mod dmac;
pub mod time;
pub mod timer;

View File

@ -18,6 +18,34 @@ pub struct RegisterBlock {
reserved1: [u32; 2],
pub scu_access_control: RW<u32>,
pub scu_non_secure_access_control: RW<u32>,
reserved2: [u32; 42],
pub iccicr: RW<u32>,
pub iccpmw: RW<u32>,
pub iccbpr: RW<u32>,
pub icciar: RW<u32>,
pub icceoir: RW<u32>,
pub iccrpr: RW<u32>,
pub icchpir: RW<u32>,
pub iccabpr: RW<u32>,
reserved3: [u32; 55],
pub iccidr: RW<u32>,
pub global_timer_counter0: ValueRegister,
pub global_timer_counter1: ValueRegister,
pub global_timer_control: GlobalTimerControl,
pub global_timer_interrupt_status: RW<u32>,
pub comparator_value0: ValueRegister,
pub comparator_value1: ValueRegister,
pub auto_increment: ValueRegister,
reserved4: [u32; 249],
pub private_timer_load: ValueRegister,
pub private_timer_counter: ValueRegister,
pub private_timer_control: RW<u32>,
pub private_timer_interrupt_status: RW<u32>,
reserved5: [u32; 4],
pub watchdog_load: ValueRegister,
pub watchdog_counter: ValueRegister,
pub watchdog_control: RW<u32>,
pub watchdog_interrupt_status: RW<u32>,
// there is plenty more (unimplemented)
}
register_at!(RegisterBlock, 0xF8F00000, new);
@ -59,3 +87,13 @@ impl ScuInvalidate {
);
}
}
register!(value_register, ValueRegister, RW, u32);
register_bits!(value_register, value, u32, 0, 31);
register!(global_timer_control, GlobalTimerControl, RW, u32);
register_bits!(global_timer_control, prescaler, u16, 8, 15);
register_bit!(global_timer_control, auto_increment_mode, 3);
register_bit!(global_timer_control, irq_enable, 2);
register_bit!(global_timer_control, comp_enablea, 1);
register_bit!(global_timer_control, timer_enable, 0);

10
libboard_zynq/src/time.rs Normal file
View File

@ -0,0 +1,10 @@
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Milliseconds(pub u64);
impl core::ops::Add for Milliseconds {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Milliseconds(self.0 + rhs.0)
}
}

View File

@ -0,0 +1,99 @@
use void::Void;
use libregister::{RegisterR, RegisterW};
use crate::{
clocks::Clocks,
mpcore,
time::Milliseconds,
};
/// "uptime"
#[derive(Clone, Copy)]
pub struct GlobalTimer {
regs: &'static mpcore::RegisterBlock,
}
impl GlobalTimer {
pub fn new() -> GlobalTimer {
let mut regs = mpcore::RegisterBlock::new();
Self::reset(&mut regs);
GlobalTimer { regs }
}
fn reset(regs: &mut mpcore::RegisterBlock) {
// Disable
regs.global_timer_control.write(
mpcore::GlobalTimerControl::zeroed()
);
// Reset counters
regs.global_timer_counter0.write(
mpcore::ValueRegister::zeroed()
);
regs.global_timer_counter1.write(
mpcore::ValueRegister::zeroed()
);
// Start
regs.global_timer_control.write(
mpcore::GlobalTimerControl::zeroed()
// maximum prescaler is still enough for millisecond
// precision while overflowing after centuries.
.prescaler(255)
.auto_increment_mode(true)
.timer_enable(true)
);
}
/// read the raw counter value
pub fn get_counter(&self) -> u64 {
loop {
let c1_pre = self.regs.global_timer_counter1.read().value();
let c0 = self.regs.global_timer_counter0.read().value();
let c1_post = self.regs.global_timer_counter1.read().value();
if c1_pre == c1_post {
return ((c1_pre as u64) << 32) | (c0 as u64);
}
// retry if c0 has wrapped while reading.
}
}
/// read and convert to time
pub fn get_time(&self) -> Milliseconds {
let prescaler = self.regs.global_timer_control.read().prescaler() as u64;
let clocks = Clocks::get();
Milliseconds(self.get_counter() * (prescaler + 1) / (clocks.cpu_3x2x() as u64 / 1000))
}
/// return a handle that has implements
/// `embedded_hal::timer::CountDown`
pub fn countdown(&self) -> CountDown {
CountDown {
timer: self.clone(),
timeout: Milliseconds(0),
}
}
}
#[derive(Clone)]
pub struct CountDown {
timer: GlobalTimer,
timeout: Milliseconds,
}
impl embedded_hal::timer::CountDown for CountDown {
type Time = Milliseconds;
fn start<T: Into<Self::Time>>(&mut self, count: T) {
self.timeout = self.timer.get_time() + count.into();
}
fn wait(&mut self) -> nb::Result<(), Void> {
if self.timer.get_time() < self.timeout {
Err(nb::Error::WouldBlock)
} else {
Ok(())
}
}
}

View File

@ -0,0 +1,2 @@
pub mod global;
pub use global::GlobalTimer;

View File

@ -1,4 +1,5 @@
use core::fmt;
use void::Void;
use libregister::*;
use super::slcr;
@ -209,9 +210,9 @@ impl fmt::Write for Uart {
/// embedded_hal async API
impl embedded_hal::serial::Write<u8> for Uart {
type Error = ();
type Error = Void;
fn write(&mut self, b: u8) -> nb::Result<(), ()> {
fn write(&mut self, b: u8) -> nb::Result<(), Void> {
if self.tx_fifo_full() {
Err(nb::Error::WouldBlock)
} else {
@ -220,7 +221,7 @@ impl embedded_hal::serial::Write<u8> for Uart {
}
}
fn flush(&mut self) -> nb::Result<(), ()> {
fn flush(&mut self) -> nb::Result<(), Void> {
if self.tx_fifo_empty() {
Ok(())
} else {