commit 72a645e8ba883abaf4b8a8e3eac3760fb496ba9a Author: Levi Pearson Date: Thu Mar 14 18:24:48 2019 -0600 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f88dba --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +**/*.rs.bk +Cargo.lock \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..e3ab850 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "msp432-hal" +version = "0.1.0" +authors = ["Levi Pearson "] +categories = ["embedded", "hardware-support", "no-std"] +description = "HAL for the TI MSP432 family of microcontrollers" +keywords = ["arm", "cortex-m", "msp432", "hal"] +edition = "2018" + +[dependencies] +cortex-m = "0.5" +embedded-hal = "0.2" +nb = "0.1" +msp432p401r = { path = "../msp432p401r" } +void = { version = "1.0", default-features = false } +cast = { version = "0.2", default-features = false } + +[features] +rt = ["msp432p401r/rt"] \ No newline at end of file diff --git a/src/cs.rs b/src/cs.rs new file mode 100644 index 0000000..3b2c2a3 --- /dev/null +++ b/src/cs.rs @@ -0,0 +1,63 @@ +//! Clock System + +use core::cmp; +use pac::{cs, CS}; + +use crate::time::Hertz; + + +/// Extension trait that constrains the `CS` peripheral +pub trait CsExt { + /// Constrains the `CS` peripheral so that it plays nicely with other abstractions + fn constrain(self) -> Cs; +} + +impl CsExt for CS { + fn constrain(self) -> Cs { + Cs { + + } + } +} + +/* ++--------+-----------------------+---------------+-------------------------------------+ +| Clock | Default Clock Source | Default Clock | Description | +| | | Frequency | | ++========+=======================+===============+=====================================+ +| MCLK | DCO | 3 MHz | Master Clock - Sources CPU and | +| | | | peripherals | ++--------+-----------------------+---------------+-------------------------------------+ +| HSMCLK | DCO | 3 MHz | Subsystem Master Clock - Sources | +| | | | peripherals | ++--------+-----------------------+---------------+-------------------------------------+ +| SMCLK | DCO | 3 MHz | Low-speed subsystem master clock - | +| | | | Sources peripherals | ++--------+-----------------------+---------------+-------------------------------------+ +| ACLK | LFXT (or REFO if no | 32.768 kHz | Auxiliary clock - Sources | +| | crystal present) | | peripherals | ++--------+-----------------------+---------------+-------------------------------------+ +| BCLK | LFXT (or REFO if no | 32.768 kHz | Low-speed backup domain clock - | +| | crystal present) | | Sources LPM peripherals | ++--------+-----------------------+---------------+-------------------------------------+ +*/ + +pub struct Cs { + +} + +/// Frozen clock frequencies +/// +/// This value holds the current clocks frequencies and indicates that they can +/// no longer be changed +#[derive(Clone, Copy)] +pub struct Clocks { + sysclk: Hertz, +} + +impl Clocks { + /// Returns the system (core) frequency + pub fn sysclk(&self) -> Hertz { + self.sysclk + } +} diff --git a/src/delay.rs b/src/delay.rs new file mode 100644 index 0000000..00d8f38 --- /dev/null +++ b/src/delay.rs @@ -0,0 +1,74 @@ +//! Delays + +use cast::u32; +use cortex_m::peripheral::syst::SystClkSource; +use cortex_m::peripheral::SYST; + +use hal::blocking::delay::{DelayMs, DelayUs}; +use crate::cs::Clocks; + +/// System timer (SysTick) as a delay provider +pub struct Delay { + clocks: Clocks, + syst: SYST, +} + +impl Delay { + /// Configure the system timer (SysTick) as a delay provider + pub fn new(mut syst: SYST, clocks: Clocks) -> Self { + syst.set_clock_source(SystClkSource::Core); + + Delay { syst, clocks } + } + + /// Release the system timer (SysTick) resource + pub fn free(self) -> SYST { + self.syst + } +} + +impl DelayMs for Delay { + fn delay_ms(&mut self, ms: u32) { + self.delay_us(ms * 1_000); + } +} + +impl DelayMs for Delay { + fn delay_ms(&mut self, ms: u16) { + self.delay_ms(u32(ms)); + } +} + +impl DelayMs for Delay { + fn delay_ms(&mut self, ms: u8) { + self.delay_ms(u32(ms)); + } +} + +impl DelayUs for Delay { + fn delay_us(&mut self, us: u32) { + let rvr = us * (self.clocks.sysclk().0 / 1_000_000); + + assert!(rvr < (1 << 24)); + + self.syst.set_reload(rvr); + self.syst.clear_current(); + self.syst.enable_counter(); + + while !self.syst.has_wrapped() {} + + self.syst.disable_counter(); + } +} + +impl DelayUs for Delay { + fn delay_us(&mut self, us: u16) { + self.delay_us(u32(us)); + } +} + +impl DelayUs for Delay { + fn delay_us(&mut self, us: u8) { + self.delay_us(u32(us)); + } +} diff --git a/src/gpio.rs b/src/gpio.rs new file mode 100644 index 0000000..c76bf3e --- /dev/null +++ b/src/gpio.rs @@ -0,0 +1,22 @@ +//! General Purpose Input / Output + +use pac::DIO; +use core::marker::PhantomData; +use hal::digital::OutputPin; + +pub trait GpioExt { + type Parts; + + /// Consume and split the device into its constituent parts + fn split(self) -> Self::Parts; +} + +/// Represents a pin configured for input. +pub struct Input { + _mode: PhantomData, +} + +/// Represents a pin configured for output. +pub struct Output { + _mode: PhantomData, +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..9cfa8f7 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,26 @@ +//! HAL for the MSP432 family of microcontrollers +//! +//! This is an implementation of the [`embedded-hal`] traits for the MSP432 family of +//! microcontrollers. +//! +//! [`embedded-hal`]: https://github.com/japaric/embedded-hal +//! +//! # Usage +//! +//! To build applications (binary crates) using this crate follow the [cortex-m-quickstart] +//! instructions and add this crate as a dependency in step number 5 and make sure you enable the +//! "rt" Cargo feature of this crate. +//! +//! [cortex-m-quickstart]: https://docs.rs/cortex-m-quickstart/~0.3 + +#![warn(missing_docs)] +#![no_std] + +extern crate embedded_hal as hal; +extern crate msp432p401r as pac; + +pub mod prelude; +pub mod gpio; +pub mod delay; +pub mod cs; +pub mod time; diff --git a/src/prelude.rs b/src/prelude.rs new file mode 100644 index 0000000..5b13046 --- /dev/null +++ b/src/prelude.rs @@ -0,0 +1,3 @@ +//! Prelude + +pub use hal::prelude::*; diff --git a/src/time.rs b/src/time.rs new file mode 100644 index 0000000..7c2ba15 --- /dev/null +++ b/src/time.rs @@ -0,0 +1,117 @@ +//! Time units + +use cortex_m::peripheral::DWT; +use crate::cs::Clocks; + +/// Bits per seconds +#[derive(Clone, Copy)] +pub struct Bps(pub u32); + +/// Hertz +#[derive(Clone, Copy)] +pub struct Hertz(pub u32); + +/// KiloHertz +#[derive(Clone, Copy)] +pub struct KiloHertz(pub u32); + +/// MegaHertz +#[derive(Clone, Copy)] +pub struct MegaHertz(pub u32); + + +/// Extension trait to add convenience methods to `u32` +pub trait U32Ext { + /// Wrap in `Bps` + fn bps(self) -> Bps; + + /// Wrap in `Hertz` + fn hz(self) -> Hertz; + + /// Wrap in `KiloHertz` + fn khz(self) -> KiloHertz; + + /// Wrap in `MegaHertz` + fn mhz(self) -> MegaHertz; +} + +impl U32Ext for u32 { + fn bps(self) -> Bps { + Bps(self) + } + + fn hz(self) -> Hertz { + Hertz(self) + } + + fn khz(self) -> KiloHertz { + KiloHertz(self) + } + + fn mhz(self) -> MegaHertz { + MegaHertz(self) + } +} + +impl Into for KiloHertz { + fn into(self) -> Hertz { + Hertz(self.0 * 1_000) + } +} + +impl Into for MegaHertz { + fn into(self) -> Hertz { + Hertz(self.0 * 1_000_000) + } +} + +impl Into for MegaHertz { + fn into(self) -> KiloHertz { + KiloHertz(self.0 * 1_000) + } +} + +/// A monotonic nondecreasing timer +#[derive(Clone, Copy)] +pub struct MonoTimer { + frequency: Hertz, +} + +impl MonoTimer { + /// Create a new monotonic timer + pub fn new(mut dwt: DWT, clocks: Clocks) -> Self { + dwt.enable_cycle_counter(); + + // can't stop or reset CYCCNT + drop(dwt); + + MonoTimer { + frequency: clocks.sysclk(), + } + } + + /// Return the frequency at which the timer is operating + pub fn frequency(&self) -> Hertz { + self.frequency + } + + /// Returns an `Instant` corresponding to "now" + pub fn now(&self) -> Instant { + Instant { + now: DWT::get_cycle_count(), + } + } +} + +/// A measurement from a monotonically nondecreasing clock +#[derive(Clone, Copy)] +pub struct Instant { + now: u32, +} + +impl Instant { + /// Ticks elapsed since the `Instant` was created + pub fn elapsed(&self) -> u32 { + DWT::get_cycle_count().wrapping_sub(self.now) + } +}