diff options
Diffstat (limited to 'drivers/pit/src')
| -rw-r--r-- | drivers/pit/src/lib.rs | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/drivers/pit/src/lib.rs b/drivers/pit/src/lib.rs new file mode 100644 index 0000000..a99d8a2 --- /dev/null +++ b/drivers/pit/src/lib.rs @@ -0,0 +1,113 @@ +#![no_std] + +use ral_registers as ral; +pub type PIT = ral_registers::Instance<RegisterBlock>; + +#[repr(C)] +#[allow(non_snake_case)] +pub struct RegisterBlock { + pub MCR: u32, + reserved_0: [u8; 220], + pub LTMR64H: u32, + pub LTMR64L: u32, + reserved_1: [u8; 24], + pub TIMER: [TIMER::RegisterBlock; 4], +} + +ral_registers::register! { + #[doc = "PIT Module Control Register"] + pub MCR<u32> RW [ + #[doc = "Freeze"] + FRZ start(0) width(1) RW { + #[doc = "Timers continue to run in Debug mode."] + RUN = 0, + #[doc = "Timers are stopped in Debug mode."] + STOP = 0x1, + } + #[doc = "Module Disable for PIT"] + MDIS start(1) width(1) RW { + #[doc = "Clock for standard PIT timers is enabled."] + ENABLE = 0, + #[doc = "Clock for standard PIT timers is disabled."] + DISABLE = 0x1, + } + ] +} + +ral_registers::register! { + #[doc = "PIT Upper Lifetime Timer Register"] + pub LTMR64H<u32> RO [] +} + +ral_registers::register! { + #[doc = "PIT Lower Lifetime Timer Register"] + pub LTMR64L<u32> RO [] +} + +#[allow(non_snake_case)] +pub mod TIMER { + + #[allow(non_snake_case)] + #[repr(C)] + pub struct RegisterBlock { + pub LDVAL: u32, + pub CVAL: u32, + pub TCTRL: u32, + pub TFLG: u32, + } + + ral_registers::register! { + #[doc = "Timer Load Value Register"] + pub LDVAL<u32> RW [] + } + ral_registers::register! { + #[doc = "Timer Current Value Register"] + pub CVAL<u32> RO [] + } + + ral_registers::register! { + #[doc = "Timer Control Register"] + pub TCTRL<u32> RW [ + #[doc = "Timer Enable"] + TEN start(0) width(1) RW {} + #[doc = "Timer Interrupt Enable"] + TIE start(1) width(1) RW {} + #[doc = "Chain Mode"] + CHN start(2) width(1) RW {} + ] + } + + ral_registers::register! { + #[doc = "Timer Flag Register"] + pub TFLG<u32> RW [ + #[doc = "Timer Interrupt Flag"] + TIF start(0) width(1) RW { + } + ] + } +} + +/// Read the lifetime counter value as a `u64`. +/// +/// This routine assumes that you've chained timers 0 and +/// timers 1 together, forming the lifetime timer. It also +/// assumes that the timers are enabled. +/// +/// The implementation includes the recommendation in errata +/// ERR050130. +pub fn read_lifetime_value(pit: PIT) -> u64 { + let mut h = ral::read_reg!(self, pit, LTMR64H); + let mut l = ral::read_reg!(self, pit, LTMR64L); + + // ERR050130 says + // + // "[...] if the read value of LTMR64L is equal to LDVAL0 [...]" + if ral::read_reg!(self, pit, TIMER[0].LDVAL) == l { + // "[...] then read both LTMR64H and LTMR64L registers for + // one additional time to obtain the correct lifetime value." + h = ral::read_reg!(self, pit, LTMR64H); + l = ral::read_reg!(self, pit, LTMR64L); + } + + (u64::from(h) << 32) | u64::from(l) +} |
