Compare commits
4 Commits
04c47b9bdb
...
88a2a2bc71
Author | SHA1 | Date |
---|---|---|
Astro | 88a2a2bc71 | |
Astro | 8012573a8f | |
Astro | 4ab6fb6271 | |
Astro | f835192c0a |
|
@ -38,6 +38,7 @@ dependencies = [
|
||||||
name = "experiments"
|
name = "experiments"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libasync 0.0.0",
|
"libasync 0.0.0",
|
||||||
"libboard_zynq 0.0.0",
|
"libboard_zynq 0.0.0",
|
||||||
"libcortex_a9 0.0.0",
|
"libcortex_a9 0.0.0",
|
||||||
|
@ -50,8 +51,10 @@ dependencies = [
|
||||||
name = "libasync"
|
name = "libasync"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libboard_zynq 0.0.0",
|
"libboard_zynq 0.0.0",
|
||||||
"libcortex_a9 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)",
|
"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)",
|
"smoltcp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
@ -66,6 +69,7 @@ dependencies = [
|
||||||
"libregister 0.0.0",
|
"libregister 0.0.0",
|
||||||
"nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ default = ["target_zc706"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
embedded-hal = "0.2"
|
||||||
libregister = { path = "../libregister" }
|
libregister = { path = "../libregister" }
|
||||||
libcortex_a9 = { path = "../libcortex_a9" }
|
libcortex_a9 = { path = "../libcortex_a9" }
|
||||||
libboard_zynq = { path = "../libboard_zynq" }
|
libboard_zynq = { path = "../libboard_zynq" }
|
||||||
|
|
|
@ -6,6 +6,8 @@ extern crate alloc;
|
||||||
use core::{mem::transmute, task::Poll};
|
use core::{mem::transmute, task::Poll};
|
||||||
use alloc::{borrow::ToOwned, collections::BTreeMap, format};
|
use alloc::{borrow::ToOwned, collections::BTreeMap, format};
|
||||||
use log::info;
|
use log::info;
|
||||||
|
use embedded_hal::timer::CountDown;
|
||||||
|
use libregister::RegisterR;
|
||||||
use libcortex_a9::{mutex::Mutex, sync_channel::{self, sync_channel}};
|
use libcortex_a9::{mutex::Mutex, sync_channel::{self, sync_channel}};
|
||||||
use libboard_zynq::{
|
use libboard_zynq::{
|
||||||
print, println,
|
print, println,
|
||||||
|
@ -18,12 +20,13 @@ use libboard_zynq::{
|
||||||
socket::SocketSet,
|
socket::SocketSet,
|
||||||
socket::{TcpSocket, TcpSocketBuffer},
|
socket::{TcpSocket, TcpSocketBuffer},
|
||||||
},
|
},
|
||||||
|
time::Milliseconds,
|
||||||
};
|
};
|
||||||
use libsupport_zynq::{
|
use libsupport_zynq::{
|
||||||
ram, alloc::{vec, vec::Vec},
|
ram, alloc::{vec, vec::Vec},
|
||||||
boot,
|
boot,
|
||||||
};
|
};
|
||||||
use libasync::{smoltcp::{Sockets, TcpStream}, task};
|
use libasync::{delay, smoltcp::{Sockets, TcpStream}, task};
|
||||||
|
|
||||||
mod ps7_init;
|
mod ps7_init;
|
||||||
|
|
||||||
|
@ -39,10 +42,7 @@ pub fn main_core0() {
|
||||||
libsupport_zynq::logger::init().unwrap();
|
libsupport_zynq::logger::init().unwrap();
|
||||||
log::set_max_level(log::LevelFilter::Trace);
|
log::set_max_level(log::LevelFilter::Trace);
|
||||||
|
|
||||||
{
|
info!("Boot mode: {:?}", zynq::slcr::RegisterBlock::new().boot_mode.read().boot_mode_pins());
|
||||||
use libregister::RegisterR;
|
|
||||||
info!("Boot mode: {:?}", zynq::slcr::RegisterBlock::new().boot_mode.read().boot_mode_pins());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(feature = "target_zc706")]
|
||||||
const CPU_FREQ: u32 = 800_000_000;
|
const CPU_FREQ: u32 = 800_000_000;
|
||||||
|
@ -72,6 +72,8 @@ pub fn main_core0() {
|
||||||
}
|
}
|
||||||
let mut flash = flash.stop();
|
let mut flash = flash.stop();
|
||||||
|
|
||||||
|
let timer = libboard_zynq::timer::GlobalTimer::new();
|
||||||
|
|
||||||
let mut ddr = zynq::ddr::DdrRam::new();
|
let mut ddr = zynq::ddr::DdrRam::new();
|
||||||
#[cfg(not(feature = "target_zc706"))]
|
#[cfg(not(feature = "target_zc706"))]
|
||||||
ddr.memtest();
|
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, || {
|
Sockets::run(&mut iface, || {
|
||||||
time += 1;
|
Instant::from_millis(timer.get_time().0 as i64)
|
||||||
Instant::from_millis(time)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@ edition = "2018"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
#futures = { version = "0.3", default-features = false }
|
#futures = { version = "0.3", default-features = false }
|
||||||
pin-utils = "0.1.0-alpha.4"
|
pin-utils = "0.1.0-alpha.4"
|
||||||
|
embedded-hal = "0.2"
|
||||||
|
nb = "0.1"
|
||||||
libcortex_a9 = { path = "../libcortex_a9" }
|
libcortex_a9 = { path = "../libcortex_a9" }
|
||||||
|
|
||||||
[dependencies.smoltcp]
|
[dependencies.smoltcp]
|
||||||
|
|
|
@ -4,5 +4,33 @@ extern crate alloc;
|
||||||
|
|
||||||
pub mod task;
|
pub mod task;
|
||||||
pub mod executor;
|
pub mod executor;
|
||||||
|
mod delay;
|
||||||
|
pub use delay::delay;
|
||||||
|
|
||||||
pub mod smoltcp;
|
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"
|
bit_field = "0.10"
|
||||||
embedded-hal = "0.2"
|
embedded-hal = "0.2"
|
||||||
nb = "0.1"
|
nb = "0.1"
|
||||||
|
void = { version = "1", default-features = false }
|
||||||
libregister = { path = "../libregister" }
|
libregister = { path = "../libregister" }
|
||||||
libcortex_a9 = { path = "../libcortex_a9" }
|
libcortex_a9 = { path = "../libcortex_a9" }
|
||||||
|
|
||||||
|
|
|
@ -15,3 +15,5 @@ pub mod ddr;
|
||||||
pub mod mpcore;
|
pub mod mpcore;
|
||||||
pub mod flash;
|
pub mod flash;
|
||||||
pub mod dmac;
|
pub mod dmac;
|
||||||
|
pub mod time;
|
||||||
|
pub mod timer;
|
||||||
|
|
|
@ -18,6 +18,34 @@ pub struct RegisterBlock {
|
||||||
reserved1: [u32; 2],
|
reserved1: [u32; 2],
|
||||||
pub scu_access_control: RW<u32>,
|
pub scu_access_control: RW<u32>,
|
||||||
pub scu_non_secure_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)
|
// there is plenty more (unimplemented)
|
||||||
}
|
}
|
||||||
register_at!(RegisterBlock, 0xF8F00000, new);
|
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 core::fmt;
|
||||||
|
use void::Void;
|
||||||
|
|
||||||
use libregister::*;
|
use libregister::*;
|
||||||
use super::slcr;
|
use super::slcr;
|
||||||
|
@ -209,9 +210,9 @@ impl fmt::Write for Uart {
|
||||||
|
|
||||||
/// embedded_hal async API
|
/// embedded_hal async API
|
||||||
impl embedded_hal::serial::Write<u8> for Uart {
|
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() {
|
if self.tx_fifo_full() {
|
||||||
Err(nb::Error::WouldBlock)
|
Err(nb::Error::WouldBlock)
|
||||||
} else {
|
} 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() {
|
if self.tx_fifo_empty() {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue