From e799d6c8956ed3ea5ced65d58c3065a22927ad10 Mon Sep 17 00:00:00 2001 From: James Munns Date: Fri, 14 Nov 2025 17:29:31 +0100 Subject: More work on examples --- examples/adc_interrupt.rs | 15 ++++-- examples/common/mod.rs | 38 +++++--------- examples/lpuart_buffered.rs | 5 +- examples/ostimer_alarm.rs | 7 +-- examples/ostimer_counter.rs | 8 ++- examples/ostimer_race_test.rs | 5 +- examples/uart_interrupt.rs | 100 ++++++++++++++++++------------------- src/adc.rs | 73 +++++++++++++++++---------- src/clocks/mod.rs | 12 ++++- src/clocks/periph_helpers.rs | 8 +++ src/lib.rs | 1 - src/lpuart/mod.rs | 2 +- src/ostimer.rs | 62 +++++++++++++---------- src/reset.rs | 112 ------------------------------------------ 14 files changed, 186 insertions(+), 262 deletions(-) delete mode 100644 src/reset.rs diff --git a/examples/adc_interrupt.rs b/examples/adc_interrupt.rs index dc82cfd30..3be85ac75 100644 --- a/examples/adc_interrupt.rs +++ b/examples/adc_interrupt.rs @@ -2,6 +2,8 @@ #![no_main] use embassy_executor::Spawner; +use embassy_mcxa276::clocks::periph_helpers::{AdcClockSel, Div4}; +use embassy_mcxa276::clocks::PoweredClock; use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; use hal::uart; use mcxa_pac::adc1::cfg::{Pwrsel, Refsel}; @@ -30,10 +32,10 @@ async fn main(_spawner: Spawner) { common::init_uart2(hal::pac()); } - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); + // let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + // let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); - uart.write_str_blocking("\r\n=== ADC interrupt Example ===\r\n"); + // uart.write_str_blocking("\r\n=== ADC interrupt Example ===\r\n"); unsafe { common::init_adc(hal::pac()); @@ -50,6 +52,9 @@ async fn main(_spawner: Spawner) { enable_conv_pause: false, conv_pause_delay: 0, fifo_watermark: 0, + power: PoweredClock::NormalEnabledDeepSleepDisabled, + source: AdcClockSel::FroLfDiv, + div: Div4::no_div(), }; let adc = hal::adc::Adc::::new(p.ADC1, adc_config); @@ -66,7 +71,7 @@ async fn main(_spawner: Spawner) { conv_trigger_config.enable_hardware_trigger = false; adc.set_conv_trigger_config(0, &conv_trigger_config); - uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); + // uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); adc.enable_interrupt(0x1); @@ -83,7 +88,7 @@ async fn main(_spawner: Spawner) { while !adc.is_interrupt_triggered() { // Wait until the interrupt is triggered } - uart.write_str_blocking("\r\n*** ADC interrupt TRIGGERED! ***\r\n"); + // uart.write_str_blocking("\r\n*** ADC interrupt TRIGGERED! ***\r\n"); //TBD need to print the value } } diff --git a/examples/common/mod.rs b/examples/common/mod.rs index 8c52c8e86..7b197a590 100644 --- a/examples/common/mod.rs +++ b/examples/common/mod.rs @@ -1,45 +1,31 @@ //! Shared board-specific helpers for the FRDM-MCXA276 examples. //! These live with the examples so the HAL stays generic. -use hal::{clocks, pins, reset}; +use hal::{clocks, pins}; use {embassy_mcxa276 as hal, panic_probe as _}; /// Initialize clocks and pin muxing for UART2 debug console. /// Safe to call multiple times; writes are idempotent for our use. #[allow(dead_code)] -pub unsafe fn init_uart2(p: &mcxa_pac::Peripherals) { - clocks::ensure_frolf_running(p); - clocks::enable_uart2_port2(p); - reset::release_reset_port2(p); - reset::release_reset_lpuart2(p); +pub unsafe fn init_uart2(_p: &mcxa_pac::Peripherals) { + // NOTE: Lpuart has been updated to properly enable + reset its own clocks. + // GPIO has not. + _ = clocks::enable_and_reset::(&clocks::NoConfig); pins::configure_uart2_pins_port2(); - clocks::select_uart2_clock(p); } /// Initialize clocks for the LED GPIO/PORT used by the blink example. #[allow(dead_code)] -pub unsafe fn init_led(p: &mcxa_pac::Peripherals) { - clocks::enable_led_port(p); - reset::release_reset_gpio3(p); - reset::release_reset_port3(p); -} - -/// Initialize clocks for OSTIMER0 (1 MHz source). -#[allow(dead_code)] -pub unsafe fn init_ostimer0(p: &mcxa_pac::Peripherals) { - clocks::ensure_frolf_running(p); - clocks::enable_ostimer0(p); - reset::release_reset_ostimer0(p); - clocks::select_ostimer0_clock_1m(p); +pub unsafe fn init_led(_p: &mcxa_pac::Peripherals) { + _ = clocks::enable_and_reset::(&clocks::NoConfig); + _ = clocks::enable_and_reset::(&clocks::NoConfig); } /// Initialize clocks and pin muxing for ADC. #[allow(dead_code)] -pub unsafe fn init_adc(p: &mcxa_pac::Peripherals) { - clocks::ensure_frolf_running(p); - clocks::enable_adc(p); - reset::release_reset_port1(p); - reset::release_reset_adc1(p); +pub unsafe fn init_adc(_p: &mcxa_pac::Peripherals) { + // NOTE: Lpuart has been updated to properly enable + reset its own clocks. + // GPIO has not. + _ = clocks::enable_and_reset::(&clocks::NoConfig); pins::configure_adc_pins(); - clocks::select_adc_clock(p); } diff --git a/examples/lpuart_buffered.rs b/examples/lpuart_buffered.rs index 35d311143..6ae690c56 100644 --- a/examples/lpuart_buffered.rs +++ b/examples/lpuart_buffered.rs @@ -12,18 +12,17 @@ mod common; // Bind OS_EVENT for timers plus LPUART2 IRQ for the buffered driver bind_interrupts!(struct Irqs { - LPUART2 => lpuart::buffered::BufferedInterruptHandler::; + LPUART2 => lpuart::buffered::BufferedInterruptHandler::; }); // Wrapper function for the interrupt handler unsafe extern "C" fn lpuart2_handler() { - lpuart::buffered::BufferedInterruptHandler::::on_interrupt(); + lpuart::buffered::BufferedInterruptHandler::::on_interrupt(); } #[embassy_executor::main] async fn main(_spawner: Spawner) { let _p = hal::init(hal::config::Config::default()); - let p2 = lpuart::lib::init(); unsafe { hal::interrupt::install_irq_handler(mcxa_pac::Interrupt::LPUART2, lpuart2_handler); diff --git a/examples/ostimer_alarm.rs b/examples/ostimer_alarm.rs index 78ca4bbc5..4f29a2c7c 100644 --- a/examples/ostimer_alarm.rs +++ b/examples/ostimer_alarm.rs @@ -9,7 +9,7 @@ use {cortex_m, embassy_mcxa276 as hal}; mod common; -use embassy_mcxa276::bind_interrupts; +use embassy_mcxa276::{bind_interrupts, clocks::{periph_helpers::OstimerClockSel, PoweredClock}}; use {defmt_rtt as _, panic_probe as _}; // Bind only OS_EVENT, and retain the symbol explicitly so it can't be GC'ed. @@ -50,9 +50,10 @@ async fn main(_spawner: Spawner) { // Create OSTIMER instance let config = hal::ostimer::Config { init_match_max: true, - clock_frequency_hz: 1_000_000, // 1MHz + power: PoweredClock::NormalEnabledDeepSleepDisabled, + source: OstimerClockSel::Clk1M, }; - let ostimer = hal::ostimer::Ostimer::::new(p.OSTIMER0, config, hal::pac()); + let ostimer = hal::ostimer::Ostimer::::new(p.OSTIMER0, config); // Create alarm with callback let alarm = hal::ostimer::Alarm::new() diff --git a/examples/ostimer_counter.rs b/examples/ostimer_counter.rs index e95140a88..069e879d8 100644 --- a/examples/ostimer_counter.rs +++ b/examples/ostimer_counter.rs @@ -7,6 +7,7 @@ #![no_main] use embassy_executor::Spawner; +use embassy_mcxa276::clocks::{periph_helpers::OstimerClockSel, PoweredClock}; use embassy_time::{Duration, Timer}; use hal::bind_interrupts; use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; @@ -22,9 +23,6 @@ async fn main(_spawner: Spawner) { let p = hal::init(Default::default()); // Enable/clock OSTIMER0 and UART2 before touching their registers - unsafe { - common::init_ostimer0(hal::pac()); - } unsafe { common::init_uart2(hal::pac()); } @@ -44,9 +42,9 @@ async fn main(_spawner: Spawner) { p.OSTIMER0, hal::ostimer::Config { init_match_max: true, - clock_frequency_hz: 1_000_000, + power: PoweredClock::NormalEnabledDeepSleepDisabled, + source: OstimerClockSel::Clk1M, }, - hal::pac(), ); // Read initial counter value diff --git a/examples/ostimer_race_test.rs b/examples/ostimer_race_test.rs index 368a3e52f..6e3d4ac21 100644 --- a/examples/ostimer_race_test.rs +++ b/examples/ostimer_race_test.rs @@ -12,6 +12,7 @@ use core::sync::atomic::{AtomicU32, Ordering}; use embassy_executor::Spawner; +use embassy_mcxa276::clocks::{periph_helpers::OstimerClockSel, PoweredClock}; use embassy_time::{Duration, Timer}; use hal::bind_interrupts; use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; @@ -98,9 +99,9 @@ async fn main(_spawner: Spawner) { p.OSTIMER0, hal::ostimer::Config { init_match_max: true, - clock_frequency_hz: 1_000_000, + power: PoweredClock::NormalEnabledDeepSleepDisabled, + source: OstimerClockSel::Clk1M, }, - hal::pac(), ); uart.write_str_blocking("OSTIMER instance created\n"); diff --git a/examples/uart_interrupt.rs b/examples/uart_interrupt.rs index bd734f859..190a4d850 100644 --- a/examples/uart_interrupt.rs +++ b/examples/uart_interrupt.rs @@ -2,68 +2,68 @@ #![no_main] use embassy_executor::Spawner; -use embassy_mcxa276 as hal; -use hal::interrupt::typelevel::Handler; -use hal::uart; +// use embassy_mcxa276 as hal; +// use hal::interrupt::typelevel::Handler; +// use hal::uart; -mod common; +// mod common; -use embassy_mcxa276::bind_interrupts; -use {defmt_rtt as _, panic_probe as _}; +// use embassy_mcxa276::bind_interrupts; +// use {defmt_rtt as _, panic_probe as _}; -// Bind LPUART2 interrupt to our handler -bind_interrupts!(struct Irqs { - LPUART2 => hal::uart::UartInterruptHandler; -}); +// // Bind LPUART2 interrupt to our handler +// bind_interrupts!(struct Irqs { +// LPUART2 => hal::uart::UartInterruptHandler; +// }); -#[used] -#[no_mangle] -static KEEP_LPUART2: unsafe extern "C" fn() = LPUART2; +// #[used] +// #[no_mangle] +// static KEEP_LPUART2: unsafe extern "C" fn() = LPUART2; -// Wrapper function for the interrupt handler -unsafe extern "C" fn lpuart2_handler() { - hal::uart::UartInterruptHandler::on_interrupt(); -} +// // Wrapper function for the interrupt handler +// unsafe extern "C" fn lpuart2_handler() { +// hal::uart::UartInterruptHandler::on_interrupt(); +// } #[embassy_executor::main] async fn main(_spawner: Spawner) { - let _p = hal::init(hal::config::Config::default()); +// let _p = hal::init(hal::config::Config::default()); - // Enable/clock UART2 before touching its registers - unsafe { - common::init_uart2(hal::pac()); - } - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let uart = uart::Uart::::new(_p.LPUART2, uart::Config::new(src)); +// // Enable/clock UART2 before touching its registers +// unsafe { +// common::init_uart2(hal::pac()); +// } +// let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; +// let uart = uart::Uart::::new(_p.LPUART2, uart::Config::new(src)); - // Configure LPUART2 interrupt for UART operation BEFORE any UART usage - hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::from(3)); +// // Configure LPUART2 interrupt for UART operation BEFORE any UART usage +// hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::from(3)); - // Manually install the interrupt handler and enable RX IRQs in the peripheral - unsafe { - hal::interrupt::LPUART2.install_handler(lpuart2_handler); - // Enable RX interrupts so the handler actually fires on incoming bytes - uart.enable_rx_interrupts(); - } +// // Manually install the interrupt handler and enable RX IRQs in the peripheral +// unsafe { +// hal::interrupt::LPUART2.install_handler(lpuart2_handler); +// // Enable RX interrupts so the handler actually fires on incoming bytes +// uart.enable_rx_interrupts(); +// } - // Print welcome message - uart.write_str_blocking("UART interrupt echo demo starting...\r\n"); - uart.write_str_blocking("Type characters to echo them back.\r\n"); +// // Print welcome message +// uart.write_str_blocking("UART interrupt echo demo starting...\r\n"); +// uart.write_str_blocking("Type characters to echo them back.\r\n"); - // Log using defmt if enabled - defmt::info!("UART interrupt echo demo starting..."); +// // Log using defmt if enabled +// defmt::info!("UART interrupt echo demo starting..."); - loop { - // Check if we have received any data - if uart.rx_data_available() { - if let Some(byte) = uart.try_read_byte() { - // Echo it back - uart.write_byte(byte); - uart.write_str_blocking(" (received)\r\n"); - } - } else { - // No data available, wait a bit before checking again - cortex_m::asm::delay(12_000_000); // ~1 second at 12MHz - } - } +// loop { +// // Check if we have received any data +// if uart.rx_data_available() { +// if let Some(byte) = uart.try_read_byte() { +// // Echo it back +// uart.write_byte(byte); +// uart.write_str_blocking(" (received)\r\n"); +// } +// } else { +// // No data available, wait a bit before checking again +// cortex_m::asm::delay(12_000_000); // ~1 second at 12MHz +// } +// } } diff --git a/src/adc.rs b/src/adc.rs index 655bf934f..b5ec5983f 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -1,6 +1,10 @@ //! ADC driver use core::sync::atomic::{AtomicBool, Ordering}; +use embassy_hal_internal::{Peri, PeripheralType}; + +use crate::clocks::periph_helpers::{AdcClockSel, AdcConfig, Div4}; +use crate::clocks::{enable_and_reset, Gate, PoweredClock}; use crate::pac; use crate::pac::adc1::cfg::{HptExdi, Pwrsel, Refsel, Tcmdres, Tprictrl, Tres}; use crate::pac::adc1::cmdh1::{Avgs, Cmpen, Next, Sts}; @@ -12,7 +16,7 @@ type Regs = pac::adc1::RegisterBlock; static INTERRUPT_TRIGGERED: AtomicBool = AtomicBool::new(false); // Token-based instance pattern like embassy-imxrt -pub trait Instance { +pub trait Instance: Gate + PeripheralType { fn ptr() -> *const Regs; } @@ -26,12 +30,12 @@ impl Instance for crate::peripherals::ADC1 { } // Also implement Instance for the Peri wrapper type -impl Instance for embassy_hal_internal::Peri<'_, crate::peripherals::ADC1> { - #[inline(always)] - fn ptr() -> *const Regs { - pac::Adc1::ptr() - } -} +// impl Instance for embassy_hal_internal::Peri<'_, crate::peripherals::ADC1> { +// #[inline(always)] +// fn ptr() -> *const Regs { +// pac::Adc1::ptr() +// } +// } #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u8)] @@ -60,6 +64,29 @@ pub struct LpadcConfig { pub enable_conv_pause: bool, pub conv_pause_delay: u16, pub fifo_watermark: u8, + pub power: PoweredClock, + pub source: AdcClockSel, + pub div: Div4, +} + +impl Default for LpadcConfig { + fn default() -> Self { + LpadcConfig { + enable_in_doze_mode: true, + conversion_average_mode: CalAvgs::NoAverage, + enable_analog_preliminary: false, + power_up_delay: 0x80, + reference_voltage_source: Refsel::Option1, + power_level_mode: Pwrsel::Lowest, + trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, + enable_conv_pause: false, + conv_pause_delay: 0, + fifo_watermark: 0, + power: PoweredClock::NormalEnabledDeepSleepDisabled, + source: AdcClockSel::FroLfDiv, + div: Div4::no_div(), + } + } } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -94,15 +121,24 @@ pub struct ConvResult { pub conv_value: u16, } -pub struct Adc { - _inst: core::marker::PhantomData, +pub struct Adc<'a, I: Instance> { + _inst: core::marker::PhantomData<&'a mut I>, } -impl Adc { +impl<'a, I: Instance> Adc<'a, I> { /// initialize ADC - pub fn new(_inst: impl Instance, config: LpadcConfig) -> Self { + pub fn new(_inst: Peri<'a, I>, config: LpadcConfig) -> Self { let adc = unsafe { &*I::ptr() }; + let _clock_freq = unsafe { + enable_and_reset::(&AdcConfig { + power: config.power, + source: config.source, + div: config.div, + }) + .expect("Adc Init should not fail") + }; + /* Reset the module. */ adc.ctrl().modify(|_, w| w.rst().held_in_reset()); adc.ctrl().modify(|_, w| w.rst().released_from_reset()); @@ -194,21 +230,6 @@ impl Adc { adc.ctrl().modify(|_, w| w.adcen().disabled()); } - pub fn get_default_config() -> LpadcConfig { - LpadcConfig { - enable_in_doze_mode: true, - conversion_average_mode: CalAvgs::NoAverage, - enable_analog_preliminary: false, - power_up_delay: 0x80, - reference_voltage_source: Refsel::Option1, - power_level_mode: Pwrsel::Lowest, - trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, - enable_conv_pause: false, - conv_pause_delay: 0, - fifo_watermark: 0, - } - } - pub fn do_offset_calibration(&self) { let adc = unsafe { &*I::ptr() }; // Enable calibration mode diff --git a/src/clocks/mod.rs b/src/clocks/mod.rs index 24e118e38..e04f63b8e 100644 --- a/src/clocks/mod.rs +++ b/src/clocks/mod.rs @@ -79,6 +79,11 @@ pub unsafe fn assert_reset() { G::assert_reset(); } +#[inline] +pub unsafe fn is_reset_released() -> bool { + G::is_reset_released() +} + /// Pulse a reset line (assert then release) with a short delay. #[inline] pub unsafe fn pulse_reset() { @@ -150,12 +155,15 @@ pub mod gate { use super::periph_helpers::{AdcConfig, LpuartConfig, OsTimerConfig}; use super::*; + // These peripherals have no additional upstream clocks or configuration required + // other than enabling through the MRCC gate. impl_cc_gate!(PORT1, mrcc_glb_cc1, port1, NoConfig); impl_cc_gate!(PORT2, mrcc_glb_cc1, port2, NoConfig); impl_cc_gate!(PORT3, mrcc_glb_cc1, port3, NoConfig); + impl_cc_gate!(GPIO3, mrcc_glb_cc2, gpio3, NoConfig); + impl_cc_gate!(OSTIMER0, mrcc_glb_cc1, ostimer0, OsTimerConfig); impl_cc_gate!(LPUART2, mrcc_glb_cc0, lpuart2, LpuartConfig); - impl_cc_gate!(GPIO3, mrcc_glb_cc2, gpio3, NoConfig); impl_cc_gate!(ADC1, mrcc_glb_cc1, adc1, AdcConfig); } @@ -276,7 +284,7 @@ pub struct Clock { pub power: PoweredClock, } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum PoweredClock { NormalEnabledDeepSleepDisabled, AlwaysEnabled, diff --git a/src/clocks/periph_helpers.rs b/src/clocks/periph_helpers.rs index de767ef87..1657bd7eb 100644 --- a/src/clocks/periph_helpers.rs +++ b/src/clocks/periph_helpers.rs @@ -18,6 +18,11 @@ pub trait SPConfHelper { pub struct Div4(pub(super) u8); impl Div4 { + /// Divide by one, or no division + pub const fn no_div() -> Self { + Self(0) + } + /// Store a "raw" divisor value that will divide the source by /// `(n + 1)`, e.g. `Div4::from_raw(0)` will divide the source /// by 1, and `Div4::from_raw(15)` will divide the source by @@ -81,6 +86,7 @@ pub enum LpuartClockSel { None, } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum LpuartInstance { Lpuart0, Lpuart1, @@ -102,6 +108,7 @@ pub struct LpuartConfig { pub(crate) instance: LpuartInstance, } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum OstimerClockSel { /// 16k clock, sourced from FRO16K (Vdd Core) Clk16kVddCore, @@ -116,6 +123,7 @@ pub struct OsTimerConfig { pub source: OstimerClockSel, } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum AdcClockSel { FroLfDiv, FroHf, diff --git a/src/lib.rs b/src/lib.rs index fd7d3cd07..4120c1e84 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,6 @@ pub mod clocks; // still provide clock helpers pub mod gpio; pub mod pins; // pin mux helpers -pub mod reset; // reset control helpers pub mod adc; pub mod config; diff --git a/src/lpuart/mod.rs b/src/lpuart/mod.rs index be69372a2..9e8b25ff6 100644 --- a/src/lpuart/mod.rs +++ b/src/lpuart/mod.rs @@ -545,7 +545,7 @@ impl Default for Config { swap_txd_rxd: false, power: PoweredClock::NormalEnabledDeepSleepDisabled, source: LpuartClockSel::FroLfDiv, - div: const { Div4::from_divisor(1).unwrap() }, + div: Div4::no_div(), } } } diff --git a/src/ostimer.rs b/src/ostimer.rs index 8bc68389a..efa534194 100644 --- a/src/ostimer.rs +++ b/src/ostimer.rs @@ -29,8 +29,13 @@ use core::sync::atomic::{AtomicBool, Ordering}; +use embassy_hal_internal::{Peri, PeripheralType}; + +use crate::clocks::periph_helpers::{OsTimerConfig, OstimerClockSel}; +use crate::clocks::{assert_reset, enable_and_reset, is_reset_released, release_reset, Gate, PoweredClock}; use crate::interrupt::InterruptExt; use crate::pac; +use crate::peripherals::OSTIMER0; // PAC defines the shared RegisterBlock under `ostimer0`. type Regs = pac::ostimer0::RegisterBlock; @@ -197,16 +202,16 @@ impl<'d> Alarm<'d> { pub struct Config { /// Initialize MATCH registers to their max values and mask/clear the interrupt flag. pub init_match_max: bool, - /// OSTIMER clock frequency in Hz (must match the actual hardware clock) - pub clock_frequency_hz: u64, + pub power: PoweredClock, + pub source: OstimerClockSel, } impl Default for Config { fn default() -> Self { Self { init_match_max: true, - // Default to 1MHz - user should override this with actual frequency - clock_frequency_hz: 1_000_000, + power: PoweredClock::NormalEnabledDeepSleepDisabled, + source: OstimerClockSel::Clk1M, } } } @@ -222,8 +227,16 @@ impl<'d, I: Instance> Ostimer<'d, I> { /// Construct OSTIMER handle. /// Requires clocks for the instance to be enabled by the board before calling. /// Does not enable NVIC or INTENA; use time_driver::init() for async operation. - pub fn new(_inst: impl Instance, cfg: Config, _p: &'d crate::pac::Peripherals) -> Self { - assert!(cfg.clock_frequency_hz > 0, "OSTIMER frequency must be greater than 0"); + pub fn new(_inst: Peri<'d, I>, cfg: Config) -> Self { + let clock_freq = unsafe { + enable_and_reset::(&OsTimerConfig { + power: cfg.power, + source: cfg.source, + }) + .expect("Enabling OsTimer clock should not fail") + }; + + assert!(clock_freq > 0, "OSTIMER frequency must be greater than 0"); if cfg.init_match_max { let r: &Regs = unsafe { &*I::ptr() }; @@ -233,7 +246,7 @@ impl<'d, I: Instance> Ostimer<'d, I> { Self { _inst: core::marker::PhantomData, - clock_frequency_hz: cfg.clock_frequency_hz, + clock_frequency_hz: clock_freq as u64, _phantom: core::marker::PhantomData, } } @@ -260,7 +273,7 @@ impl<'d, I: Instance> Ostimer<'d, I> { /// # Safety /// This operation will reset the entire OSTIMER peripheral. Any active alarms /// or time_driver operations will be disrupted. Use with caution. - pub fn reset(&self, peripherals: &crate::pac::Peripherals) { + pub fn reset(&self, _peripherals: &crate::pac::Peripherals) { critical_section::with(|_| { let r: &Regs = unsafe { &*I::ptr() }; @@ -270,19 +283,17 @@ impl<'d, I: Instance> Ostimer<'d, I> { .write(|w| w.ostimer_intrflag().clear_bit_by_one().ostimer_intena().clear_bit()); unsafe { - crate::reset::assert::(peripherals); - } + assert_reset::(); - for _ in 0..RESET_STABILIZE_SPINS { - cortex_m::asm::nop(); - } + for _ in 0..RESET_STABILIZE_SPINS { + cortex_m::asm::nop(); + } - unsafe { - crate::reset::release::(peripherals); - } + release_reset::(); - while !::is_released(&peripherals.mrcc0) { - cortex_m::asm::nop(); + while !is_reset_released::() { + cortex_m::asm::nop(); + } } for _ in 0..RESET_STABILIZE_SPINS { @@ -469,14 +480,13 @@ fn now_ticks_read() -> u64 { // Read high then low to minimize incoherent snapshots let hi = (r.evtimerh().read().evtimer_count_value().bits() as u64) & (EVTIMER_HI_MASK as u64); let lo = r.evtimerl().read().evtimer_count_value().bits() as u64; - // Combine and convert from Gray code to binary let gray = lo | (hi << EVTIMER_HI_SHIFT); gray_to_bin(gray) } // Instance trait like other drivers, providing a PAC pointer for this OSTIMER instance -pub trait Instance { +pub trait Instance: Gate + PeripheralType { fn ptr() -> *const Regs; } @@ -491,12 +501,12 @@ impl Instance for crate::peripherals::OSTIMER0 { } // Also implement Instance for the Peri wrapper type -impl Instance for embassy_hal_internal::Peri<'_, crate::peripherals::OSTIMER0> { - #[inline(always)] - fn ptr() -> *const Regs { - pac::Ostimer0::ptr() - } -} +// impl Instance for embassy_hal_internal::Peri<'_, crate::peripherals::OSTIMER0> { +// #[inline(always)] +// fn ptr() -> *const Regs { +// pac::Ostimer0::ptr() +// } +// } #[inline(always)] fn bin_to_gray(x: u64) -> u64 { diff --git a/src/reset.rs b/src/reset.rs deleted file mode 100644 index 1c131d1cc..000000000 --- a/src/reset.rs +++ /dev/null @@ -1,112 +0,0 @@ -//! Reset control helpers built on PAC field writers. -use crate::pac; - -/// Trait describing a reset line that can be asserted/deasserted. -pub trait ResetLine { - /// Drive the peripheral out of reset. - unsafe fn release(mrcc: &pac::mrcc0::RegisterBlock); - - /// Drive the peripheral into reset. - unsafe fn assert(mrcc: &pac::mrcc0::RegisterBlock); - - /// Check whether the peripheral is currently released. - fn is_released(mrcc: &pac::mrcc0::RegisterBlock) -> bool; -} - -/// Release a reset line for the given peripheral set. -#[inline] -pub unsafe fn release(peripherals: &pac::Peripherals) { - R::release(&peripherals.mrcc0); -} - -/// Assert a reset line for the given peripheral set. -#[inline] -pub unsafe fn assert(peripherals: &pac::Peripherals) { - R::assert(&peripherals.mrcc0); -} - -/// Pulse a reset line (assert then release) with a short delay. -#[inline] -pub unsafe fn pulse(peripherals: &pac::Peripherals) { - let mrcc = &peripherals.mrcc0; - R::assert(mrcc); - cortex_m::asm::nop(); - cortex_m::asm::nop(); - R::release(mrcc); -} - -macro_rules! impl_reset_line { - ($name:ident, $reg:ident, $field:ident) => { - pub struct $name; - - impl ResetLine for $name { - #[inline] - unsafe fn release(mrcc: &pac::mrcc0::RegisterBlock) { - mrcc.$reg().modify(|_, w| w.$field().enabled()); - } - - #[inline] - unsafe fn assert(mrcc: &pac::mrcc0::RegisterBlock) { - mrcc.$reg().modify(|_, w| w.$field().disabled()); - } - - #[inline] - fn is_released(mrcc: &pac::mrcc0::RegisterBlock) -> bool { - mrcc.$reg().read().$field().is_enabled() - } - } - }; -} - -pub mod line { - use super::*; - - impl_reset_line!(Port2, mrcc_glb_rst1, port2); - impl_reset_line!(Port3, mrcc_glb_rst1, port3); - impl_reset_line!(Gpio3, mrcc_glb_rst2, gpio3); - impl_reset_line!(Lpuart2, mrcc_glb_rst0, lpuart2); - impl_reset_line!(Ostimer0, mrcc_glb_rst1, ostimer0); - impl_reset_line!(Port1, mrcc_glb_rst1, port1); - impl_reset_line!(Adc1, mrcc_glb_rst1, adc1); -} - -#[inline] -pub unsafe fn release_reset_port2(peripherals: &pac::Peripherals) { - release::(peripherals); -} - -#[inline] -pub unsafe fn release_reset_port3(peripherals: &pac::Peripherals) { - release::(peripherals); -} - -#[inline] -pub unsafe fn release_reset_gpio3(peripherals: &pac::Peripherals) { - release::(peripherals); -} - -#[inline] -pub unsafe fn release_reset_lpuart2(peripherals: &pac::Peripherals) { - release::(peripherals); -} - -#[inline] -pub unsafe fn release_reset_ostimer0(peripherals: &pac::Peripherals) { - release::(peripherals); -} - -/// Convenience shim retained for existing call sites. -#[inline] -pub unsafe fn reset_ostimer0(peripherals: &pac::Peripherals) { - pulse::(peripherals); -} - -#[inline] -pub unsafe fn release_reset_port1(peripherals: &pac::Peripherals) { - release::(peripherals); -} - -#[inline] -pub unsafe fn release_reset_adc1(peripherals: &pac::Peripherals) { - release::(peripherals); -} -- cgit