From e0278814b6841b393d705644868aa02354fb3691 Mon Sep 17 00:00:00 2001 From: Nathan Samson Date: Fri, 14 Jan 2022 21:40:55 +0100 Subject: [PATCH] Add a non busy sleep --- Cargo.lock | 54 +++++++++++++++++++++++++++++++++++++++---- Cargo.toml | 5 ++++ examples/timer.rs | 59 +++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 ++ src/timer.rs | 37 +++++++++++++++++++++++++++++ 5 files changed, 152 insertions(+), 5 deletions(-) create mode 100644 examples/timer.rs create mode 100644 src/timer.rs diff --git a/Cargo.lock b/Cargo.lock index f08de6b..b50b1da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,35 +1,59 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "arduino-hal" +version = "0.1.0" +source = "git+https://github.com/rahix/avr-hal?rev=f84c0dff774c2292bc932b670955165161ecc7d1#f84c0dff774c2292bc932b670955165161ecc7d1" +dependencies = [ + "atmega-hal", + "avr-device", + "avr-hal-generic 0.1.0 (git+https://github.com/rahix/avr-hal?rev=f84c0dff774c2292bc932b670955165161ecc7d1)", + "cfg-if 1.0.0", + "embedded-hal", + "ufmt", + "void", +] + [[package]] name = "arduino-uno" version = "0.1.0" source = "git+https://github.com/Rahix/avr-hal?rev=a20277873a8102998d5fd69743771bd8c0aa9423#a20277873a8102998d5fd69743771bd8c0aa9423" dependencies = [ "atmega328p-hal", - "avr-hal-generic", + "avr-hal-generic 0.1.0 (git+https://github.com/Rahix/avr-hal?rev=a20277873a8102998d5fd69743771bd8c0aa9423)", ] [[package]] name = "async-avr" version = "0.1.0" dependencies = [ + "arduino-hal", "arduino-uno", "atmega328p-hal", "avr-device", - "avr-hal-generic", + "avr-hal-generic 0.1.0 (git+https://github.com/Rahix/avr-hal?rev=a20277873a8102998d5fd69743771bd8c0aa9423)", "futures-util", "panic-halt", "pin-utils", "ufmt", ] +[[package]] +name = "atmega-hal" +version = "0.1.0" +source = "git+https://github.com/rahix/avr-hal?rev=f84c0dff774c2292bc932b670955165161ecc7d1#f84c0dff774c2292bc932b670955165161ecc7d1" +dependencies = [ + "avr-device", + "avr-hal-generic 0.1.0 (git+https://github.com/rahix/avr-hal?rev=f84c0dff774c2292bc932b670955165161ecc7d1)", +] + [[package]] name = "atmega328p-hal" version = "0.1.0" source = "git+https://github.com/Rahix/avr-hal?rev=a20277873a8102998d5fd69743771bd8c0aa9423#a20277873a8102998d5fd69743771bd8c0aa9423" dependencies = [ "avr-device", - "avr-hal-generic", + "avr-hal-generic 0.1.0 (git+https://github.com/Rahix/avr-hal?rev=a20277873a8102998d5fd69743771bd8c0aa9423)", ] [[package]] @@ -40,7 +64,7 @@ checksum = "63801a7acebed9c5ad3d89a9d3baa394fdd4de5e3a9a2384f9659fa1dc7fa823" dependencies = [ "avr-device-macros", "bare-metal", - "cfg-if", + "cfg-if 0.1.10", "vcell", ] @@ -61,7 +85,21 @@ version = "0.1.0" source = "git+https://github.com/Rahix/avr-hal?rev=a20277873a8102998d5fd69743771bd8c0aa9423#a20277873a8102998d5fd69743771bd8c0aa9423" dependencies = [ "avr-device", - "cfg-if", + "cfg-if 0.1.10", + "embedded-hal", + "nb 0.1.3", + "paste", + "ufmt", + "void", +] + +[[package]] +name = "avr-hal-generic" +version = "0.1.0" +source = "git+https://github.com/rahix/avr-hal?rev=f84c0dff774c2292bc932b670955165161ecc7d1#f84c0dff774c2292bc932b670955165161ecc7d1" +dependencies = [ + "avr-device", + "cfg-if 0.1.10", "embedded-hal", "nb 0.1.3", "paste", @@ -84,6 +122,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "embedded-hal" version = "0.2.4" diff --git a/Cargo.toml b/Cargo.toml index f7c658e..9021236 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,11 @@ pin-utils = "0.1.0" futures-util = { version = "0.3.5", default-features = false, features = ["async-await-macro"] } ufmt = "0.1.0" +[dependencies.arduino-hal] +git = "https://github.com/rahix/avr-hal" +rev = "f84c0dff774c2292bc932b670955165161ecc7d1" +features = ["arduino-uno"] + [profile.dev] panic = "abort" lto = true diff --git a/examples/timer.rs b/examples/timer.rs new file mode 100644 index 0000000..719f812 --- /dev/null +++ b/examples/timer.rs @@ -0,0 +1,59 @@ +//! This example demonstrates how to set up a SPI interface and communicate +//! over it. The physical hardware configuation consists of connecting a +//! jumper directly from pin `~11` to pin `~12`. +//! +//! This example opens a serial connection to the host computer. On most POSIX operating systems (like GNU/Linux or +//! OSX), you can interface with the program by running (assuming the device appears as ttyACM0) +//! +//! $ sudo screen /dev/ttyACM0 57600# + +#![no_std] +#![no_main] +#![feature(abi_avr_interrupt)] + +use panic_halt as _; +use core::cell::RefCell; +use avr_hal_generic::void::ResultVoidExt; + +use async_avr::timer::TimeReader; + +use async_avr::{block_on, timer}; + +struct ArduinoOneHwTimer { + timer: arduino_hal::pac::TC1, +} + +impl timer::TimeReader for ArduinoOneHwTimer { + fn ticks(&self) -> u16 { + return self.timer.tcnt1.read().bits(); + } +} + +#[arduino_hal::entry] +fn main() -> ! { + let dp = arduino_hal::Peripherals::take().unwrap(); + let pins = arduino_hal::pins!(dp); + let mut serial = arduino_hal::default_serial!(dp, pins, 9600); + + let mut led = pins.d13.into_output(); + + dp.TC1.tccr1b.write(|w| w.cs1().prescale_1024()); + let hw_timer = RefCell::new(ArduinoOneHwTimer { timer: dp.TC1 }); + + let led_blink_1s = async { + loop { + led.toggle(); + timer::Timer::sleep_in_millis(1000u16, hw_timer.borrow()).await; + } + }; + + let serial_write_3_5s = async { + loop { + ufmt::uwriteln!(&mut serial, "Another 3.5s have passed! {}\r", hw_timer.borrow().ticks()).void_unwrap(); + timer::Timer::sleep_in_millis(3500u16, hw_timer.borrow()).await; + } + }; + + block_on(async { futures_util::join!(led_blink_1s, serial_write_3_5s) }); + loop {} +} diff --git a/src/lib.rs b/src/lib.rs index 33451ce..cfff98c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,8 @@ pub use executor::block_on; use futures_util::future::Future; pub use spi::AsyncSpi; +pub mod timer; + pub struct AsyncSerial(T); impl AsyncSerial { diff --git a/src/timer.rs b/src/timer.rs new file mode 100644 index 0000000..74774c6 --- /dev/null +++ b/src/timer.rs @@ -0,0 +1,37 @@ +use core::cell::Ref; +use core::task::{Context, Poll}; + +pub trait TimeReader { + fn ticks(&self) -> u16; +} + +pub struct Timer<'a, T> where T: TimeReader { + delay_in_ticks: u16, + start_tick: u16, + hw_timer: Ref<'a, T>, +} + +impl<'a, T: TimeReader> Timer<'a, T> { + pub fn sleep_in_millis(delay_in_millis: u16, hw_timer: Ref<'a, T>) -> Timer<'a, T> { + Timer { + // this assumes a 16MHz timer with a 1024 prescalar + delay_in_ticks: delay_in_millis * 10 / 64u16 * 100, + start_tick: hw_timer.ticks(), + hw_timer: hw_timer + } + } +} + +impl<'a, T: TimeReader> crate::Future for Timer<'a, T> { + type Output = bool; + + fn poll(self: crate::Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { + let tick = self.hw_timer.ticks(); + + if tick - self.start_tick >= self.delay_in_ticks { + return Poll::Ready(true); + } else { + return Poll::Pending; + } + } +}