Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements to the time and watchdog interface #174

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Changed

- Updated the `cast` dependency from 0.2 to 0.3
- The IwdgTimeout can now be any type that implements Into<MicroSeconds>

### Added

Expand All @@ -18,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- PWM complementary output capability for TIM1 with new example to demonstrate
- Implement interface for reading and writing to the internal flash memory and an example for demonstration.
- PWM output on complementary channels only for single channel timers (TIM16 + TIM17)
- Types for Microseconds, Milliseconds and Seconds in time.rs

### Fixed

Expand Down
82 changes: 78 additions & 4 deletions src/time.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
/// Bits per second
#[derive(PartialEq, PartialOrd, Clone, Copy)]
#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]
pub struct Bps(pub u32);

#[derive(PartialEq, PartialOrd, Clone, Copy)]
#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]
pub struct Hertz(pub u32);

#[derive(PartialEq, PartialOrd, Clone, Copy)]
#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]
pub struct KiloHertz(pub u32);

#[derive(PartialEq, PartialOrd, Clone, Copy)]
#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]
pub struct MegaHertz(pub u32);

#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]
pub struct MicroSecond(pub u32);

#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]
pub struct MilliSecond(pub u32);

#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]
pub struct Second(pub u32);

/// Extension trait that adds convenience methods to the `u32` type
pub trait U32Ext {
/// Wrap in `Bps`
Expand All @@ -24,6 +33,15 @@ pub trait U32Ext {

/// Wrap in `MegaHertz`
fn mhz(self) -> MegaHertz;

/// Wrap in `MicroSecond`
fn us(self) -> MicroSecond;

/// Wrap in `MilliSecond`
fn ms(self) -> MilliSecond;

/// Wrap in `Second`
fn seconds(self) -> Second;
}

impl U32Ext for u32 {
Expand All @@ -42,6 +60,18 @@ impl U32Ext for u32 {
fn mhz(self) -> MegaHertz {
MegaHertz(self)
}

fn us(self) -> MicroSecond {
MicroSecond(self)
}

fn ms(self) -> MilliSecond {
MilliSecond(self)
}

fn seconds(self) -> Second {
Second(self)
}
}

impl From<KiloHertz> for Hertz {
Expand All @@ -61,3 +91,47 @@ impl From<MegaHertz> for KiloHertz {
KiloHertz(mhz.0 * 1_000)
}
}

impl Hertz {
pub fn duration(self, cycles: u32) -> MicroSecond {
let cycles = cycles as u64;
let clk = self.0 as u64;
let us = cycles.saturating_mul(1_000_000_u64) / clk;
MicroSecond(us as u32)
}
}

impl MicroSecond {
pub fn cycles(self, clk: Hertz) -> u32 {
assert!(self.0 > 0);
let clk = clk.0 as u64;
let period = self.0 as u64;
let cycles = clk.saturating_mul(period) / 1_000_000_u64;
cycles as u32
}
}

impl From<Second> for MicroSecond {
fn from(period: Second) -> MicroSecond {
MicroSecond(period.0 * 1_000_000)
}
}

impl From<MilliSecond> for MicroSecond {
fn from(period: MilliSecond) -> MicroSecond {
MicroSecond(period.0 * 1_000)
}
}

impl From<Second> for MilliSecond {
fn from(period: Second) -> MilliSecond {
MilliSecond(period.0 * 1_000)
}
}

impl From<Hertz> for MicroSecond {
fn from(freq: Hertz) -> MicroSecond {
assert!(freq.0 <= 1_000_000);
MicroSecond(1_000_000 / freq.0)
}
}
18 changes: 10 additions & 8 deletions src/watchdog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
//!
//! use crate::hal::pac;
//! use crate::hal::prelude::*;
//! use crate::hal:watchdog::Watchdog;
//! use crate::hal:time::Hertz;
//! use crate::hal::watchdog::Watchdog;
//! use crate::hal::time::Hertz;
//!
//! let mut p = pac::Peripherals::take().unwrap();
//!
Expand All @@ -44,7 +44,7 @@
use embedded_hal::watchdog;

use crate::pac::IWDG;
use crate::time::Hertz;
use crate::time::{MicroSecond, U32Ext};

/// Watchdog instance
pub struct Watchdog {
Expand All @@ -66,13 +66,16 @@ pub struct IwdgTimeout {
reload: u16,
}

impl From<Hertz> for IwdgTimeout {
impl<T> From<T> for IwdgTimeout
where
T: Into<MicroSecond>,
{
/// This converts the value so it's usable by the IWDG
/// Due to conversion losses, the specified frequency is a maximum
///
/// It can also only represent values < 10000 Hertz
fn from(hz: Hertz) -> Self {
let mut time = 40_000 / 4 / hz.0;
fn from(period: T) -> Self {
let mut time = period.into().cycles((40_000 / 4).hz());
let mut psc = 0;
let mut reload = 0;
while psc < 7 {
Expand All @@ -83,9 +86,8 @@ impl From<Hertz> for IwdgTimeout {
psc += 1;
time /= 2;
}
// As we get an integer value, reload is always below 0xFFF
let reload = reload as u16;
IwdgTimeout { psc, reload }
Self { psc, reload }
}
}

Expand Down