mirror of
https://github.com/italicsjenga/rp-hal-boards.git
synced 2024-12-23 20:51:31 +11:00
Add embedded_hal::timer support (#110)
* Add embedded_hal::timer support * fixup: add pico countdown based blinky example & rework get_counter(&self) -> u16
This commit is contained in:
parent
833b69819e
commit
c509b9d22f
|
@ -23,6 +23,7 @@ panic-halt= "0.2.0"
|
|||
embedded-hal ="0.2.5"
|
||||
cortex-m-rtic = "0.6.0-alpha.5"
|
||||
rp2040-boot2 = "0.1.2"
|
||||
nb = "1.0"
|
||||
|
||||
[features]
|
||||
default = ["rt"]
|
||||
|
|
61
boards/pico/examples/pico_countdown_blinky.rs
Normal file
61
boards/pico/examples/pico_countdown_blinky.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
//! Blinks the LED on a Pico board
|
||||
//!
|
||||
//! This will blink an LED attached to GP25, which is the pin the Pico uses for the on-board LED.
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use cortex_m::prelude::_embedded_hal_timer_CountDown;
|
||||
use cortex_m_rt::entry;
|
||||
use embedded_hal::digital::v2::OutputPin;
|
||||
use embedded_time::duration::Extensions;
|
||||
use panic_halt as _;
|
||||
use pico::{
|
||||
hal::{self as hal, clocks::init_clocks_and_plls, pac, sio::Sio, watchdog::Watchdog},
|
||||
XOSC_CRYSTAL_FREQ,
|
||||
};
|
||||
|
||||
#[link_section = ".boot2"]
|
||||
#[used]
|
||||
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let mut pac = pac::Peripherals::take().unwrap();
|
||||
let mut watchdog = Watchdog::new(pac.WATCHDOG);
|
||||
|
||||
let _clocks = init_clocks_and_plls(
|
||||
XOSC_CRYSTAL_FREQ,
|
||||
pac.XOSC,
|
||||
pac.CLOCKS,
|
||||
pac.PLL_SYS,
|
||||
pac.PLL_USB,
|
||||
&mut pac.RESETS,
|
||||
&mut watchdog,
|
||||
)
|
||||
.ok()
|
||||
.unwrap();
|
||||
|
||||
let timer = hal::timer::Timer::new(pac.TIMER);
|
||||
let mut count_down = timer.count_down();
|
||||
|
||||
let sio = Sio::new(pac.SIO);
|
||||
let pins = hal::gpio::Pins::new(
|
||||
pac.IO_BANK0,
|
||||
pac.PADS_BANK0,
|
||||
sio.gpio_bank0,
|
||||
&mut pac.RESETS,
|
||||
);
|
||||
let mut led_pin = pins.gpio25.into_push_pull_output();
|
||||
|
||||
loop {
|
||||
led_pin.set_high().unwrap();
|
||||
// wait for 500ms
|
||||
count_down.start(500.milliseconds());
|
||||
let _ = nb::block!(count_down.wait());
|
||||
|
||||
led_pin.set_low().unwrap();
|
||||
// wait for 500ms
|
||||
count_down.start(500.milliseconds());
|
||||
let _ = nb::block!(count_down.wait());
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
//! Timer Peripheral
|
||||
// See [Chapter 4 Section 6](https://datasheets.raspberrypi.org/rp2040/rp2040_datasheet.pdf) for more details
|
||||
|
||||
use embedded_time::duration::Microseconds;
|
||||
|
||||
use crate::pac::TIMER;
|
||||
|
||||
/// Timer peripheral
|
||||
|
@ -16,9 +18,75 @@ impl Timer {
|
|||
|
||||
/// Get the current counter value.
|
||||
pub fn get_counter(&self) -> u64 {
|
||||
// latched read, low before high
|
||||
let lo = self.timer.timelr.read().bits();
|
||||
let hi = self.timer.timehr.read().bits();
|
||||
(hi as u64) << 32 | lo as u64
|
||||
let mut hi0 = self.timer.timerawh.read().bits();
|
||||
loop {
|
||||
let low = self.timer.timerawl.read().bits();
|
||||
let hi1 = self.timer.timerawh.read().bits();
|
||||
if hi0 == hi1 {
|
||||
break (u64::from(hi0) << 32) | u64::from(low);
|
||||
}
|
||||
hi0 = hi1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the value of the least significant word of the counter.
|
||||
pub fn get_counter_low(&self) -> u32 {
|
||||
self.timer.timerawl.read().bits()
|
||||
}
|
||||
|
||||
/// Initialized a Count Down instance without starting it.
|
||||
pub fn count_down(&self) -> CountDown<'_> {
|
||||
CountDown {
|
||||
timer: self,
|
||||
period: Microseconds::new(0),
|
||||
next_end: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Delay implementation
|
||||
pub struct CountDown<'timer> {
|
||||
timer: &'timer Timer,
|
||||
period: embedded_time::duration::Microseconds<u64>,
|
||||
next_end: Option<u64>,
|
||||
}
|
||||
|
||||
impl embedded_hal::timer::CountDown for CountDown<'_> {
|
||||
type Time = embedded_time::duration::Microseconds<u64>;
|
||||
|
||||
fn start<T>(&mut self, count: T)
|
||||
where
|
||||
T: Into<Self::Time>,
|
||||
{
|
||||
self.period = count.into();
|
||||
self.next_end = Some(self.timer.get_counter().wrapping_add(self.period.0));
|
||||
}
|
||||
|
||||
fn wait(&mut self) -> nb::Result<(), void::Void> {
|
||||
if let Some(end) = self.next_end {
|
||||
let ts = self.timer.get_counter();
|
||||
if ts >= end {
|
||||
self.next_end = Some(end.wrapping_add(self.period.0));
|
||||
Ok(())
|
||||
} else {
|
||||
Err(nb::Error::WouldBlock)
|
||||
}
|
||||
} else {
|
||||
panic!("CountDown is not running!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl embedded_hal::timer::Periodic for CountDown<'_> {}
|
||||
impl embedded_hal::timer::Cancel for CountDown<'_> {
|
||||
type Error = &'static str;
|
||||
|
||||
fn cancel(&mut self) -> Result<(), Self::Error> {
|
||||
if self.next_end.is_none() {
|
||||
Err("CountDown is not running.")
|
||||
} else {
|
||||
self.next_end = None;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue