From 77f4308a7cc7b3c5e7a236c306b0c82f4f3d0fe0 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sun, 19 Jul 2020 21:21:00 +0100 Subject: [PATCH] Add support for RTC from the HIB peripheral --- tm4c123x-hal/src/hib.rs | 72 ++++++++++++++++++++++++++++++++++++++ tm4c123x-hal/src/lib.rs | 1 + tm4c129x-hal/src/hib.rs | 76 +++++++++++++++++++++++++++++++++++++++++ tm4c129x-hal/src/lib.rs | 1 + 4 files changed, 150 insertions(+) create mode 100644 tm4c123x-hal/src/hib.rs create mode 100644 tm4c129x-hal/src/hib.rs diff --git a/tm4c123x-hal/src/hib.rs b/tm4c123x-hal/src/hib.rs new file mode 100644 index 0000000..3cf7f25 --- /dev/null +++ b/tm4c123x-hal/src/hib.rs @@ -0,0 +1,72 @@ +//! A wrapper for the HIB (Hibernation) peripheral + +use crate::sysctl; + +/// Which source to use for the HIB clock +pub enum Source { + /// HIB clock is from an external oscillator + ExternalOscillator, + /// HIB clock is from the internal low-frequency oscillator + LowFrequencyInternalOscillator, +} + +/// A wrapper around the HIB (Hibernation) peripheral +pub struct Hib { + hib: tm4c123x::HIB, +} + +impl Hib { + /// Initialize the HIB peripheral, using a clock from `source` + pub fn hib(hib: tm4c123x::HIB, source: Source, _pc: &sysctl::PowerControl) -> Self { + hib.ctl.write(|w| { + match source { + Source::ExternalOscillator => w.oscbyp().set_bit(), + Source::LowFrequencyInternalOscillator => w.oscbyp().clear_bit(), + }; + + w.clk32en().set_bit(); + + w + }); + + while hib.ctl.read().wrc().bit_is_clear() {} + hib.ctl.write(|w| { + match source { + Source::ExternalOscillator => w.oscbyp().set_bit(), + Source::LowFrequencyInternalOscillator => w.oscbyp().clear_bit(), + }; + + w.oscdrv().set_bit(); + w.clk32en().set_bit(); + w.rtcen().set_bit(); + + w + }); + while hib.ctl.read().wrc().bit_is_clear() {} + + Hib { hib } + } + + /// Get the current time, in units of (seconds, subseconds), where a + /// subsecond is 1/32768 seconds + pub fn get_time(&self) -> (u32, u16) { + loop { + let seconds = self.hib.rtcc.read().bits(); + let subsec = self.hib.rtcss.read().rtcssc().bits(); + + if seconds == self.hib.rtcc.read().bits() { + return (seconds, subsec); + } + } + } + + /// Get the current time in milliseconds + pub fn get_millis(&self) -> u64 { + let (seconds, subsec) = self.get_time(); + let seconds: u64 = seconds.into(); + let subsec: u64 = subsec.into(); + + let millis: u64 = subsec * 1000 / 32_768; + return seconds * 1000 + millis; + } +} diff --git a/tm4c123x-hal/src/lib.rs b/tm4c123x-hal/src/lib.rs index 3772060..12137ba 100644 --- a/tm4c123x-hal/src/lib.rs +++ b/tm4c123x-hal/src/lib.rs @@ -33,6 +33,7 @@ pub use crate::tm4c123x::interrupt; use embedded_hal as hal; pub mod gpio; +pub mod hib; pub mod i2c; pub mod prelude; pub mod pwm; diff --git a/tm4c129x-hal/src/hib.rs b/tm4c129x-hal/src/hib.rs new file mode 100644 index 0000000..2516d4d --- /dev/null +++ b/tm4c129x-hal/src/hib.rs @@ -0,0 +1,76 @@ +//! A wrapper for the HIB (Hibernation) peripheral + +use crate::sysctl; + +/// Which source to use for the HIB clock +pub enum Source { + /// HIB clock is from an external crystal + ExternalCrystal, + /// HIB clock is from an external oscillator + ExternalOscillator, + /// HIB clock is from the internal low-frequency oscillator + LowFrequencyInternalOscillator, +} + +/// A wrapper around the HIB (Hibernation) peripheral +pub struct Hib { + hib: tm4c129x::HIB, +} + +impl Hib { + /// Initialize the HIB peripheral, using a clock from `source` + pub fn hib(hib: tm4c129x::HIB, source: Source, _pc: &sysctl::PowerControl) -> Self { + hib.ctl.write(|w| { + match source { + Source::ExternalCrystal => w.oscsel().clear_bit().oscbyp().clear_bit(), + Source::ExternalOscillator => w.oscsel().clear_bit().oscbyp().set_bit(), + Source::LowFrequencyInternalOscillator => w.oscsel().set_bit().oscbyp().clear_bit(), + }; + + w.clk32en().set_bit(); + + w + }); + + while hib.ctl.read().wrc().bit_is_clear() {} + hib.ctl.write(|w| { + match source { + Source::ExternalCrystal => w.oscsel().clear_bit().oscbyp().clear_bit(), + Source::ExternalOscillator => w.oscsel().clear_bit().oscbyp().set_bit(), + Source::LowFrequencyInternalOscillator => w.oscsel().set_bit().oscbyp().clear_bit(), + }; + + w.oscdrv().set_bit(); + w.clk32en().set_bit(); + w.rtcen().set_bit(); + + w + }); + while hib.ctl.read().wrc().bit_is_clear() {} + + Hib { hib } + } + + /// Get the current time, in units of (seconds, subseconds), where a + /// subsecond is 1/32768 seconds + pub fn get_time(&self) -> (u32, u16) { + loop { + let seconds = self.hib.rtcc.read().bits(); + let subsec = self.hib.rtcss.read().rtcssc().bits(); + + if seconds == self.hib.rtcc.read().bits() { + return (seconds, subsec); + } + } + } + + /// Get the current time in milliseconds + pub fn get_millis(&self) -> u64 { + let (seconds, subsec) = self.get_time(); + let seconds: u64 = seconds.into(); + let subsec: u64 = subsec.into(); + + let millis: u64 = subsec * 1000 / 32_768; + return seconds * 1000 + millis; + } +} diff --git a/tm4c129x-hal/src/lib.rs b/tm4c129x-hal/src/lib.rs index 618752c..73a6de0 100644 --- a/tm4c129x-hal/src/lib.rs +++ b/tm4c129x-hal/src/lib.rs @@ -33,6 +33,7 @@ pub use tm4c_hal::{bb, delay, time}; pub use crate::tm4c129x::interrupt; pub mod gpio; +pub mod hib; pub mod i2c; pub mod prelude; pub mod serial;