diff options
| author | Felipe Balbi <[email protected]> | 2025-11-19 09:11:54 -0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-11-19 09:11:54 -0800 |
| commit | a8eb124e47e633cd81e0863253d5f6bdd7545260 (patch) | |
| tree | 526374336411093886915121fea7245efa067c93 /src | |
| parent | ffe3e5acae6c0038db4176dc7d031b57f865e07f (diff) | |
OSTimer updates (#24)
* Initialize OSTIMER0 during HAL initialization
Provide the user with a working time driver.
Signed-off-by: Felipe Balbi <[email protected]>
* Handle time_driver interrupt internally
Signed-off-by: Felipe Balbi <[email protected]>
* Gate `time-driver` impl behind a `time` flag
Also prevents creation of an `Ostimer` instance if the `time`
feature is active.
* Remove some dead code
---------
Signed-off-by: Felipe Balbi <[email protected]>
Co-authored-by: James Munns <[email protected]>
Diffstat (limited to 'src')
| -rw-r--r-- | src/clocks/mod.rs | 6 | ||||
| -rw-r--r-- | src/config.rs | 2 | ||||
| -rw-r--r-- | src/lib.rs | 11 | ||||
| -rw-r--r-- | src/ostimer.rs | 88 |
4 files changed, 81 insertions, 26 deletions
diff --git a/src/clocks/mod.rs b/src/clocks/mod.rs index 558fb0278..a12e125c6 100644 --- a/src/clocks/mod.rs +++ b/src/clocks/mod.rs | |||
| @@ -867,7 +867,9 @@ macro_rules! impl_cc_gate { | |||
| 867 | /// This module contains implementations of MRCC APIs, specifically of the [`Gate`] trait, | 867 | /// This module contains implementations of MRCC APIs, specifically of the [`Gate`] trait, |
| 868 | /// for various low level peripherals. | 868 | /// for various low level peripherals. |
| 869 | pub(crate) mod gate { | 869 | pub(crate) mod gate { |
| 870 | use super::periph_helpers::{AdcConfig, LpuartConfig, NoConfig, OsTimerConfig}; | 870 | #[cfg(not(feature = "time"))] |
| 871 | use super::periph_helpers::OsTimerConfig; | ||
| 872 | use super::periph_helpers::{AdcConfig, LpuartConfig, NoConfig}; | ||
| 871 | use super::*; | 873 | use super::*; |
| 872 | 874 | ||
| 873 | // These peripherals have no additional upstream clocks or configuration required | 875 | // These peripherals have no additional upstream clocks or configuration required |
| @@ -888,7 +890,9 @@ pub(crate) mod gate { | |||
| 888 | 890 | ||
| 889 | // These peripherals DO have meaningful configuration, and could fail if the system | 891 | // These peripherals DO have meaningful configuration, and could fail if the system |
| 890 | // clocks do not match their needs. | 892 | // clocks do not match their needs. |
| 893 | #[cfg(not(feature = "time"))] | ||
| 891 | impl_cc_gate!(OSTIMER0, mrcc_glb_cc1, mrcc_glb_rst1, ostimer0, OsTimerConfig); | 894 | impl_cc_gate!(OSTIMER0, mrcc_glb_cc1, mrcc_glb_rst1, ostimer0, OsTimerConfig); |
| 895 | |||
| 892 | impl_cc_gate!(LPUART2, mrcc_glb_cc0, mrcc_glb_rst0, lpuart2, LpuartConfig); | 896 | impl_cc_gate!(LPUART2, mrcc_glb_cc0, mrcc_glb_rst0, lpuart2, LpuartConfig); |
| 893 | impl_cc_gate!(ADC1, mrcc_glb_cc1, mrcc_glb_rst1, adc1, AdcConfig); | 897 | impl_cc_gate!(ADC1, mrcc_glb_cc1, mrcc_glb_rst1, adc1, AdcConfig); |
| 894 | } | 898 | } |
diff --git a/src/config.rs b/src/config.rs index 0939c11f1..9c0d47ecb 100644 --- a/src/config.rs +++ b/src/config.rs | |||
| @@ -5,6 +5,7 @@ use crate::interrupt::Priority; | |||
| 5 | 5 | ||
| 6 | #[non_exhaustive] | 6 | #[non_exhaustive] |
| 7 | pub struct Config { | 7 | pub struct Config { |
| 8 | #[cfg(feature = "time")] | ||
| 8 | pub time_interrupt_priority: Priority, | 9 | pub time_interrupt_priority: Priority, |
| 9 | pub rtc_interrupt_priority: Priority, | 10 | pub rtc_interrupt_priority: Priority, |
| 10 | pub adc_interrupt_priority: Priority, | 11 | pub adc_interrupt_priority: Priority, |
| @@ -14,6 +15,7 @@ pub struct Config { | |||
| 14 | impl Default for Config { | 15 | impl Default for Config { |
| 15 | fn default() -> Self { | 16 | fn default() -> Self { |
| 16 | Self { | 17 | Self { |
| 18 | #[cfg(feature = "time")] | ||
| 17 | time_interrupt_priority: Priority::from(0), | 19 | time_interrupt_priority: Priority::from(0), |
| 18 | rtc_interrupt_priority: Priority::from(0), | 20 | rtc_interrupt_priority: Priority::from(0), |
| 19 | adc_interrupt_priority: Priority::from(0), | 21 | adc_interrupt_priority: Priority::from(0), |
diff --git a/src/lib.rs b/src/lib.rs index c885ecc50..e93ff61a6 100644 --- a/src/lib.rs +++ b/src/lib.rs | |||
| @@ -14,6 +14,9 @@ pub mod lpuart; | |||
| 14 | pub mod ostimer; | 14 | pub mod ostimer; |
| 15 | pub mod rtc; | 15 | pub mod rtc; |
| 16 | 16 | ||
| 17 | #[cfg(feature = "rt")] | ||
| 18 | pub use crate::pac::NVIC_PRIO_BITS; | ||
| 19 | |||
| 17 | #[rustfmt::skip] | 20 | #[rustfmt::skip] |
| 18 | embassy_hal_internal::peripherals!( | 21 | embassy_hal_internal::peripherals!( |
| 19 | ADC0, | 22 | ADC0, |
| @@ -83,6 +86,8 @@ embassy_hal_internal::peripherals!( | |||
| 83 | MBC0, | 86 | MBC0, |
| 84 | MRCC0, | 87 | MRCC0, |
| 85 | OPAMP0, | 88 | OPAMP0, |
| 89 | |||
| 90 | #[cfg(not(feature = "time"))] | ||
| 86 | OSTIMER0, | 91 | OSTIMER0, |
| 87 | 92 | ||
| 88 | P0_0, | 93 | P0_0, |
| @@ -335,7 +340,6 @@ pub use interrupt::InterruptExt; | |||
| 335 | pub use mcxa_pac as pac; | 340 | pub use mcxa_pac as pac; |
| 336 | #[cfg(not(feature = "unstable-pac"))] | 341 | #[cfg(not(feature = "unstable-pac"))] |
| 337 | pub(crate) use mcxa_pac as pac; | 342 | pub(crate) use mcxa_pac as pac; |
| 338 | pub use ostimer::Ostimer0 as Ostimer0Token; | ||
| 339 | pub use rtc::Rtc0 as Rtc0Token; | 343 | pub use rtc::Rtc0 as Rtc0Token; |
| 340 | 344 | ||
| 341 | /// Initialize HAL with configuration (mirrors embassy-imxrt style). Minimal: just take peripherals. | 345 | /// Initialize HAL with configuration (mirrors embassy-imxrt style). Minimal: just take peripherals. |
| @@ -343,6 +347,7 @@ pub use rtc::Rtc0 as Rtc0Token; | |||
| 343 | pub fn init(cfg: crate::config::Config) -> Peripherals { | 347 | pub fn init(cfg: crate::config::Config) -> Peripherals { |
| 344 | let peripherals = Peripherals::take(); | 348 | let peripherals = Peripherals::take(); |
| 345 | // Apply user-configured priority early; enabling is left to examples/apps | 349 | // Apply user-configured priority early; enabling is left to examples/apps |
| 350 | #[cfg(feature = "time")] | ||
| 346 | crate::interrupt::OS_EVENT.set_priority(cfg.time_interrupt_priority); | 351 | crate::interrupt::OS_EVENT.set_priority(cfg.time_interrupt_priority); |
| 347 | // Apply user-configured priority early; enabling is left to examples/apps | 352 | // Apply user-configured priority early; enabling is left to examples/apps |
| 348 | crate::interrupt::RTC.set_priority(cfg.rtc_interrupt_priority); | 353 | crate::interrupt::RTC.set_priority(cfg.rtc_interrupt_priority); |
| @@ -352,6 +357,10 @@ pub fn init(cfg: crate::config::Config) -> Peripherals { | |||
| 352 | // Configure clocks | 357 | // Configure clocks |
| 353 | crate::clocks::init(cfg.clock_cfg).unwrap(); | 358 | crate::clocks::init(cfg.clock_cfg).unwrap(); |
| 354 | 359 | ||
| 360 | // Initialize embassy-time global driver backed by OSTIMER0 | ||
| 361 | #[cfg(feature = "time")] | ||
| 362 | crate::ostimer::time_driver::init(crate::config::Config::default().time_interrupt_priority, 1_000_000); | ||
| 363 | |||
| 355 | // Enable GPIO clocks | 364 | // Enable GPIO clocks |
| 356 | unsafe { | 365 | unsafe { |
| 357 | _ = crate::clocks::enable_and_reset::<crate::peripherals::PORT0>(&crate::clocks::periph_helpers::NoConfig); | 366 | _ = crate::clocks::enable_and_reset::<crate::peripherals::PORT0>(&crate::clocks::periph_helpers::NoConfig); |
diff --git a/src/ostimer.rs b/src/ostimer.rs index cd5451b53..c51812e3d 100644 --- a/src/ostimer.rs +++ b/src/ostimer.rs | |||
| @@ -35,7 +35,6 @@ use crate::clocks::periph_helpers::{OsTimerConfig, OstimerClockSel}; | |||
| 35 | use crate::clocks::{assert_reset, enable_and_reset, is_reset_released, release_reset, Gate, PoweredClock}; | 35 | use crate::clocks::{assert_reset, enable_and_reset, is_reset_released, release_reset, Gate, PoweredClock}; |
| 36 | use crate::interrupt::InterruptExt; | 36 | use crate::interrupt::InterruptExt; |
| 37 | use crate::pac; | 37 | use crate::pac; |
| 38 | use crate::peripherals::OSTIMER0; | ||
| 39 | 38 | ||
| 40 | // PAC defines the shared RegisterBlock under `ostimer0`. | 39 | // PAC defines the shared RegisterBlock under `ostimer0`. |
| 41 | type Regs = pac::ostimer0::RegisterBlock; | 40 | type Regs = pac::ostimer0::RegisterBlock; |
| @@ -283,15 +282,15 @@ impl<'d, I: Instance> Ostimer<'d, I> { | |||
| 283 | .write(|w| w.ostimer_intrflag().clear_bit_by_one().ostimer_intena().clear_bit()); | 282 | .write(|w| w.ostimer_intrflag().clear_bit_by_one().ostimer_intena().clear_bit()); |
| 284 | 283 | ||
| 285 | unsafe { | 284 | unsafe { |
| 286 | assert_reset::<OSTIMER0>(); | 285 | assert_reset::<I>(); |
| 287 | 286 | ||
| 288 | for _ in 0..RESET_STABILIZE_SPINS { | 287 | for _ in 0..RESET_STABILIZE_SPINS { |
| 289 | cortex_m::asm::nop(); | 288 | cortex_m::asm::nop(); |
| 290 | } | 289 | } |
| 291 | 290 | ||
| 292 | release_reset::<OSTIMER0>(); | 291 | release_reset::<I>(); |
| 293 | 292 | ||
| 294 | while !is_reset_released::<OSTIMER0>() { | 293 | while !is_reset_released::<I>() { |
| 295 | cortex_m::asm::nop(); | 294 | cortex_m::asm::nop(); |
| 296 | } | 295 | } |
| 297 | } | 296 | } |
| @@ -490,9 +489,7 @@ pub trait Instance: Gate<MrccPeriphConfig = OsTimerConfig> + PeripheralType { | |||
| 490 | fn ptr() -> *const Regs; | 489 | fn ptr() -> *const Regs; |
| 491 | } | 490 | } |
| 492 | 491 | ||
| 493 | // Token for OSTIMER0 provided by embassy-hal-internal peripherals macro. | 492 | #[cfg(not(feature = "time"))] |
| 494 | pub type Ostimer0 = crate::peripherals::OSTIMER0; | ||
| 495 | |||
| 496 | impl Instance for crate::peripherals::OSTIMER0 { | 493 | impl Instance for crate::peripherals::OSTIMER0 { |
| 497 | #[inline(always)] | 494 | #[inline(always)] |
| 498 | fn ptr() -> *const Regs { | 495 | fn ptr() -> *const Regs { |
| @@ -500,14 +497,6 @@ impl Instance for crate::peripherals::OSTIMER0 { | |||
| 500 | } | 497 | } |
| 501 | } | 498 | } |
| 502 | 499 | ||
| 503 | // Also implement Instance for the Peri wrapper type | ||
| 504 | // impl Instance for embassy_hal_internal::Peri<'_, crate::peripherals::OSTIMER0> { | ||
| 505 | // #[inline(always)] | ||
| 506 | // fn ptr() -> *const Regs { | ||
| 507 | // pac::Ostimer0::ptr() | ||
| 508 | // } | ||
| 509 | // } | ||
| 510 | |||
| 511 | #[inline(always)] | 500 | #[inline(always)] |
| 512 | fn bin_to_gray(x: u64) -> u64 { | 501 | fn bin_to_gray(x: u64) -> u64 { |
| 513 | x ^ (x >> 1) | 502 | x ^ (x >> 1) |
| @@ -523,6 +512,7 @@ fn gray_to_bin(gray: u64) -> u64 { | |||
| 523 | bin | 512 | bin |
| 524 | } | 513 | } |
| 525 | 514 | ||
| 515 | #[cfg(feature = "time")] | ||
| 526 | pub mod time_driver { | 516 | pub mod time_driver { |
| 527 | use core::sync::atomic::Ordering; | 517 | use core::sync::atomic::Ordering; |
| 528 | use core::task::Waker; | 518 | use core::task::Waker; |
| @@ -537,7 +527,55 @@ pub mod time_driver { | |||
| 537 | use crate::clocks::periph_helpers::{OsTimerConfig, OstimerClockSel}; | 527 | use crate::clocks::periph_helpers::{OsTimerConfig, OstimerClockSel}; |
| 538 | use crate::clocks::{enable_and_reset, PoweredClock}; | 528 | use crate::clocks::{enable_and_reset, PoweredClock}; |
| 539 | use crate::pac; | 529 | use crate::pac; |
| 540 | use crate::peripherals::OSTIMER0; | 530 | |
| 531 | #[allow(non_camel_case_types)] | ||
| 532 | pub(crate) struct _OSTIMER0_TIME_DRIVER { | ||
| 533 | _x: (), | ||
| 534 | } | ||
| 535 | |||
| 536 | // #[cfg(feature = "time")] | ||
| 537 | // impl_cc_gate!(_OSTIMER0_TIME_DRIVER, mrcc_glb_cc1, mrcc_glb_rst1, ostimer0, OsTimerConfig); | ||
| 538 | |||
| 539 | impl crate::clocks::Gate for _OSTIMER0_TIME_DRIVER { | ||
| 540 | type MrccPeriphConfig = crate::clocks::periph_helpers::OsTimerConfig; | ||
| 541 | |||
| 542 | #[inline] | ||
| 543 | unsafe fn enable_clock() { | ||
| 544 | let mrcc = unsafe { pac::Mrcc0::steal() }; | ||
| 545 | mrcc.mrcc_glb_cc1().modify(|_, w| w.ostimer0().enabled()); | ||
| 546 | } | ||
| 547 | |||
| 548 | #[inline] | ||
| 549 | unsafe fn disable_clock() { | ||
| 550 | let mrcc = unsafe { pac::Mrcc0::steal() }; | ||
| 551 | mrcc.mrcc_glb_cc1().modify(|_r, w| w.ostimer0().disabled()); | ||
| 552 | } | ||
| 553 | |||
| 554 | #[inline] | ||
| 555 | fn is_clock_enabled() -> bool { | ||
| 556 | let mrcc = unsafe { pac::Mrcc0::steal() }; | ||
| 557 | mrcc.mrcc_glb_cc1().read().ostimer0().is_enabled() | ||
| 558 | } | ||
| 559 | |||
| 560 | #[inline] | ||
| 561 | unsafe fn release_reset() { | ||
| 562 | let mrcc = unsafe { pac::Mrcc0::steal() }; | ||
| 563 | mrcc.mrcc_glb_rst1().modify(|_, w| w.ostimer0().enabled()); | ||
| 564 | } | ||
| 565 | |||
| 566 | #[inline] | ||
| 567 | unsafe fn assert_reset() { | ||
| 568 | let mrcc = unsafe { pac::Mrcc0::steal() }; | ||
| 569 | mrcc.mrcc_glb_rst1().modify(|_, w| w.ostimer0().disabled()); | ||
| 570 | } | ||
| 571 | |||
| 572 | #[inline] | ||
| 573 | fn is_reset_released() -> bool { | ||
| 574 | let mrcc = unsafe { pac::Mrcc0::steal() }; | ||
| 575 | mrcc.mrcc_glb_rst1().read().ostimer0().is_enabled() | ||
| 576 | } | ||
| 577 | } | ||
| 578 | |||
| 541 | pub struct Driver; | 579 | pub struct Driver; |
| 542 | static TIMER_WAKER: AtomicWaker = AtomicWaker::new(); | 580 | static TIMER_WAKER: AtomicWaker = AtomicWaker::new(); |
| 543 | 581 | ||
| @@ -625,7 +663,7 @@ pub mod time_driver { | |||
| 625 | /// The embassy_time_driver macro handles driver registration automatically. | 663 | /// The embassy_time_driver macro handles driver registration automatically. |
| 626 | pub fn init(priority: crate::interrupt::Priority, frequency_hz: u64) { | 664 | pub fn init(priority: crate::interrupt::Priority, frequency_hz: u64) { |
| 627 | let _clock_freq = unsafe { | 665 | let _clock_freq = unsafe { |
| 628 | enable_and_reset::<OSTIMER0>(&OsTimerConfig { | 666 | enable_and_reset::<_OSTIMER0_TIME_DRIVER>(&OsTimerConfig { |
| 629 | power: PoweredClock::AlwaysEnabled, | 667 | power: PoweredClock::AlwaysEnabled, |
| 630 | source: OstimerClockSel::Clk1M, | 668 | source: OstimerClockSel::Clk1M, |
| 631 | }) | 669 | }) |
| @@ -694,12 +732,14 @@ pub mod time_driver { | |||
| 694 | } | 732 | } |
| 695 | }); | 733 | }); |
| 696 | } | 734 | } |
| 735 | } | ||
| 697 | 736 | ||
| 698 | /// Type-level handler to be used with bind_interrupts! for OS_EVENT. | 737 | #[cfg(feature = "time")] |
| 699 | pub struct OsEventHandler; | 738 | use crate::pac::interrupt; |
| 700 | impl crate::interrupt::typelevel::Handler<crate::interrupt::typelevel::OS_EVENT> for OsEventHandler { | 739 | |
| 701 | unsafe fn on_interrupt() { | 740 | #[cfg(feature = "time")] |
| 702 | on_interrupt(); | 741 | #[allow(non_snake_case)] |
| 703 | } | 742 | #[interrupt] |
| 704 | } | 743 | fn OS_EVENT() { |
| 744 | time_driver::on_interrupt() | ||
| 705 | } | 745 | } |
