Compare commits
4 Commits
04c47b9bdb
...
88a2a2bc71
Author | SHA1 | Date |
---|---|---|
Astro | 88a2a2bc71 | |
Astro | 8012573a8f | |
Astro | 4ab6fb6271 | |
Astro | f835192c0a |
|
@ -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)",
|
||||
]
|
||||
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
#[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)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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" }
|
||||
|
||||
|
|
|
@ -15,3 +15,5 @@ pub mod ddr;
|
|||
pub mod mpcore;
|
||||
pub mod flash;
|
||||
pub mod dmac;
|
||||
pub mod time;
|
||||
pub mod timer;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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(())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
pub mod global;
|
||||
pub use global::GlobalTimer;
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue