diff options
| author | Irina Chiorean <[email protected]> | 2025-09-01 12:12:39 +0300 |
|---|---|---|
| committer | Roi Bachynskyi <[email protected]> | 2025-09-12 11:07:02 +0300 |
| commit | d1dc7a3a88fbcc8a47fc8031a0338858c08090e9 (patch) | |
| tree | 9ce4d2d2ab386a8c1fa66e2f53cdec5df679fd38 /embassy-nxp | |
| parent | e74dbe8c5d625f17c0bcee82aa8a2d45deb33a18 (diff) | |
lpc55: rtc driver rewritten
Diffstat (limited to 'embassy-nxp')
| -rw-r--r-- | embassy-nxp/src/time_driver/rtc.rs | 76 |
1 files changed, 41 insertions, 35 deletions
diff --git a/embassy-nxp/src/time_driver/rtc.rs b/embassy-nxp/src/time_driver/rtc.rs index 94272e9c2..fb6de6a5e 100644 --- a/embassy-nxp/src/time_driver/rtc.rs +++ b/embassy-nxp/src/time_driver/rtc.rs | |||
| @@ -6,7 +6,9 @@ use embassy_hal_internal::interrupt::{InterruptExt, Priority}; | |||
| 6 | use embassy_sync::blocking_mutex::CriticalSectionMutex as Mutex; | 6 | use embassy_sync::blocking_mutex::CriticalSectionMutex as Mutex; |
| 7 | use embassy_time_driver::{time_driver_impl, Driver}; | 7 | use embassy_time_driver::{time_driver_impl, Driver}; |
| 8 | use embassy_time_queue_utils::Queue; | 8 | use embassy_time_queue_utils::Queue; |
| 9 | use lpc55_pac::{interrupt, PMC, RTC, SYSCON}; | 9 | |
| 10 | use crate::pac::{interrupt, pmc, rtc, PMC, RTC, SYSCON}; | ||
| 11 | |||
| 10 | struct AlarmState { | 12 | struct AlarmState { |
| 11 | timestamp: Cell<u64>, | 13 | timestamp: Cell<u64>, |
| 12 | } | 14 | } |
| @@ -32,33 +34,32 @@ time_driver_impl!(static DRIVER: RtcDriver = RtcDriver { | |||
| 32 | }); | 34 | }); |
| 33 | impl RtcDriver { | 35 | impl RtcDriver { |
| 34 | fn init(&'static self) { | 36 | fn init(&'static self) { |
| 35 | let syscon = unsafe { &*SYSCON::ptr() }; | 37 | let syscon = SYSCON; |
| 36 | let pmc = unsafe { &*PMC::ptr() }; | 38 | let pmc = PMC; |
| 37 | let rtc = unsafe { &*RTC::ptr() }; | 39 | let rtc = RTC; |
| 38 | 40 | ||
| 39 | syscon.ahbclkctrl0.modify(|_, w| w.rtc().enable()); | 41 | syscon.ahbclkctrl0().modify(|w| w.set_rtc(true)); |
| 40 | 42 | ||
| 41 | // By default the RTC enters software reset. If for some reason it is | 43 | // By default the RTC enters software reset. If for some reason it is |
| 42 | // not in reset, we enter and them promptly leave.q | 44 | // not in reset, we enter and them promptly leave.q |
| 43 | rtc.ctrl.modify(|_, w| w.swreset().set_bit()); | 45 | rtc.ctrl().modify(|w| w.set_swreset(true)); |
| 44 | rtc.ctrl.modify(|_, w| w.swreset().clear_bit()); | 46 | rtc.ctrl().modify(|w| w.set_swreset(false)); |
| 45 | 47 | ||
| 46 | // Select clock source - either XTAL or FRO | 48 | // Select clock source - either XTAL or FRO |
| 47 | // pmc.rtcosc32k.write(|w| w.sel().xtal32k()); | 49 | // pmc.rtcosc32k().write(|w| w.set_sel(pmc::vals::Sel::XTAL32K)); |
| 48 | pmc.rtcosc32k.write(|w| w.sel().fro32k()); | 50 | pmc.rtcosc32k().write(|w| w.set_sel(pmc::vals::Sel::FRO32K)); |
| 49 | 51 | ||
| 50 | // Start the RTC peripheral | 52 | // Start the RTC peripheral |
| 51 | rtc.ctrl.modify(|_, w| w.rtc_osc_pd().power_up()); | 53 | rtc.ctrl().modify(|w| w.set_rtc_osc_pd(rtc::vals::RtcOscPd::POWER_UP)); |
| 52 | |||
| 53 | // rtc.ctrl.modify(|_, w| w.rtc_en().clear_bit()); // EXTRA | ||
| 54 | 54 | ||
| 55 | //reset/clear(?) counter | 55 | //reset/clear(?) counter |
| 56 | rtc.count.reset(); | 56 | rtc.count().modify(|w| w.set_val(0)); |
| 57 | //en rtc main counter | 57 | //en rtc main counter |
| 58 | rtc.ctrl.modify(|_, w| w.rtc_en().set_bit()); | 58 | rtc.ctrl().modify(|w| w.set_rtc_en(true)); |
| 59 | rtc.ctrl.modify(|_, w| w.rtc1khz_en().set_bit()); | 59 | rtc.ctrl().modify(|w| w.set_rtc1khz_en(true)); |
| 60 | // subsec counter enable | 60 | // subsec counter enable |
| 61 | rtc.ctrl.modify(|_, w| w.rtc_subsec_ena().set_bit()); | 61 | rtc.ctrl() |
| 62 | .modify(|w| w.set_rtc_subsec_ena(rtc::vals::RtcSubsecEna::POWER_UP)); | ||
| 62 | 63 | ||
| 63 | // enable irq | 64 | // enable irq |
| 64 | unsafe { | 65 | unsafe { |
| @@ -68,7 +69,7 @@ impl RtcDriver { | |||
| 68 | } | 69 | } |
| 69 | 70 | ||
| 70 | fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool { | 71 | fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool { |
| 71 | let rtc = unsafe { &*RTC::ptr() }; | 72 | let rtc = RTC; |
| 72 | let alarm = &self.alarms.borrow(cs); | 73 | let alarm = &self.alarms.borrow(cs); |
| 73 | alarm.timestamp.set(timestamp); | 74 | alarm.timestamp.set(timestamp); |
| 74 | let now = self.now(); | 75 | let now = self.now(); |
| @@ -83,33 +84,38 @@ impl RtcDriver { | |||
| 83 | let sec = (diff / 32768) as u32; | 84 | let sec = (diff / 32768) as u32; |
| 84 | let subsec = (diff % 32768) as u32; | 85 | let subsec = (diff % 32768) as u32; |
| 85 | 86 | ||
| 86 | let current_sec = rtc.count.read().val().bits(); | 87 | let current_sec = rtc.count().read().val(); |
| 87 | let target_sec = current_sec.wrapping_add(sec as u32); | 88 | let target_sec = current_sec.wrapping_add(sec as u32); |
| 88 | 89 | ||
| 89 | rtc.match_.write(|w| unsafe { w.matval().bits(target_sec) }); | 90 | rtc.match_().write(|w| w.set_matval(target_sec)); |
| 90 | rtc.wake.write(|w| unsafe { | 91 | rtc.wake().write(|w| { |
| 91 | let ms = (subsec * 1000) / 32768; | 92 | let ms = (subsec * 1000) / 32768; |
| 92 | w.val().bits(ms as u16) | 93 | w.set_val(ms as u16) |
| 93 | }); | 94 | }); |
| 95 | |||
| 94 | if subsec > 0 { | 96 | if subsec > 0 { |
| 95 | let ms = (subsec * 1000) / 32768; | 97 | let ms = (subsec * 1000) / 32768; |
| 96 | rtc.wake.write(|w| unsafe { w.val().bits(ms as u16) }); | 98 | rtc.wake().write(|w| w.set_val(ms as u16)); |
| 97 | } | 99 | } |
| 98 | rtc.ctrl.modify(|_, w| w.alarm1hz().clear_bit().wake1khz().clear_bit()); | 100 | |
| 101 | rtc.ctrl().modify(|w| { | ||
| 102 | w.set_alarm1hz(false); | ||
| 103 | w.set_wake1khz(rtc::vals::Wake1khz::RUN) | ||
| 104 | }); | ||
| 99 | true | 105 | true |
| 100 | } | 106 | } |
| 101 | 107 | ||
| 102 | fn on_interrupt(&self) { | 108 | fn on_interrupt(&self) { |
| 103 | critical_section::with(|cs| { | 109 | critical_section::with(|cs| { |
| 104 | let rtc = unsafe { &*RTC::ptr() }; | 110 | let rtc = RTC; |
| 105 | let flags = rtc.ctrl.read(); | 111 | let flags = rtc.ctrl().read(); |
| 106 | if flags.alarm1hz().bit_is_clear() { | 112 | if flags.alarm1hz() == false { |
| 107 | rtc.ctrl.modify(|_, w| w.alarm1hz().set_bit()); | 113 | rtc.ctrl().modify(|w| w.set_alarm1hz(true)); |
| 108 | self.trigger_alarm(cs); | 114 | self.trigger_alarm(cs); |
| 109 | } | 115 | } |
| 110 | 116 | ||
| 111 | if flags.wake1khz().bit_is_clear() { | 117 | if flags.wake1khz() == rtc::vals::Wake1khz::RUN { |
| 112 | rtc.ctrl.modify(|_, w| w.wake1khz().set_bit()); | 118 | rtc.ctrl().modify(|w| w.set_wake1khz(rtc::vals::Wake1khz::TIMEOUT)); |
| 113 | self.trigger_alarm(cs); | 119 | self.trigger_alarm(cs); |
| 114 | } | 120 | } |
| 115 | }); | 121 | }); |
| @@ -135,13 +141,13 @@ impl RtcDriver { | |||
| 135 | 141 | ||
| 136 | impl Driver for RtcDriver { | 142 | impl Driver for RtcDriver { |
| 137 | fn now(&self) -> u64 { | 143 | fn now(&self) -> u64 { |
| 138 | let rtc = unsafe { &*RTC::ptr() }; | 144 | let rtc = RTC; |
| 139 | 145 | ||
| 140 | loop { | 146 | loop { |
| 141 | let sec1 = rtc.count.read().val().bits() as u64; | 147 | let sec1 = rtc.count().read().val() as u64; |
| 142 | let sub1 = rtc.subsec.read().subsec().bits() as u64; | 148 | let sub1 = rtc.subsec().read().subsec() as u64; |
| 143 | let sec2 = rtc.count.read().val().bits() as u64; | 149 | let sec2 = rtc.count().read().val() as u64; |
| 144 | let sub2 = rtc.subsec.read().subsec().bits() as u64; | 150 | let sub2 = rtc.subsec().read().subsec() as u64; |
| 145 | 151 | ||
| 146 | if sec1 == sec2 && sub1 == sub2 { | 152 | if sec1 == sec2 && sub1 == sub2 { |
| 147 | return sec1 * 32768 + sub1; | 153 | return sec1 * 32768 + sub1; |
| @@ -162,7 +168,7 @@ impl Driver for RtcDriver { | |||
| 162 | }) | 168 | }) |
| 163 | } | 169 | } |
| 164 | } | 170 | } |
| 165 | #[cortex_m_rt::interrupt] | 171 | #[interrupt] |
| 166 | fn RTC() { | 172 | fn RTC() { |
| 167 | DRIVER.on_interrupt(); | 173 | DRIVER.on_interrupt(); |
| 168 | } | 174 | } |
