Skip to content
This repository has been archived by the owner on May 15, 2021. It is now read-only.

Timers #12

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 49 additions & 76 deletions src/delay.rs
Original file line number Diff line number Diff line change
@@ -1,82 +1,55 @@
//! Delays

use cast::u32;
use nrf51::TIMER0;
use nrf51::{TIMER0, TIMER1, TIMER2};

use hal::blocking::delay::{DelayMs, DelayUs};

/// System timer `TIMER0` as a delay provider
pub struct Delay {
timer: TIMER0,
}

impl Delay {
/// Configures the TIMER0 as a delay provider
pub fn new(timer: TIMER0) -> Self {
timer.tasks_stop.write(|w| unsafe { w.bits(1) });

// Set counter to 24bit mode
timer.bitmode.write(|w| unsafe { w.bits(2) });

// Set prescaler to 4 == 1MHz timer
timer.prescaler.write(|w| unsafe { w.bits(4) });

Delay { timer }
}

pub fn free(self) -> TIMER0 {
self.timer
}
}

impl DelayMs<u32> for Delay {
fn delay_ms(&mut self, ms: u32) {
self.delay_us(ms * 1_000);
}
}

impl DelayMs<u16> for Delay {
fn delay_ms(&mut self, ms: u16) {
self.delay_ms(u32(ms));
}
}

impl DelayMs<u8> for Delay {
fn delay_ms(&mut self, ms: u8) {
self.delay_ms(u32(ms));
}
}

impl DelayUs<u32> for Delay {
fn delay_us(&mut self, us: u32) {
/* Clear event in case it was used before */
self.timer.events_compare[0].write(|w| unsafe { w.bits(0) });

/* Program counter compare register with value */
self.timer.cc[0].write(|w| unsafe { w.bits(us) });

/* Clear current counter value */
self.timer.tasks_clear.write(|w| unsafe { w.bits(1) });

/* Start counting */
self.timer.tasks_start.write(|w| unsafe { w.bits(1) });

/* Busy wait for event to happen */
while self.timer.events_compare[0].read().bits() == 0 {}

/* Stop counting */
self.timer.tasks_stop.write(|w| unsafe { w.bits(1) });
}
}

impl DelayUs<u16> for Delay {
fn delay_us(&mut self, us: u16) {
self.delay_us(u32(us))
}
}

impl DelayUs<u8> for Delay {
fn delay_us(&mut self, us: u8) {
self.delay_us(u32(us))
}
}
pub use timer::{Timer, BitMode};
pub use timer::{micros, hertz};

macro_rules! delay {
( $($TIM:ty),+ ) => {
$(
impl DelayMs<u32> for Timer<$TIM> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you've renamed Delay to Timer? That'll break all some stuff, including your own examples in microbit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll create an alias to Delay as a structural fix, as that what clients will expect. Behind the scenes though it makes no sense to have a distinction.

fn delay_ms(&mut self, ms: u32) {
self.delay_us(ms * 1_000);
}
}

impl DelayMs<u16> for Timer<$TIM> {
fn delay_ms(&mut self, ms: u16) {
self.delay_ms(u32(ms));
}
}

impl DelayMs<u8> for Timer<$TIM> {
fn delay_ms(&mut self, ms: u8) {
self.delay_ms(u32(ms));
}
}

impl DelayUs<u32> for Timer<$TIM> {
fn delay_us(&mut self, us: u32) {

self.delay(micros(us));
}
}

impl DelayUs<u16> for Timer<$TIM> {
fn delay_us(&mut self, us: u16) {
self.delay_us(u32(us))
}
}

impl DelayUs<u8> for Timer<$TIM> {
fn delay_us(&mut self, us: u8) {
self.delay_us(u32(us))
}
}

)+
};
}

delay!(TIMER0, TIMER1, TIMER2);
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#![no_std]
#![cfg_attr(feature = "rt", feature(global_asm))]
#![cfg_attr(feature = "rt", feature(used))]
#![feature(const_fn)]
#![feature(try_from)]
#![feature(duration_as_u128)]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should try to get rid of all those features. This should eventually be Rust 2018 stable-able.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I had forgotten about that:

  • Remove all 3 2018-incompatible features

I used core::time::Duration to get it working, but it is expensive in an MCU to use u128s to manipulate time. It seems there are many ongoing discussions about how to handle real unite both in rust and rust-embedded, none nearing conclusion. So for now I will just make 3 types: tick (An nrf51 specific tick, 1/16th of a μs, a μs and a ms.

#![allow(non_camel_case_types)]

extern crate cast;
Expand Down
Loading