From 88a2a2bc7155722b6f69a1d4ca3fb09c6fb00adf Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 25 Apr 2020 01:18:49 +0200 Subject: [PATCH] libasync, libboard_zynq: add block_async glue, make GlobalTimer sharable --- Cargo.lock | 3 +++ experiments/Cargo.toml | 1 + experiments/src/main.rs | 24 ++++++++++++++++-------- libasync/Cargo.toml | 2 ++ libasync/src/lib.rs | 28 ++++++++++++++++++++++++++++ libboard_zynq/src/time.rs | 8 ++++++++ libboard_zynq/src/timer/global.rs | 26 ++++++++++++++------------ 7 files changed, 72 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c42bfe4..9095208 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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)", ] diff --git a/experiments/Cargo.toml b/experiments/Cargo.toml index ddf863d..3a7794c 100644 --- a/experiments/Cargo.toml +++ b/experiments/Cargo.toml @@ -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" } diff --git a/experiments/src/main.rs b/experiments/src/main.rs index af2a125..50a117d 100644 --- a/experiments/src/main.rs +++ b/experiments/src/main.rs @@ -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) }) } diff --git a/libasync/Cargo.toml b/libasync/Cargo.toml index 3858977..ca62fae 100644 --- a/libasync/Cargo.toml +++ b/libasync/Cargo.toml @@ -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] diff --git a/libasync/src/lib.rs b/libasync/src/lib.rs index 0478fb3..2e78c75 100644 --- a/libasync/src/lib.rs +++ b/libasync/src/lib.rs @@ -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), + } + } + } + } +} diff --git a/libboard_zynq/src/time.rs b/libboard_zynq/src/time.rs index f82c8fb..e012714 100644 --- a/libboard_zynq/src/time.rs +++ b/libboard_zynq/src/time.rs @@ -1,2 +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) + } +} diff --git a/libboard_zynq/src/timer/global.rs b/libboard_zynq/src/timer/global.rs index e671e06..758e890 100644 --- a/libboard_zynq/src/timer/global.rs +++ b/libboard_zynq/src/timer/global.rs @@ -7,32 +7,34 @@ use crate::{ }; /// "uptime" +#[derive(Clone, Copy)] pub struct GlobalTimer { - regs: &'static mut mpcore::RegisterBlock, + regs: &'static mpcore::RegisterBlock, } impl GlobalTimer { pub fn new() -> GlobalTimer { - let regs = mpcore::RegisterBlock::new(); + let mut regs = mpcore::RegisterBlock::new(); + Self::reset(&mut regs); GlobalTimer { regs } } - pub fn reset(&mut self) { + fn reset(regs: &mut mpcore::RegisterBlock) { // Disable - self.regs.global_timer_control.write( + regs.global_timer_control.write( mpcore::GlobalTimerControl::zeroed() ); // Reset counters - self.regs.global_timer_counter0.write( + regs.global_timer_counter0.write( mpcore::ValueRegister::zeroed() ); - self.regs.global_timer_counter1.write( + regs.global_timer_counter1.write( mpcore::ValueRegister::zeroed() ); // Start - self.regs.global_timer_control.write( + regs.global_timer_control.write( mpcore::GlobalTimerControl::zeroed() // maximum prescaler is still enough for millisecond // precision while overflowing after centuries. @@ -68,23 +70,23 @@ impl GlobalTimer { /// `embedded_hal::timer::CountDown` pub fn countdown(&self) -> CountDown { CountDown { - timer: &self, + timer: self.clone(), timeout: Milliseconds(0), } } } #[derive(Clone)] -pub struct CountDown<'a> { - timer: &'a GlobalTimer, +pub struct CountDown { + timer: GlobalTimer, timeout: Milliseconds, } -impl embedded_hal::timer::CountDown for CountDown<'_> { +impl embedded_hal::timer::CountDown for CountDown { type Time = Milliseconds; fn start>(&mut self, count: T) { - self.timeout = count.into(); + self.timeout = self.timer.get_time() + count.into(); } fn wait(&mut self) -> nb::Result<(), Void> {