diff options
Diffstat (limited to 'embassy-mcxa/src')
| -rw-r--r-- | embassy-mcxa/src/rtc.rs | 78 |
1 files changed, 34 insertions, 44 deletions
diff --git a/embassy-mcxa/src/rtc.rs b/embassy-mcxa/src/rtc.rs index f975d9c9f..c5474d34a 100644 --- a/embassy-mcxa/src/rtc.rs +++ b/embassy-mcxa/src/rtc.rs | |||
| @@ -9,8 +9,6 @@ use crate::interrupt::typelevel::{Handler, Interrupt}; | |||
| 9 | use crate::pac; | 9 | use crate::pac; |
| 10 | use crate::pac::rtc0::cr::Um; | 10 | use crate::pac::rtc0::cr::Um; |
| 11 | 11 | ||
| 12 | type Regs = pac::rtc0::RegisterBlock; | ||
| 13 | |||
| 14 | /// Global wait cell for alarm notifications | 12 | /// Global wait cell for alarm notifications |
| 15 | static WAKER: WaitCell = WaitCell::new(); | 13 | static WAKER: WaitCell = WaitCell::new(); |
| 16 | 14 | ||
| @@ -22,7 +20,7 @@ pub struct InterruptHandler<I: Instance> { | |||
| 22 | /// Trait for RTC peripheral instances | 20 | /// Trait for RTC peripheral instances |
| 23 | pub trait Instance: PeripheralType { | 21 | pub trait Instance: PeripheralType { |
| 24 | type Interrupt: Interrupt; | 22 | type Interrupt: Interrupt; |
| 25 | fn ptr() -> *const Regs; | 23 | fn ptr() -> &'static pac::rtc0::RegisterBlock; |
| 26 | } | 24 | } |
| 27 | 25 | ||
| 28 | /// Token for RTC0 | 26 | /// Token for RTC0 |
| @@ -30,8 +28,8 @@ pub type Rtc0 = crate::peripherals::RTC0; | |||
| 30 | impl Instance for crate::peripherals::RTC0 { | 28 | impl Instance for crate::peripherals::RTC0 { |
| 31 | type Interrupt = crate::interrupt::typelevel::RTC; | 29 | type Interrupt = crate::interrupt::typelevel::RTC; |
| 32 | #[inline(always)] | 30 | #[inline(always)] |
| 33 | fn ptr() -> *const Regs { | 31 | fn ptr() -> &'static pac::rtc0::RegisterBlock { |
| 34 | pac::Rtc0::ptr() | 32 | unsafe { &*pac::Rtc0::ptr() } |
| 35 | } | 33 | } |
| 36 | } | 34 | } |
| 37 | 35 | ||
| @@ -204,18 +202,19 @@ pub fn get_default_config() -> RtcConfig { | |||
| 204 | } | 202 | } |
| 205 | } | 203 | } |
| 206 | /// Minimal RTC handle for a specific instance I (store the zero-sized token like embassy) | 204 | /// Minimal RTC handle for a specific instance I (store the zero-sized token like embassy) |
| 207 | pub struct Rtc<'a, I: Instance> { | 205 | pub struct Rtc<'a> { |
| 208 | _inst: core::marker::PhantomData<&'a mut I>, | 206 | _inst: core::marker::PhantomData<&'a mut ()>, |
| 207 | info: &'static pac::rtc0::RegisterBlock, | ||
| 209 | } | 208 | } |
| 210 | 209 | ||
| 211 | impl<'a, I: Instance> Rtc<'a, I> { | 210 | impl<'a> Rtc<'a> { |
| 212 | /// Create a new instance of the real time clock. | 211 | /// Create a new instance of the real time clock. |
| 213 | pub fn new( | 212 | pub fn new<I: Instance>( |
| 214 | _inst: Peri<'a, I>, | 213 | _inst: Peri<'a, I>, |
| 215 | _irq: impl crate::interrupt::typelevel::Binding<I::Interrupt, InterruptHandler<I>> + 'a, | 214 | _irq: impl crate::interrupt::typelevel::Binding<I::Interrupt, InterruptHandler<I>> + 'a, |
| 216 | config: RtcConfig, | 215 | config: RtcConfig, |
| 217 | ) -> Self { | 216 | ) -> Self { |
| 218 | let rtc = unsafe { &*I::ptr() }; | 217 | let info = I::ptr(); |
| 219 | 218 | ||
| 220 | // The RTC is NOT gated by the MRCC, but we DO need to make sure the 16k clock | 219 | // The RTC is NOT gated by the MRCC, but we DO need to make sure the 16k clock |
| 221 | // on the vsys domain is active | 220 | // on the vsys domain is active |
| @@ -227,13 +226,13 @@ impl<'a, I: Instance> Rtc<'a, I> { | |||
| 227 | } | 226 | } |
| 228 | 227 | ||
| 229 | // RTC reset | 228 | // RTC reset |
| 230 | rtc.cr().modify(|_, w| w.swr().set_bit()); | 229 | info.cr().modify(|_, w| w.swr().set_bit()); |
| 231 | rtc.cr().modify(|_, w| w.swr().clear_bit()); | 230 | info.cr().modify(|_, w| w.swr().clear_bit()); |
| 232 | rtc.tsr().write(|w| unsafe { w.bits(1) }); | 231 | info.tsr().write(|w| unsafe { w.bits(1) }); |
| 233 | 232 | ||
| 234 | rtc.cr().modify(|_, w| w.um().variant(config.update_mode)); | 233 | info.cr().modify(|_, w| w.um().variant(config.update_mode)); |
| 235 | 234 | ||
| 236 | rtc.tcr().modify(|_, w| unsafe { | 235 | info.tcr().modify(|_, w| unsafe { |
| 237 | w.cir() | 236 | w.cir() |
| 238 | .bits(config.compensation_interval) | 237 | .bits(config.compensation_interval) |
| 239 | .tcr() | 238 | .tcr() |
| @@ -246,6 +245,7 @@ impl<'a, I: Instance> Rtc<'a, I> { | |||
| 246 | 245 | ||
| 247 | Self { | 246 | Self { |
| 248 | _inst: core::marker::PhantomData, | 247 | _inst: core::marker::PhantomData, |
| 248 | info, | ||
| 249 | } | 249 | } |
| 250 | } | 250 | } |
| 251 | 251 | ||
| @@ -259,9 +259,8 @@ impl<'a, I: Instance> Rtc<'a, I> { | |||
| 259 | /// | 259 | /// |
| 260 | /// The datetime is converted to Unix timestamp and written to the time seconds register. | 260 | /// The datetime is converted to Unix timestamp and written to the time seconds register. |
| 261 | pub fn set_datetime(&self, datetime: RtcDateTime) { | 261 | pub fn set_datetime(&self, datetime: RtcDateTime) { |
| 262 | let rtc = unsafe { &*I::ptr() }; | ||
| 263 | let seconds = convert_datetime_to_seconds(&datetime); | 262 | let seconds = convert_datetime_to_seconds(&datetime); |
| 264 | rtc.tsr().write(|w| unsafe { w.bits(seconds) }); | 263 | self.info.tsr().write(|w| unsafe { w.bits(seconds) }); |
| 265 | } | 264 | } |
| 266 | 265 | ||
| 267 | /// Get the current date and time | 266 | /// Get the current date and time |
| @@ -274,8 +273,7 @@ impl<'a, I: Instance> Rtc<'a, I> { | |||
| 274 | /// | 273 | /// |
| 275 | /// Reads the current Unix timestamp from the time seconds register and converts it. | 274 | /// Reads the current Unix timestamp from the time seconds register and converts it. |
| 276 | pub fn get_datetime(&self) -> RtcDateTime { | 275 | pub fn get_datetime(&self) -> RtcDateTime { |
| 277 | let rtc = unsafe { &*I::ptr() }; | 276 | let seconds = self.info.tsr().read().bits(); |
| 278 | let seconds = rtc.tsr().read().bits(); | ||
| 279 | convert_seconds_to_datetime(seconds) | 277 | convert_seconds_to_datetime(seconds) |
| 280 | } | 278 | } |
| 281 | 279 | ||
| @@ -295,19 +293,18 @@ impl<'a, I: Instance> Rtc<'a, I> { | |||
| 295 | /// - Uses timeouts to prevent infinite loops | 293 | /// - Uses timeouts to prevent infinite loops |
| 296 | /// - Enables the alarm interrupt after setting | 294 | /// - Enables the alarm interrupt after setting |
| 297 | pub fn set_alarm(&self, alarm: RtcDateTime) { | 295 | pub fn set_alarm(&self, alarm: RtcDateTime) { |
| 298 | let rtc = unsafe { &*I::ptr() }; | ||
| 299 | let seconds = convert_datetime_to_seconds(&alarm); | 296 | let seconds = convert_datetime_to_seconds(&alarm); |
| 300 | 297 | ||
| 301 | rtc.tar().write(|w| unsafe { w.bits(0) }); | 298 | self.info.tar().write(|w| unsafe { w.bits(0) }); |
| 302 | let mut timeout = 10000; | 299 | let mut timeout = 10000; |
| 303 | while rtc.tar().read().bits() != 0 && timeout > 0 { | 300 | while self.info.tar().read().bits() != 0 && timeout > 0 { |
| 304 | timeout -= 1; | 301 | timeout -= 1; |
| 305 | } | 302 | } |
| 306 | 303 | ||
| 307 | rtc.tar().write(|w| unsafe { w.bits(seconds) }); | 304 | self.info.tar().write(|w| unsafe { w.bits(seconds) }); |
| 308 | 305 | ||
| 309 | let mut timeout = 10000; | 306 | let mut timeout = 10000; |
| 310 | while rtc.tar().read().bits() != seconds && timeout > 0 { | 307 | while self.info.tar().read().bits() != seconds && timeout > 0 { |
| 311 | timeout -= 1; | 308 | timeout -= 1; |
| 312 | } | 309 | } |
| 313 | 310 | ||
| @@ -324,8 +321,7 @@ impl<'a, I: Instance> Rtc<'a, I> { | |||
| 324 | /// | 321 | /// |
| 325 | /// Reads the alarm timestamp from the time alarm register and converts it. | 322 | /// Reads the alarm timestamp from the time alarm register and converts it. |
| 326 | pub fn get_alarm(&self) -> RtcDateTime { | 323 | pub fn get_alarm(&self) -> RtcDateTime { |
| 327 | let rtc = unsafe { &*I::ptr() }; | 324 | let alarm_seconds = self.info.tar().read().bits(); |
| 328 | let alarm_seconds = rtc.tar().read().bits(); | ||
| 329 | convert_seconds_to_datetime(alarm_seconds) | 325 | convert_seconds_to_datetime(alarm_seconds) |
| 330 | } | 326 | } |
| 331 | 327 | ||
| @@ -335,8 +331,7 @@ impl<'a, I: Instance> Rtc<'a, I> { | |||
| 335 | /// | 331 | /// |
| 336 | /// Sets the Time Counter Enable (TCE) bit in the status register. | 332 | /// Sets the Time Counter Enable (TCE) bit in the status register. |
| 337 | pub fn start(&self) { | 333 | pub fn start(&self) { |
| 338 | let rtc = unsafe { &*I::ptr() }; | 334 | self.info.sr().modify(|_, w| w.tce().set_bit()); |
| 339 | rtc.sr().modify(|_, w| w.tce().set_bit()); | ||
| 340 | } | 335 | } |
| 341 | 336 | ||
| 342 | /// Stop the RTC time counter | 337 | /// Stop the RTC time counter |
| @@ -345,8 +340,7 @@ impl<'a, I: Instance> Rtc<'a, I> { | |||
| 345 | /// | 340 | /// |
| 346 | /// Clears the Time Counter Enable (TCE) bit in the status register. | 341 | /// Clears the Time Counter Enable (TCE) bit in the status register. |
| 347 | pub fn stop(&self) { | 342 | pub fn stop(&self) { |
| 348 | let rtc = unsafe { &*I::ptr() }; | 343 | self.info.sr().modify(|_, w| w.tce().clear_bit()); |
| 349 | rtc.sr().modify(|_, w| w.tce().clear_bit()); | ||
| 350 | } | 344 | } |
| 351 | 345 | ||
| 352 | /// Enable specific RTC interrupts | 346 | /// Enable specific RTC interrupts |
| @@ -364,19 +358,17 @@ impl<'a, I: Instance> Rtc<'a, I> { | |||
| 364 | /// - Alarm Interrupt | 358 | /// - Alarm Interrupt |
| 365 | /// - Seconds Interrupt | 359 | /// - Seconds Interrupt |
| 366 | pub fn set_interrupt(&self, mask: u32) { | 360 | pub fn set_interrupt(&self, mask: u32) { |
| 367 | let rtc = unsafe { &*I::ptr() }; | ||
| 368 | |||
| 369 | if (RtcInterruptEnable::RTC_TIME_INVALID_INTERRUPT_ENABLE & mask) != 0 { | 361 | if (RtcInterruptEnable::RTC_TIME_INVALID_INTERRUPT_ENABLE & mask) != 0 { |
| 370 | rtc.ier().modify(|_, w| w.tiie().tiie_1()); | 362 | self.info.ier().modify(|_, w| w.tiie().tiie_1()); |
| 371 | } | 363 | } |
| 372 | if (RtcInterruptEnable::RTC_TIME_OVERFLOW_INTERRUPT_ENABLE & mask) != 0 { | 364 | if (RtcInterruptEnable::RTC_TIME_OVERFLOW_INTERRUPT_ENABLE & mask) != 0 { |
| 373 | rtc.ier().modify(|_, w| w.toie().toie_1()); | 365 | self.info.ier().modify(|_, w| w.toie().toie_1()); |
| 374 | } | 366 | } |
| 375 | if (RtcInterruptEnable::RTC_ALARM_INTERRUPT_ENABLE & mask) != 0 { | 367 | if (RtcInterruptEnable::RTC_ALARM_INTERRUPT_ENABLE & mask) != 0 { |
| 376 | rtc.ier().modify(|_, w| w.taie().taie_1()); | 368 | self.info.ier().modify(|_, w| w.taie().taie_1()); |
| 377 | } | 369 | } |
| 378 | if (RtcInterruptEnable::RTC_SECONDS_INTERRUPT_ENABLE & mask) != 0 { | 370 | if (RtcInterruptEnable::RTC_SECONDS_INTERRUPT_ENABLE & mask) != 0 { |
| 379 | rtc.ier().modify(|_, w| w.tsie().tsie_1()); | 371 | self.info.ier().modify(|_, w| w.tsie().tsie_1()); |
| 380 | } | 372 | } |
| 381 | } | 373 | } |
| 382 | 374 | ||
| @@ -390,19 +382,17 @@ impl<'a, I: Instance> Rtc<'a, I> { | |||
| 390 | /// | 382 | /// |
| 391 | /// This function disables the specified interrupt types. | 383 | /// This function disables the specified interrupt types. |
| 392 | pub fn disable_interrupt(&self, mask: u32) { | 384 | pub fn disable_interrupt(&self, mask: u32) { |
| 393 | let rtc = unsafe { &*I::ptr() }; | ||
| 394 | |||
| 395 | if (RtcInterruptEnable::RTC_TIME_INVALID_INTERRUPT_ENABLE & mask) != 0 { | 385 | if (RtcInterruptEnable::RTC_TIME_INVALID_INTERRUPT_ENABLE & mask) != 0 { |
| 396 | rtc.ier().modify(|_, w| w.tiie().tiie_0()); | 386 | self.info.ier().modify(|_, w| w.tiie().tiie_0()); |
| 397 | } | 387 | } |
| 398 | if (RtcInterruptEnable::RTC_TIME_OVERFLOW_INTERRUPT_ENABLE & mask) != 0 { | 388 | if (RtcInterruptEnable::RTC_TIME_OVERFLOW_INTERRUPT_ENABLE & mask) != 0 { |
| 399 | rtc.ier().modify(|_, w| w.toie().toie_0()); | 389 | self.info.ier().modify(|_, w| w.toie().toie_0()); |
| 400 | } | 390 | } |
| 401 | if (RtcInterruptEnable::RTC_ALARM_INTERRUPT_ENABLE & mask) != 0 { | 391 | if (RtcInterruptEnable::RTC_ALARM_INTERRUPT_ENABLE & mask) != 0 { |
| 402 | rtc.ier().modify(|_, w| w.taie().taie_0()); | 392 | self.info.ier().modify(|_, w| w.taie().taie_0()); |
| 403 | } | 393 | } |
| 404 | if (RtcInterruptEnable::RTC_SECONDS_INTERRUPT_ENABLE & mask) != 0 { | 394 | if (RtcInterruptEnable::RTC_SECONDS_INTERRUPT_ENABLE & mask) != 0 { |
| 405 | rtc.ier().modify(|_, w| w.tsie().tsie_0()); | 395 | self.info.ier().modify(|_, w| w.tsie().tsie_0()); |
| 406 | } | 396 | } |
| 407 | } | 397 | } |
| 408 | 398 | ||
| @@ -412,8 +402,7 @@ impl<'a, I: Instance> Rtc<'a, I> { | |||
| 412 | /// | 402 | /// |
| 413 | /// This function clears the Time Alarm Interrupt Enable bit. | 403 | /// This function clears the Time Alarm Interrupt Enable bit. |
| 414 | pub fn clear_alarm_flag(&self) { | 404 | pub fn clear_alarm_flag(&self) { |
| 415 | let rtc = unsafe { &*I::ptr() }; | 405 | self.info.ier().modify(|_, w| w.taie().clear_bit()); |
| 416 | rtc.ier().modify(|_, w| w.taie().clear_bit()); | ||
| 417 | } | 406 | } |
| 418 | 407 | ||
| 419 | /// Wait for an RTC alarm to trigger. | 408 | /// Wait for an RTC alarm to trigger. |
| @@ -421,6 +410,7 @@ impl<'a, I: Instance> Rtc<'a, I> { | |||
| 421 | /// # Arguments | 410 | /// # Arguments |
| 422 | /// | 411 | /// |
| 423 | /// * `alarm` - The date and time when the alarm should trigger | 412 | /// * `alarm` - The date and time when the alarm should trigger |
| 413 | /// | ||
| 424 | /// This function will wait until the RTC alarm is triggered. | 414 | /// This function will wait until the RTC alarm is triggered. |
| 425 | /// If no alarm is scheduled, it will wait indefinitely until one is scheduled and triggered. | 415 | /// If no alarm is scheduled, it will wait indefinitely until one is scheduled and triggered. |
| 426 | pub async fn wait_for_alarm(&mut self, alarm: RtcDateTime) { | 416 | pub async fn wait_for_alarm(&mut self, alarm: RtcDateTime) { |
