diff options
| author | James Munns <[email protected]> | 2025-11-14 17:29:31 +0100 |
|---|---|---|
| committer | James Munns <[email protected]> | 2025-11-14 17:29:31 +0100 |
| commit | e799d6c8956ed3ea5ced65d58c3065a22927ad10 (patch) | |
| tree | 05db757ce7d739c9f7a92905406bae08e3a281e1 | |
| parent | 9b91d886e6a5067d6a553715a053db653af55ca6 (diff) | |
More work on examples
| -rw-r--r-- | examples/adc_interrupt.rs | 15 | ||||
| -rw-r--r-- | examples/common/mod.rs | 38 | ||||
| -rw-r--r-- | examples/lpuart_buffered.rs | 5 | ||||
| -rw-r--r-- | examples/ostimer_alarm.rs | 7 | ||||
| -rw-r--r-- | examples/ostimer_counter.rs | 8 | ||||
| -rw-r--r-- | examples/ostimer_race_test.rs | 5 | ||||
| -rw-r--r-- | examples/uart_interrupt.rs | 100 | ||||
| -rw-r--r-- | src/adc.rs | 73 | ||||
| -rw-r--r-- | src/clocks/mod.rs | 12 | ||||
| -rw-r--r-- | src/clocks/periph_helpers.rs | 8 | ||||
| -rw-r--r-- | src/lib.rs | 1 | ||||
| -rw-r--r-- | src/lpuart/mod.rs | 2 | ||||
| -rw-r--r-- | src/ostimer.rs | 62 | ||||
| -rw-r--r-- | src/reset.rs | 112 |
14 files changed, 186 insertions, 262 deletions
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 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use embassy_executor::Spawner; | 4 | use embassy_executor::Spawner; |
| 5 | use embassy_mcxa276::clocks::periph_helpers::{AdcClockSel, Div4}; | ||
| 6 | use embassy_mcxa276::clocks::PoweredClock; | ||
| 5 | use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; | 7 | use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; |
| 6 | use hal::uart; | 8 | use hal::uart; |
| 7 | use mcxa_pac::adc1::cfg::{Pwrsel, Refsel}; | 9 | use mcxa_pac::adc1::cfg::{Pwrsel, Refsel}; |
| @@ -30,10 +32,10 @@ async fn main(_spawner: Spawner) { | |||
| 30 | common::init_uart2(hal::pac()); | 32 | common::init_uart2(hal::pac()); |
| 31 | } | 33 | } |
| 32 | 34 | ||
| 33 | let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; | 35 | // let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; |
| 34 | let uart = uart::Uart::<uart::Lpuart2>::new(p.LPUART2, uart::Config::new(src)); | 36 | // let uart = uart::Uart::<uart::Lpuart2>::new(p.LPUART2, uart::Config::new(src)); |
| 35 | 37 | ||
| 36 | uart.write_str_blocking("\r\n=== ADC interrupt Example ===\r\n"); | 38 | // uart.write_str_blocking("\r\n=== ADC interrupt Example ===\r\n"); |
| 37 | 39 | ||
| 38 | unsafe { | 40 | unsafe { |
| 39 | common::init_adc(hal::pac()); | 41 | common::init_adc(hal::pac()); |
| @@ -50,6 +52,9 @@ async fn main(_spawner: Spawner) { | |||
| 50 | enable_conv_pause: false, | 52 | enable_conv_pause: false, |
| 51 | conv_pause_delay: 0, | 53 | conv_pause_delay: 0, |
| 52 | fifo_watermark: 0, | 54 | fifo_watermark: 0, |
| 55 | power: PoweredClock::NormalEnabledDeepSleepDisabled, | ||
| 56 | source: AdcClockSel::FroLfDiv, | ||
| 57 | div: Div4::no_div(), | ||
| 53 | }; | 58 | }; |
| 54 | let adc = hal::adc::Adc::<hal::adc::Adc1>::new(p.ADC1, adc_config); | 59 | let adc = hal::adc::Adc::<hal::adc::Adc1>::new(p.ADC1, adc_config); |
| 55 | 60 | ||
| @@ -66,7 +71,7 @@ async fn main(_spawner: Spawner) { | |||
| 66 | conv_trigger_config.enable_hardware_trigger = false; | 71 | conv_trigger_config.enable_hardware_trigger = false; |
| 67 | adc.set_conv_trigger_config(0, &conv_trigger_config); | 72 | adc.set_conv_trigger_config(0, &conv_trigger_config); |
| 68 | 73 | ||
| 69 | uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); | 74 | // uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); |
| 70 | 75 | ||
| 71 | adc.enable_interrupt(0x1); | 76 | adc.enable_interrupt(0x1); |
| 72 | 77 | ||
| @@ -83,7 +88,7 @@ async fn main(_spawner: Spawner) { | |||
| 83 | while !adc.is_interrupt_triggered() { | 88 | while !adc.is_interrupt_triggered() { |
| 84 | // Wait until the interrupt is triggered | 89 | // Wait until the interrupt is triggered |
| 85 | } | 90 | } |
| 86 | uart.write_str_blocking("\r\n*** ADC interrupt TRIGGERED! ***\r\n"); | 91 | // uart.write_str_blocking("\r\n*** ADC interrupt TRIGGERED! ***\r\n"); |
| 87 | //TBD need to print the value | 92 | //TBD need to print the value |
| 88 | } | 93 | } |
| 89 | } | 94 | } |
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 @@ | |||
| 1 | //! Shared board-specific helpers for the FRDM-MCXA276 examples. | 1 | //! Shared board-specific helpers for the FRDM-MCXA276 examples. |
| 2 | //! These live with the examples so the HAL stays generic. | 2 | //! These live with the examples so the HAL stays generic. |
| 3 | 3 | ||
| 4 | use hal::{clocks, pins, reset}; | 4 | use hal::{clocks, pins}; |
| 5 | use {embassy_mcxa276 as hal, panic_probe as _}; | 5 | use {embassy_mcxa276 as hal, panic_probe as _}; |
| 6 | 6 | ||
| 7 | /// Initialize clocks and pin muxing for UART2 debug console. | 7 | /// Initialize clocks and pin muxing for UART2 debug console. |
| 8 | /// Safe to call multiple times; writes are idempotent for our use. | 8 | /// Safe to call multiple times; writes are idempotent for our use. |
| 9 | #[allow(dead_code)] | 9 | #[allow(dead_code)] |
| 10 | pub unsafe fn init_uart2(p: &mcxa_pac::Peripherals) { | 10 | pub unsafe fn init_uart2(_p: &mcxa_pac::Peripherals) { |
| 11 | clocks::ensure_frolf_running(p); | 11 | // NOTE: Lpuart has been updated to properly enable + reset its own clocks. |
| 12 | clocks::enable_uart2_port2(p); | 12 | // GPIO has not. |
| 13 | reset::release_reset_port2(p); | 13 | _ = clocks::enable_and_reset::<hal::peripherals::PORT2>(&clocks::NoConfig); |
| 14 | reset::release_reset_lpuart2(p); | ||
| 15 | pins::configure_uart2_pins_port2(); | 14 | pins::configure_uart2_pins_port2(); |
| 16 | clocks::select_uart2_clock(p); | ||
| 17 | } | 15 | } |
| 18 | 16 | ||
| 19 | /// Initialize clocks for the LED GPIO/PORT used by the blink example. | 17 | /// Initialize clocks for the LED GPIO/PORT used by the blink example. |
| 20 | #[allow(dead_code)] | 18 | #[allow(dead_code)] |
| 21 | pub unsafe fn init_led(p: &mcxa_pac::Peripherals) { | 19 | pub unsafe fn init_led(_p: &mcxa_pac::Peripherals) { |
| 22 | clocks::enable_led_port(p); | 20 | _ = clocks::enable_and_reset::<hal::peripherals::PORT3>(&clocks::NoConfig); |
| 23 | reset::release_reset_gpio3(p); | 21 | _ = clocks::enable_and_reset::<hal::peripherals::GPIO3>(&clocks::NoConfig); |
| 24 | reset::release_reset_port3(p); | ||
| 25 | } | ||
| 26 | |||
| 27 | /// Initialize clocks for OSTIMER0 (1 MHz source). | ||
| 28 | #[allow(dead_code)] | ||
| 29 | pub unsafe fn init_ostimer0(p: &mcxa_pac::Peripherals) { | ||
| 30 | clocks::ensure_frolf_running(p); | ||
| 31 | clocks::enable_ostimer0(p); | ||
| 32 | reset::release_reset_ostimer0(p); | ||
| 33 | clocks::select_ostimer0_clock_1m(p); | ||
| 34 | } | 22 | } |
| 35 | 23 | ||
| 36 | /// Initialize clocks and pin muxing for ADC. | 24 | /// Initialize clocks and pin muxing for ADC. |
| 37 | #[allow(dead_code)] | 25 | #[allow(dead_code)] |
| 38 | pub unsafe fn init_adc(p: &mcxa_pac::Peripherals) { | 26 | pub unsafe fn init_adc(_p: &mcxa_pac::Peripherals) { |
| 39 | clocks::ensure_frolf_running(p); | 27 | // NOTE: Lpuart has been updated to properly enable + reset its own clocks. |
| 40 | clocks::enable_adc(p); | 28 | // GPIO has not. |
| 41 | reset::release_reset_port1(p); | 29 | _ = clocks::enable_and_reset::<hal::peripherals::PORT1>(&clocks::NoConfig); |
| 42 | reset::release_reset_adc1(p); | ||
| 43 | pins::configure_adc_pins(); | 30 | pins::configure_adc_pins(); |
| 44 | clocks::select_adc_clock(p); | ||
| 45 | } | 31 | } |
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; | |||
| 12 | 12 | ||
| 13 | // Bind OS_EVENT for timers plus LPUART2 IRQ for the buffered driver | 13 | // Bind OS_EVENT for timers plus LPUART2 IRQ for the buffered driver |
| 14 | bind_interrupts!(struct Irqs { | 14 | bind_interrupts!(struct Irqs { |
| 15 | LPUART2 => lpuart::buffered::BufferedInterruptHandler::<lpuart::lib::peripherals::LPUART2>; | 15 | LPUART2 => lpuart::buffered::BufferedInterruptHandler::<hal::peripherals::LPUART2>; |
| 16 | }); | 16 | }); |
| 17 | 17 | ||
| 18 | // Wrapper function for the interrupt handler | 18 | // Wrapper function for the interrupt handler |
| 19 | unsafe extern "C" fn lpuart2_handler() { | 19 | unsafe extern "C" fn lpuart2_handler() { |
| 20 | lpuart::buffered::BufferedInterruptHandler::<lpuart::lib::peripherals::LPUART2>::on_interrupt(); | 20 | lpuart::buffered::BufferedInterruptHandler::<hal::peripherals::LPUART2>::on_interrupt(); |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | #[embassy_executor::main] | 23 | #[embassy_executor::main] |
| 24 | async fn main(_spawner: Spawner) { | 24 | async fn main(_spawner: Spawner) { |
| 25 | let _p = hal::init(hal::config::Config::default()); | 25 | let _p = hal::init(hal::config::Config::default()); |
| 26 | let p2 = lpuart::lib::init(); | ||
| 27 | 26 | ||
| 28 | unsafe { | 27 | unsafe { |
| 29 | hal::interrupt::install_irq_handler(mcxa_pac::Interrupt::LPUART2, lpuart2_handler); | 28 | 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}; | |||
| 9 | 9 | ||
| 10 | mod common; | 10 | mod common; |
| 11 | 11 | ||
| 12 | use embassy_mcxa276::bind_interrupts; | 12 | use embassy_mcxa276::{bind_interrupts, clocks::{periph_helpers::OstimerClockSel, PoweredClock}}; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 14 | ||
| 15 | // Bind only OS_EVENT, and retain the symbol explicitly so it can't be GC'ed. | 15 | // 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) { | |||
| 50 | // Create OSTIMER instance | 50 | // Create OSTIMER instance |
| 51 | let config = hal::ostimer::Config { | 51 | let config = hal::ostimer::Config { |
| 52 | init_match_max: true, | 52 | init_match_max: true, |
| 53 | clock_frequency_hz: 1_000_000, // 1MHz | 53 | power: PoweredClock::NormalEnabledDeepSleepDisabled, |
| 54 | source: OstimerClockSel::Clk1M, | ||
| 54 | }; | 55 | }; |
| 55 | let ostimer = hal::ostimer::Ostimer::<hal::ostimer::Ostimer0>::new(p.OSTIMER0, config, hal::pac()); | 56 | let ostimer = hal::ostimer::Ostimer::<hal::ostimer::Ostimer0>::new(p.OSTIMER0, config); |
| 56 | 57 | ||
| 57 | // Create alarm with callback | 58 | // Create alarm with callback |
| 58 | let alarm = hal::ostimer::Alarm::new() | 59 | 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 @@ | |||
| 7 | #![no_main] | 7 | #![no_main] |
| 8 | 8 | ||
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_mcxa276::clocks::{periph_helpers::OstimerClockSel, PoweredClock}; | ||
| 10 | use embassy_time::{Duration, Timer}; | 11 | use embassy_time::{Duration, Timer}; |
| 11 | use hal::bind_interrupts; | 12 | use hal::bind_interrupts; |
| 12 | use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; | 13 | use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; |
| @@ -23,9 +24,6 @@ async fn main(_spawner: Spawner) { | |||
| 23 | 24 | ||
| 24 | // Enable/clock OSTIMER0 and UART2 before touching their registers | 25 | // Enable/clock OSTIMER0 and UART2 before touching their registers |
| 25 | unsafe { | 26 | unsafe { |
| 26 | common::init_ostimer0(hal::pac()); | ||
| 27 | } | ||
| 28 | unsafe { | ||
| 29 | common::init_uart2(hal::pac()); | 27 | common::init_uart2(hal::pac()); |
| 30 | } | 28 | } |
| 31 | let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; | 29 | let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; |
| @@ -44,9 +42,9 @@ async fn main(_spawner: Spawner) { | |||
| 44 | p.OSTIMER0, | 42 | p.OSTIMER0, |
| 45 | hal::ostimer::Config { | 43 | hal::ostimer::Config { |
| 46 | init_match_max: true, | 44 | init_match_max: true, |
| 47 | clock_frequency_hz: 1_000_000, | 45 | power: PoweredClock::NormalEnabledDeepSleepDisabled, |
| 46 | source: OstimerClockSel::Clk1M, | ||
| 48 | }, | 47 | }, |
| 49 | hal::pac(), | ||
| 50 | ); | 48 | ); |
| 51 | 49 | ||
| 52 | // Read initial counter value | 50 | // 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 @@ | |||
| 12 | use core::sync::atomic::{AtomicU32, Ordering}; | 12 | use core::sync::atomic::{AtomicU32, Ordering}; |
| 13 | 13 | ||
| 14 | use embassy_executor::Spawner; | 14 | use embassy_executor::Spawner; |
| 15 | use embassy_mcxa276::clocks::{periph_helpers::OstimerClockSel, PoweredClock}; | ||
| 15 | use embassy_time::{Duration, Timer}; | 16 | use embassy_time::{Duration, Timer}; |
| 16 | use hal::bind_interrupts; | 17 | use hal::bind_interrupts; |
| 17 | use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; | 18 | use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; |
| @@ -98,9 +99,9 @@ async fn main(_spawner: Spawner) { | |||
| 98 | p.OSTIMER0, | 99 | p.OSTIMER0, |
| 99 | hal::ostimer::Config { | 100 | hal::ostimer::Config { |
| 100 | init_match_max: true, | 101 | init_match_max: true, |
| 101 | clock_frequency_hz: 1_000_000, | 102 | power: PoweredClock::NormalEnabledDeepSleepDisabled, |
| 103 | source: OstimerClockSel::Clk1M, | ||
| 102 | }, | 104 | }, |
| 103 | hal::pac(), | ||
| 104 | ); | 105 | ); |
| 105 | 106 | ||
| 106 | uart.write_str_blocking("OSTIMER instance created\n"); | 107 | 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 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use embassy_executor::Spawner; | 4 | use embassy_executor::Spawner; |
| 5 | use embassy_mcxa276 as hal; | 5 | // use embassy_mcxa276 as hal; |
| 6 | use hal::interrupt::typelevel::Handler; | 6 | // use hal::interrupt::typelevel::Handler; |
| 7 | use hal::uart; | 7 | // use hal::uart; |
| 8 | 8 | ||
| 9 | mod common; | 9 | // mod common; |
| 10 | 10 | ||
| 11 | use embassy_mcxa276::bind_interrupts; | 11 | // use embassy_mcxa276::bind_interrupts; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | // use {defmt_rtt as _, panic_probe as _}; |
| 13 | 13 | ||
| 14 | // Bind LPUART2 interrupt to our handler | 14 | // // Bind LPUART2 interrupt to our handler |
| 15 | bind_interrupts!(struct Irqs { | 15 | // bind_interrupts!(struct Irqs { |
| 16 | LPUART2 => hal::uart::UartInterruptHandler; | 16 | // LPUART2 => hal::uart::UartInterruptHandler; |
| 17 | }); | 17 | // }); |
| 18 | 18 | ||
| 19 | #[used] | 19 | // #[used] |
| 20 | #[no_mangle] | 20 | // #[no_mangle] |
| 21 | static KEEP_LPUART2: unsafe extern "C" fn() = LPUART2; | 21 | // static KEEP_LPUART2: unsafe extern "C" fn() = LPUART2; |
| 22 | 22 | ||
| 23 | // Wrapper function for the interrupt handler | 23 | // // Wrapper function for the interrupt handler |
| 24 | unsafe extern "C" fn lpuart2_handler() { | 24 | // unsafe extern "C" fn lpuart2_handler() { |
| 25 | hal::uart::UartInterruptHandler::on_interrupt(); | 25 | // hal::uart::UartInterruptHandler::on_interrupt(); |
| 26 | } | 26 | // } |
| 27 | 27 | ||
| 28 | #[embassy_executor::main] | 28 | #[embassy_executor::main] |
| 29 | async fn main(_spawner: Spawner) { | 29 | async fn main(_spawner: Spawner) { |
| 30 | let _p = hal::init(hal::config::Config::default()); | 30 | // let _p = hal::init(hal::config::Config::default()); |
| 31 | 31 | ||
| 32 | // Enable/clock UART2 before touching its registers | 32 | // // Enable/clock UART2 before touching its registers |
| 33 | unsafe { | 33 | // unsafe { |
| 34 | common::init_uart2(hal::pac()); | 34 | // common::init_uart2(hal::pac()); |
| 35 | } | 35 | // } |
| 36 | let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; | 36 | // let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; |
| 37 | let uart = uart::Uart::<uart::Lpuart2>::new(_p.LPUART2, uart::Config::new(src)); | 37 | // let uart = uart::Uart::<uart::Lpuart2>::new(_p.LPUART2, uart::Config::new(src)); |
| 38 | 38 | ||
| 39 | // Configure LPUART2 interrupt for UART operation BEFORE any UART usage | 39 | // // Configure LPUART2 interrupt for UART operation BEFORE any UART usage |
| 40 | hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::from(3)); | 40 | // hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::from(3)); |
| 41 | 41 | ||
| 42 | // Manually install the interrupt handler and enable RX IRQs in the peripheral | 42 | // // Manually install the interrupt handler and enable RX IRQs in the peripheral |
| 43 | unsafe { | 43 | // unsafe { |
| 44 | hal::interrupt::LPUART2.install_handler(lpuart2_handler); | 44 | // hal::interrupt::LPUART2.install_handler(lpuart2_handler); |
| 45 | // Enable RX interrupts so the handler actually fires on incoming bytes | 45 | // // Enable RX interrupts so the handler actually fires on incoming bytes |
| 46 | uart.enable_rx_interrupts(); | 46 | // uart.enable_rx_interrupts(); |
| 47 | } | 47 | // } |
| 48 | 48 | ||
| 49 | // Print welcome message | 49 | // // Print welcome message |
| 50 | uart.write_str_blocking("UART interrupt echo demo starting...\r\n"); | 50 | // uart.write_str_blocking("UART interrupt echo demo starting...\r\n"); |
| 51 | uart.write_str_blocking("Type characters to echo them back.\r\n"); | 51 | // uart.write_str_blocking("Type characters to echo them back.\r\n"); |
| 52 | 52 | ||
| 53 | // Log using defmt if enabled | 53 | // // Log using defmt if enabled |
| 54 | defmt::info!("UART interrupt echo demo starting..."); | 54 | // defmt::info!("UART interrupt echo demo starting..."); |
| 55 | 55 | ||
| 56 | loop { | 56 | // loop { |
| 57 | // Check if we have received any data | 57 | // // Check if we have received any data |
| 58 | if uart.rx_data_available() { | 58 | // if uart.rx_data_available() { |
| 59 | if let Some(byte) = uart.try_read_byte() { | 59 | // if let Some(byte) = uart.try_read_byte() { |
| 60 | // Echo it back | 60 | // // Echo it back |
| 61 | uart.write_byte(byte); | 61 | // uart.write_byte(byte); |
| 62 | uart.write_str_blocking(" (received)\r\n"); | 62 | // uart.write_str_blocking(" (received)\r\n"); |
| 63 | } | 63 | // } |
| 64 | } else { | 64 | // } else { |
| 65 | // No data available, wait a bit before checking again | 65 | // // No data available, wait a bit before checking again |
| 66 | cortex_m::asm::delay(12_000_000); // ~1 second at 12MHz | 66 | // cortex_m::asm::delay(12_000_000); // ~1 second at 12MHz |
| 67 | } | 67 | // } |
| 68 | } | 68 | // } |
| 69 | } | 69 | } |
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 @@ | |||
| 1 | //! ADC driver | 1 | //! ADC driver |
| 2 | use core::sync::atomic::{AtomicBool, Ordering}; | 2 | use core::sync::atomic::{AtomicBool, Ordering}; |
| 3 | 3 | ||
| 4 | use embassy_hal_internal::{Peri, PeripheralType}; | ||
| 5 | |||
| 6 | use crate::clocks::periph_helpers::{AdcClockSel, AdcConfig, Div4}; | ||
| 7 | use crate::clocks::{enable_and_reset, Gate, PoweredClock}; | ||
| 4 | use crate::pac; | 8 | use crate::pac; |
| 5 | use crate::pac::adc1::cfg::{HptExdi, Pwrsel, Refsel, Tcmdres, Tprictrl, Tres}; | 9 | use crate::pac::adc1::cfg::{HptExdi, Pwrsel, Refsel, Tcmdres, Tprictrl, Tres}; |
| 6 | use crate::pac::adc1::cmdh1::{Avgs, Cmpen, Next, Sts}; | 10 | use crate::pac::adc1::cmdh1::{Avgs, Cmpen, Next, Sts}; |
| @@ -12,7 +16,7 @@ type Regs = pac::adc1::RegisterBlock; | |||
| 12 | 16 | ||
| 13 | static INTERRUPT_TRIGGERED: AtomicBool = AtomicBool::new(false); | 17 | static INTERRUPT_TRIGGERED: AtomicBool = AtomicBool::new(false); |
| 14 | // Token-based instance pattern like embassy-imxrt | 18 | // Token-based instance pattern like embassy-imxrt |
| 15 | pub trait Instance { | 19 | pub trait Instance: Gate<MrccPeriphConfig = AdcConfig> + PeripheralType { |
| 16 | fn ptr() -> *const Regs; | 20 | fn ptr() -> *const Regs; |
| 17 | } | 21 | } |
| 18 | 22 | ||
| @@ -26,12 +30,12 @@ impl Instance for crate::peripherals::ADC1 { | |||
| 26 | } | 30 | } |
| 27 | 31 | ||
| 28 | // Also implement Instance for the Peri wrapper type | 32 | // Also implement Instance for the Peri wrapper type |
| 29 | impl Instance for embassy_hal_internal::Peri<'_, crate::peripherals::ADC1> { | 33 | // impl Instance for embassy_hal_internal::Peri<'_, crate::peripherals::ADC1> { |
| 30 | #[inline(always)] | 34 | // #[inline(always)] |
| 31 | fn ptr() -> *const Regs { | 35 | // fn ptr() -> *const Regs { |
| 32 | pac::Adc1::ptr() | 36 | // pac::Adc1::ptr() |
| 33 | } | 37 | // } |
| 34 | } | 38 | // } |
| 35 | 39 | ||
| 36 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 40 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| 37 | #[repr(u8)] | 41 | #[repr(u8)] |
| @@ -60,6 +64,29 @@ pub struct LpadcConfig { | |||
| 60 | pub enable_conv_pause: bool, | 64 | pub enable_conv_pause: bool, |
| 61 | pub conv_pause_delay: u16, | 65 | pub conv_pause_delay: u16, |
| 62 | pub fifo_watermark: u8, | 66 | pub fifo_watermark: u8, |
| 67 | pub power: PoweredClock, | ||
| 68 | pub source: AdcClockSel, | ||
| 69 | pub div: Div4, | ||
| 70 | } | ||
| 71 | |||
| 72 | impl Default for LpadcConfig { | ||
| 73 | fn default() -> Self { | ||
| 74 | LpadcConfig { | ||
| 75 | enable_in_doze_mode: true, | ||
| 76 | conversion_average_mode: CalAvgs::NoAverage, | ||
| 77 | enable_analog_preliminary: false, | ||
| 78 | power_up_delay: 0x80, | ||
| 79 | reference_voltage_source: Refsel::Option1, | ||
| 80 | power_level_mode: Pwrsel::Lowest, | ||
| 81 | trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, | ||
| 82 | enable_conv_pause: false, | ||
| 83 | conv_pause_delay: 0, | ||
| 84 | fifo_watermark: 0, | ||
| 85 | power: PoweredClock::NormalEnabledDeepSleepDisabled, | ||
| 86 | source: AdcClockSel::FroLfDiv, | ||
| 87 | div: Div4::no_div(), | ||
| 88 | } | ||
| 89 | } | ||
| 63 | } | 90 | } |
| 64 | 91 | ||
| 65 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 92 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| @@ -94,15 +121,24 @@ pub struct ConvResult { | |||
| 94 | pub conv_value: u16, | 121 | pub conv_value: u16, |
| 95 | } | 122 | } |
| 96 | 123 | ||
| 97 | pub struct Adc<I: Instance> { | 124 | pub struct Adc<'a, I: Instance> { |
| 98 | _inst: core::marker::PhantomData<I>, | 125 | _inst: core::marker::PhantomData<&'a mut I>, |
| 99 | } | 126 | } |
| 100 | 127 | ||
| 101 | impl<I: Instance> Adc<I> { | 128 | impl<'a, I: Instance> Adc<'a, I> { |
| 102 | /// initialize ADC | 129 | /// initialize ADC |
| 103 | pub fn new(_inst: impl Instance, config: LpadcConfig) -> Self { | 130 | pub fn new(_inst: Peri<'a, I>, config: LpadcConfig) -> Self { |
| 104 | let adc = unsafe { &*I::ptr() }; | 131 | let adc = unsafe { &*I::ptr() }; |
| 105 | 132 | ||
| 133 | let _clock_freq = unsafe { | ||
| 134 | enable_and_reset::<I>(&AdcConfig { | ||
| 135 | power: config.power, | ||
| 136 | source: config.source, | ||
| 137 | div: config.div, | ||
| 138 | }) | ||
| 139 | .expect("Adc Init should not fail") | ||
| 140 | }; | ||
| 141 | |||
| 106 | /* Reset the module. */ | 142 | /* Reset the module. */ |
| 107 | adc.ctrl().modify(|_, w| w.rst().held_in_reset()); | 143 | adc.ctrl().modify(|_, w| w.rst().held_in_reset()); |
| 108 | adc.ctrl().modify(|_, w| w.rst().released_from_reset()); | 144 | adc.ctrl().modify(|_, w| w.rst().released_from_reset()); |
| @@ -194,21 +230,6 @@ impl<I: Instance> Adc<I> { | |||
| 194 | adc.ctrl().modify(|_, w| w.adcen().disabled()); | 230 | adc.ctrl().modify(|_, w| w.adcen().disabled()); |
| 195 | } | 231 | } |
| 196 | 232 | ||
| 197 | pub fn get_default_config() -> LpadcConfig { | ||
| 198 | LpadcConfig { | ||
| 199 | enable_in_doze_mode: true, | ||
| 200 | conversion_average_mode: CalAvgs::NoAverage, | ||
| 201 | enable_analog_preliminary: false, | ||
| 202 | power_up_delay: 0x80, | ||
| 203 | reference_voltage_source: Refsel::Option1, | ||
| 204 | power_level_mode: Pwrsel::Lowest, | ||
| 205 | trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, | ||
| 206 | enable_conv_pause: false, | ||
| 207 | conv_pause_delay: 0, | ||
| 208 | fifo_watermark: 0, | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | pub fn do_offset_calibration(&self) { | 233 | pub fn do_offset_calibration(&self) { |
| 213 | let adc = unsafe { &*I::ptr() }; | 234 | let adc = unsafe { &*I::ptr() }; |
| 214 | // Enable calibration mode | 235 | // 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: Gate>() { | |||
| 79 | G::assert_reset(); | 79 | G::assert_reset(); |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | #[inline] | ||
| 83 | pub unsafe fn is_reset_released<G: Gate>() -> bool { | ||
| 84 | G::is_reset_released() | ||
| 85 | } | ||
| 86 | |||
| 82 | /// Pulse a reset line (assert then release) with a short delay. | 87 | /// Pulse a reset line (assert then release) with a short delay. |
| 83 | #[inline] | 88 | #[inline] |
| 84 | pub unsafe fn pulse_reset<G: Gate>() { | 89 | pub unsafe fn pulse_reset<G: Gate>() { |
| @@ -150,12 +155,15 @@ pub mod gate { | |||
| 150 | use super::periph_helpers::{AdcConfig, LpuartConfig, OsTimerConfig}; | 155 | use super::periph_helpers::{AdcConfig, LpuartConfig, OsTimerConfig}; |
| 151 | use super::*; | 156 | use super::*; |
| 152 | 157 | ||
| 158 | // These peripherals have no additional upstream clocks or configuration required | ||
| 159 | // other than enabling through the MRCC gate. | ||
| 153 | impl_cc_gate!(PORT1, mrcc_glb_cc1, port1, NoConfig); | 160 | impl_cc_gate!(PORT1, mrcc_glb_cc1, port1, NoConfig); |
| 154 | impl_cc_gate!(PORT2, mrcc_glb_cc1, port2, NoConfig); | 161 | impl_cc_gate!(PORT2, mrcc_glb_cc1, port2, NoConfig); |
| 155 | impl_cc_gate!(PORT3, mrcc_glb_cc1, port3, NoConfig); | 162 | impl_cc_gate!(PORT3, mrcc_glb_cc1, port3, NoConfig); |
| 163 | impl_cc_gate!(GPIO3, mrcc_glb_cc2, gpio3, NoConfig); | ||
| 164 | |||
| 156 | impl_cc_gate!(OSTIMER0, mrcc_glb_cc1, ostimer0, OsTimerConfig); | 165 | impl_cc_gate!(OSTIMER0, mrcc_glb_cc1, ostimer0, OsTimerConfig); |
| 157 | impl_cc_gate!(LPUART2, mrcc_glb_cc0, lpuart2, LpuartConfig); | 166 | impl_cc_gate!(LPUART2, mrcc_glb_cc0, lpuart2, LpuartConfig); |
| 158 | impl_cc_gate!(GPIO3, mrcc_glb_cc2, gpio3, NoConfig); | ||
| 159 | impl_cc_gate!(ADC1, mrcc_glb_cc1, adc1, AdcConfig); | 167 | impl_cc_gate!(ADC1, mrcc_glb_cc1, adc1, AdcConfig); |
| 160 | } | 168 | } |
| 161 | 169 | ||
| @@ -276,7 +284,7 @@ pub struct Clock { | |||
| 276 | pub power: PoweredClock, | 284 | pub power: PoweredClock, |
| 277 | } | 285 | } |
| 278 | 286 | ||
| 279 | #[derive(Debug, Clone, Copy)] | 287 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| 280 | pub enum PoweredClock { | 288 | pub enum PoweredClock { |
| 281 | NormalEnabledDeepSleepDisabled, | 289 | NormalEnabledDeepSleepDisabled, |
| 282 | AlwaysEnabled, | 290 | 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 { | |||
| 18 | pub struct Div4(pub(super) u8); | 18 | pub struct Div4(pub(super) u8); |
| 19 | 19 | ||
| 20 | impl Div4 { | 20 | impl Div4 { |
| 21 | /// Divide by one, or no division | ||
| 22 | pub const fn no_div() -> Self { | ||
| 23 | Self(0) | ||
| 24 | } | ||
| 25 | |||
| 21 | /// Store a "raw" divisor value that will divide the source by | 26 | /// Store a "raw" divisor value that will divide the source by |
| 22 | /// `(n + 1)`, e.g. `Div4::from_raw(0)` will divide the source | 27 | /// `(n + 1)`, e.g. `Div4::from_raw(0)` will divide the source |
| 23 | /// by 1, and `Div4::from_raw(15)` will divide the source by | 28 | /// by 1, and `Div4::from_raw(15)` will divide the source by |
| @@ -81,6 +86,7 @@ pub enum LpuartClockSel { | |||
| 81 | None, | 86 | None, |
| 82 | } | 87 | } |
| 83 | 88 | ||
| 89 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] | ||
| 84 | pub enum LpuartInstance { | 90 | pub enum LpuartInstance { |
| 85 | Lpuart0, | 91 | Lpuart0, |
| 86 | Lpuart1, | 92 | Lpuart1, |
| @@ -102,6 +108,7 @@ pub struct LpuartConfig { | |||
| 102 | pub(crate) instance: LpuartInstance, | 108 | pub(crate) instance: LpuartInstance, |
| 103 | } | 109 | } |
| 104 | 110 | ||
| 111 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] | ||
| 105 | pub enum OstimerClockSel { | 112 | pub enum OstimerClockSel { |
| 106 | /// 16k clock, sourced from FRO16K (Vdd Core) | 113 | /// 16k clock, sourced from FRO16K (Vdd Core) |
| 107 | Clk16kVddCore, | 114 | Clk16kVddCore, |
| @@ -116,6 +123,7 @@ pub struct OsTimerConfig { | |||
| 116 | pub source: OstimerClockSel, | 123 | pub source: OstimerClockSel, |
| 117 | } | 124 | } |
| 118 | 125 | ||
| 126 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] | ||
| 119 | pub enum AdcClockSel { | 127 | pub enum AdcClockSel { |
| 120 | FroLfDiv, | 128 | FroLfDiv, |
| 121 | FroHf, | 129 | 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 @@ | |||
| 6 | pub mod clocks; // still provide clock helpers | 6 | pub mod clocks; // still provide clock helpers |
| 7 | pub mod gpio; | 7 | pub mod gpio; |
| 8 | pub mod pins; // pin mux helpers | 8 | pub mod pins; // pin mux helpers |
| 9 | pub mod reset; // reset control helpers | ||
| 10 | 9 | ||
| 11 | pub mod adc; | 10 | pub mod adc; |
| 12 | pub mod config; | 11 | 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 { | |||
| 545 | swap_txd_rxd: false, | 545 | swap_txd_rxd: false, |
| 546 | power: PoweredClock::NormalEnabledDeepSleepDisabled, | 546 | power: PoweredClock::NormalEnabledDeepSleepDisabled, |
| 547 | source: LpuartClockSel::FroLfDiv, | 547 | source: LpuartClockSel::FroLfDiv, |
| 548 | div: const { Div4::from_divisor(1).unwrap() }, | 548 | div: Div4::no_div(), |
| 549 | } | 549 | } |
| 550 | } | 550 | } |
| 551 | } | 551 | } |
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 @@ | |||
| 29 | 29 | ||
| 30 | use core::sync::atomic::{AtomicBool, Ordering}; | 30 | use core::sync::atomic::{AtomicBool, Ordering}; |
| 31 | 31 | ||
| 32 | use embassy_hal_internal::{Peri, PeripheralType}; | ||
| 33 | |||
| 34 | use crate::clocks::periph_helpers::{OsTimerConfig, OstimerClockSel}; | ||
| 35 | use crate::clocks::{assert_reset, enable_and_reset, is_reset_released, release_reset, Gate, PoweredClock}; | ||
| 32 | use crate::interrupt::InterruptExt; | 36 | use crate::interrupt::InterruptExt; |
| 33 | use crate::pac; | 37 | use crate::pac; |
| 38 | use crate::peripherals::OSTIMER0; | ||
| 34 | 39 | ||
| 35 | // PAC defines the shared RegisterBlock under `ostimer0`. | 40 | // PAC defines the shared RegisterBlock under `ostimer0`. |
| 36 | type Regs = pac::ostimer0::RegisterBlock; | 41 | type Regs = pac::ostimer0::RegisterBlock; |
| @@ -197,16 +202,16 @@ impl<'d> Alarm<'d> { | |||
| 197 | pub struct Config { | 202 | pub struct Config { |
| 198 | /// Initialize MATCH registers to their max values and mask/clear the interrupt flag. | 203 | /// Initialize MATCH registers to their max values and mask/clear the interrupt flag. |
| 199 | pub init_match_max: bool, | 204 | pub init_match_max: bool, |
| 200 | /// OSTIMER clock frequency in Hz (must match the actual hardware clock) | 205 | pub power: PoweredClock, |
| 201 | pub clock_frequency_hz: u64, | 206 | pub source: OstimerClockSel, |
| 202 | } | 207 | } |
| 203 | 208 | ||
| 204 | impl Default for Config { | 209 | impl Default for Config { |
| 205 | fn default() -> Self { | 210 | fn default() -> Self { |
| 206 | Self { | 211 | Self { |
| 207 | init_match_max: true, | 212 | init_match_max: true, |
| 208 | // Default to 1MHz - user should override this with actual frequency | 213 | power: PoweredClock::NormalEnabledDeepSleepDisabled, |
| 209 | clock_frequency_hz: 1_000_000, | 214 | source: OstimerClockSel::Clk1M, |
| 210 | } | 215 | } |
| 211 | } | 216 | } |
| 212 | } | 217 | } |
| @@ -222,8 +227,16 @@ impl<'d, I: Instance> Ostimer<'d, I> { | |||
| 222 | /// Construct OSTIMER handle. | 227 | /// Construct OSTIMER handle. |
| 223 | /// Requires clocks for the instance to be enabled by the board before calling. | 228 | /// Requires clocks for the instance to be enabled by the board before calling. |
| 224 | /// Does not enable NVIC or INTENA; use time_driver::init() for async operation. | 229 | /// Does not enable NVIC or INTENA; use time_driver::init() for async operation. |
| 225 | pub fn new(_inst: impl Instance, cfg: Config, _p: &'d crate::pac::Peripherals) -> Self { | 230 | pub fn new(_inst: Peri<'d, I>, cfg: Config) -> Self { |
| 226 | assert!(cfg.clock_frequency_hz > 0, "OSTIMER frequency must be greater than 0"); | 231 | let clock_freq = unsafe { |
| 232 | enable_and_reset::<I>(&OsTimerConfig { | ||
| 233 | power: cfg.power, | ||
| 234 | source: cfg.source, | ||
| 235 | }) | ||
| 236 | .expect("Enabling OsTimer clock should not fail") | ||
| 237 | }; | ||
| 238 | |||
| 239 | assert!(clock_freq > 0, "OSTIMER frequency must be greater than 0"); | ||
| 227 | 240 | ||
| 228 | if cfg.init_match_max { | 241 | if cfg.init_match_max { |
| 229 | let r: &Regs = unsafe { &*I::ptr() }; | 242 | let r: &Regs = unsafe { &*I::ptr() }; |
| @@ -233,7 +246,7 @@ impl<'d, I: Instance> Ostimer<'d, I> { | |||
| 233 | 246 | ||
| 234 | Self { | 247 | Self { |
| 235 | _inst: core::marker::PhantomData, | 248 | _inst: core::marker::PhantomData, |
| 236 | clock_frequency_hz: cfg.clock_frequency_hz, | 249 | clock_frequency_hz: clock_freq as u64, |
| 237 | _phantom: core::marker::PhantomData, | 250 | _phantom: core::marker::PhantomData, |
| 238 | } | 251 | } |
| 239 | } | 252 | } |
| @@ -260,7 +273,7 @@ impl<'d, I: Instance> Ostimer<'d, I> { | |||
| 260 | /// # Safety | 273 | /// # Safety |
| 261 | /// This operation will reset the entire OSTIMER peripheral. Any active alarms | 274 | /// This operation will reset the entire OSTIMER peripheral. Any active alarms |
| 262 | /// or time_driver operations will be disrupted. Use with caution. | 275 | /// or time_driver operations will be disrupted. Use with caution. |
| 263 | pub fn reset(&self, peripherals: &crate::pac::Peripherals) { | 276 | pub fn reset(&self, _peripherals: &crate::pac::Peripherals) { |
| 264 | critical_section::with(|_| { | 277 | critical_section::with(|_| { |
| 265 | let r: &Regs = unsafe { &*I::ptr() }; | 278 | let r: &Regs = unsafe { &*I::ptr() }; |
| 266 | 279 | ||
| @@ -270,19 +283,17 @@ impl<'d, I: Instance> Ostimer<'d, I> { | |||
| 270 | .write(|w| w.ostimer_intrflag().clear_bit_by_one().ostimer_intena().clear_bit()); | 283 | .write(|w| w.ostimer_intrflag().clear_bit_by_one().ostimer_intena().clear_bit()); |
| 271 | 284 | ||
| 272 | unsafe { | 285 | unsafe { |
| 273 | crate::reset::assert::<crate::reset::line::Ostimer0>(peripherals); | 286 | assert_reset::<OSTIMER0>(); |
| 274 | } | ||
| 275 | 287 | ||
| 276 | for _ in 0..RESET_STABILIZE_SPINS { | 288 | for _ in 0..RESET_STABILIZE_SPINS { |
| 277 | cortex_m::asm::nop(); | 289 | cortex_m::asm::nop(); |
| 278 | } | 290 | } |
| 279 | 291 | ||
| 280 | unsafe { | 292 | release_reset::<OSTIMER0>(); |
| 281 | crate::reset::release::<crate::reset::line::Ostimer0>(peripherals); | ||
| 282 | } | ||
| 283 | 293 | ||
| 284 | while !<crate::reset::line::Ostimer0 as crate::reset::ResetLine>::is_released(&peripherals.mrcc0) { | 294 | while !is_reset_released::<OSTIMER0>() { |
| 285 | cortex_m::asm::nop(); | 295 | cortex_m::asm::nop(); |
| 296 | } | ||
| 286 | } | 297 | } |
| 287 | 298 | ||
| 288 | for _ in 0..RESET_STABILIZE_SPINS { | 299 | for _ in 0..RESET_STABILIZE_SPINS { |
| @@ -469,14 +480,13 @@ fn now_ticks_read() -> u64 { | |||
| 469 | // Read high then low to minimize incoherent snapshots | 480 | // Read high then low to minimize incoherent snapshots |
| 470 | let hi = (r.evtimerh().read().evtimer_count_value().bits() as u64) & (EVTIMER_HI_MASK as u64); | 481 | let hi = (r.evtimerh().read().evtimer_count_value().bits() as u64) & (EVTIMER_HI_MASK as u64); |
| 471 | let lo = r.evtimerl().read().evtimer_count_value().bits() as u64; | 482 | let lo = r.evtimerl().read().evtimer_count_value().bits() as u64; |
| 472 | |||
| 473 | // Combine and convert from Gray code to binary | 483 | // Combine and convert from Gray code to binary |
| 474 | let gray = lo | (hi << EVTIMER_HI_SHIFT); | 484 | let gray = lo | (hi << EVTIMER_HI_SHIFT); |
| 475 | gray_to_bin(gray) | 485 | gray_to_bin(gray) |
| 476 | } | 486 | } |
| 477 | 487 | ||
| 478 | // Instance trait like other drivers, providing a PAC pointer for this OSTIMER instance | 488 | // Instance trait like other drivers, providing a PAC pointer for this OSTIMER instance |
| 479 | pub trait Instance { | 489 | pub trait Instance: Gate<MrccPeriphConfig = OsTimerConfig> + PeripheralType { |
| 480 | fn ptr() -> *const Regs; | 490 | fn ptr() -> *const Regs; |
| 481 | } | 491 | } |
| 482 | 492 | ||
| @@ -491,12 +501,12 @@ impl Instance for crate::peripherals::OSTIMER0 { | |||
| 491 | } | 501 | } |
| 492 | 502 | ||
| 493 | // Also implement Instance for the Peri wrapper type | 503 | // Also implement Instance for the Peri wrapper type |
| 494 | impl Instance for embassy_hal_internal::Peri<'_, crate::peripherals::OSTIMER0> { | 504 | // impl Instance for embassy_hal_internal::Peri<'_, crate::peripherals::OSTIMER0> { |
| 495 | #[inline(always)] | 505 | // #[inline(always)] |
| 496 | fn ptr() -> *const Regs { | 506 | // fn ptr() -> *const Regs { |
| 497 | pac::Ostimer0::ptr() | 507 | // pac::Ostimer0::ptr() |
| 498 | } | 508 | // } |
| 499 | } | 509 | // } |
| 500 | 510 | ||
| 501 | #[inline(always)] | 511 | #[inline(always)] |
| 502 | fn bin_to_gray(x: u64) -> u64 { | 512 | 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 @@ | |||
| 1 | //! Reset control helpers built on PAC field writers. | ||
| 2 | use crate::pac; | ||
| 3 | |||
| 4 | /// Trait describing a reset line that can be asserted/deasserted. | ||
| 5 | pub trait ResetLine { | ||
| 6 | /// Drive the peripheral out of reset. | ||
| 7 | unsafe fn release(mrcc: &pac::mrcc0::RegisterBlock); | ||
| 8 | |||
| 9 | /// Drive the peripheral into reset. | ||
| 10 | unsafe fn assert(mrcc: &pac::mrcc0::RegisterBlock); | ||
| 11 | |||
| 12 | /// Check whether the peripheral is currently released. | ||
| 13 | fn is_released(mrcc: &pac::mrcc0::RegisterBlock) -> bool; | ||
| 14 | } | ||
| 15 | |||
| 16 | /// Release a reset line for the given peripheral set. | ||
| 17 | #[inline] | ||
| 18 | pub unsafe fn release<R: ResetLine>(peripherals: &pac::Peripherals) { | ||
| 19 | R::release(&peripherals.mrcc0); | ||
| 20 | } | ||
| 21 | |||
| 22 | /// Assert a reset line for the given peripheral set. | ||
| 23 | #[inline] | ||
| 24 | pub unsafe fn assert<R: ResetLine>(peripherals: &pac::Peripherals) { | ||
| 25 | R::assert(&peripherals.mrcc0); | ||
| 26 | } | ||
| 27 | |||
| 28 | /// Pulse a reset line (assert then release) with a short delay. | ||
| 29 | #[inline] | ||
| 30 | pub unsafe fn pulse<R: ResetLine>(peripherals: &pac::Peripherals) { | ||
| 31 | let mrcc = &peripherals.mrcc0; | ||
| 32 | R::assert(mrcc); | ||
| 33 | cortex_m::asm::nop(); | ||
| 34 | cortex_m::asm::nop(); | ||
| 35 | R::release(mrcc); | ||
| 36 | } | ||
| 37 | |||
| 38 | macro_rules! impl_reset_line { | ||
| 39 | ($name:ident, $reg:ident, $field:ident) => { | ||
| 40 | pub struct $name; | ||
| 41 | |||
| 42 | impl ResetLine for $name { | ||
| 43 | #[inline] | ||
| 44 | unsafe fn release(mrcc: &pac::mrcc0::RegisterBlock) { | ||
| 45 | mrcc.$reg().modify(|_, w| w.$field().enabled()); | ||
| 46 | } | ||
| 47 | |||
| 48 | #[inline] | ||
| 49 | unsafe fn assert(mrcc: &pac::mrcc0::RegisterBlock) { | ||
| 50 | mrcc.$reg().modify(|_, w| w.$field().disabled()); | ||
| 51 | } | ||
| 52 | |||
| 53 | #[inline] | ||
| 54 | fn is_released(mrcc: &pac::mrcc0::RegisterBlock) -> bool { | ||
| 55 | mrcc.$reg().read().$field().is_enabled() | ||
| 56 | } | ||
| 57 | } | ||
| 58 | }; | ||
| 59 | } | ||
| 60 | |||
| 61 | pub mod line { | ||
| 62 | use super::*; | ||
| 63 | |||
| 64 | impl_reset_line!(Port2, mrcc_glb_rst1, port2); | ||
| 65 | impl_reset_line!(Port3, mrcc_glb_rst1, port3); | ||
| 66 | impl_reset_line!(Gpio3, mrcc_glb_rst2, gpio3); | ||
| 67 | impl_reset_line!(Lpuart2, mrcc_glb_rst0, lpuart2); | ||
| 68 | impl_reset_line!(Ostimer0, mrcc_glb_rst1, ostimer0); | ||
| 69 | impl_reset_line!(Port1, mrcc_glb_rst1, port1); | ||
| 70 | impl_reset_line!(Adc1, mrcc_glb_rst1, adc1); | ||
| 71 | } | ||
| 72 | |||
| 73 | #[inline] | ||
| 74 | pub unsafe fn release_reset_port2(peripherals: &pac::Peripherals) { | ||
| 75 | release::<line::Port2>(peripherals); | ||
| 76 | } | ||
| 77 | |||
| 78 | #[inline] | ||
| 79 | pub unsafe fn release_reset_port3(peripherals: &pac::Peripherals) { | ||
| 80 | release::<line::Port3>(peripherals); | ||
| 81 | } | ||
| 82 | |||
| 83 | #[inline] | ||
| 84 | pub unsafe fn release_reset_gpio3(peripherals: &pac::Peripherals) { | ||
| 85 | release::<line::Gpio3>(peripherals); | ||
| 86 | } | ||
| 87 | |||
| 88 | #[inline] | ||
| 89 | pub unsafe fn release_reset_lpuart2(peripherals: &pac::Peripherals) { | ||
| 90 | release::<line::Lpuart2>(peripherals); | ||
| 91 | } | ||
| 92 | |||
| 93 | #[inline] | ||
| 94 | pub unsafe fn release_reset_ostimer0(peripherals: &pac::Peripherals) { | ||
| 95 | release::<line::Ostimer0>(peripherals); | ||
| 96 | } | ||
| 97 | |||
| 98 | /// Convenience shim retained for existing call sites. | ||
| 99 | #[inline] | ||
| 100 | pub unsafe fn reset_ostimer0(peripherals: &pac::Peripherals) { | ||
| 101 | pulse::<line::Ostimer0>(peripherals); | ||
| 102 | } | ||
| 103 | |||
| 104 | #[inline] | ||
| 105 | pub unsafe fn release_reset_port1(peripherals: &pac::Peripherals) { | ||
| 106 | release::<line::Port1>(peripherals); | ||
| 107 | } | ||
| 108 | |||
| 109 | #[inline] | ||
| 110 | pub unsafe fn release_reset_adc1(peripherals: &pac::Peripherals) { | ||
| 111 | release::<line::Adc1>(peripherals); | ||
| 112 | } | ||
