aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/adc_interrupt.rs15
-rw-r--r--examples/common/mod.rs38
-rw-r--r--examples/lpuart_buffered.rs5
-rw-r--r--examples/ostimer_alarm.rs7
-rw-r--r--examples/ostimer_counter.rs8
-rw-r--r--examples/ostimer_race_test.rs5
-rw-r--r--examples/uart_interrupt.rs100
-rw-r--r--src/adc.rs73
-rw-r--r--src/clocks/mod.rs12
-rw-r--r--src/clocks/periph_helpers.rs8
-rw-r--r--src/lib.rs1
-rw-r--r--src/lpuart/mod.rs2
-rw-r--r--src/ostimer.rs62
-rw-r--r--src/reset.rs112
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
4use embassy_executor::Spawner; 4use embassy_executor::Spawner;
5use embassy_mcxa276::clocks::periph_helpers::{AdcClockSel, Div4};
6use embassy_mcxa276::clocks::PoweredClock;
5use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; 7use hal::adc::{LpadcConfig, TriggerPriorityPolicy};
6use hal::uart; 8use hal::uart;
7use mcxa_pac::adc1::cfg::{Pwrsel, Refsel}; 9use 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
4use hal::{clocks, pins, reset}; 4use hal::{clocks, pins};
5use {embassy_mcxa276 as hal, panic_probe as _}; 5use {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)]
10pub unsafe fn init_uart2(p: &mcxa_pac::Peripherals) { 10pub 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)]
21pub unsafe fn init_led(p: &mcxa_pac::Peripherals) { 19pub 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)]
29pub 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)]
38pub unsafe fn init_adc(p: &mcxa_pac::Peripherals) { 26pub 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
14bind_interrupts!(struct Irqs { 14bind_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
19unsafe extern "C" fn lpuart2_handler() { 19unsafe 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]
24async fn main(_spawner: Spawner) { 24async 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
10mod common; 10mod common;
11 11
12use embassy_mcxa276::bind_interrupts; 12use embassy_mcxa276::{bind_interrupts, clocks::{periph_helpers::OstimerClockSel, PoweredClock}};
13use {defmt_rtt as _, panic_probe as _}; 13use {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
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_mcxa276::clocks::{periph_helpers::OstimerClockSel, PoweredClock};
10use embassy_time::{Duration, Timer}; 11use embassy_time::{Duration, Timer};
11use hal::bind_interrupts; 12use hal::bind_interrupts;
12use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; 13use {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 @@
12use core::sync::atomic::{AtomicU32, Ordering}; 12use core::sync::atomic::{AtomicU32, Ordering};
13 13
14use embassy_executor::Spawner; 14use embassy_executor::Spawner;
15use embassy_mcxa276::clocks::{periph_helpers::OstimerClockSel, PoweredClock};
15use embassy_time::{Duration, Timer}; 16use embassy_time::{Duration, Timer};
16use hal::bind_interrupts; 17use hal::bind_interrupts;
17use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; 18use {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
4use embassy_executor::Spawner; 4use embassy_executor::Spawner;
5use embassy_mcxa276 as hal; 5// use embassy_mcxa276 as hal;
6use hal::interrupt::typelevel::Handler; 6// use hal::interrupt::typelevel::Handler;
7use hal::uart; 7// use hal::uart;
8 8
9mod common; 9// mod common;
10 10
11use embassy_mcxa276::bind_interrupts; 11// use embassy_mcxa276::bind_interrupts;
12use {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
15bind_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]
21static 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
24unsafe 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]
29async fn main(_spawner: Spawner) { 29async 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
2use core::sync::atomic::{AtomicBool, Ordering}; 2use core::sync::atomic::{AtomicBool, Ordering};
3 3
4use embassy_hal_internal::{Peri, PeripheralType};
5
6use crate::clocks::periph_helpers::{AdcClockSel, AdcConfig, Div4};
7use crate::clocks::{enable_and_reset, Gate, PoweredClock};
4use crate::pac; 8use crate::pac;
5use crate::pac::adc1::cfg::{HptExdi, Pwrsel, Refsel, Tcmdres, Tprictrl, Tres}; 9use crate::pac::adc1::cfg::{HptExdi, Pwrsel, Refsel, Tcmdres, Tprictrl, Tres};
6use crate::pac::adc1::cmdh1::{Avgs, Cmpen, Next, Sts}; 10use crate::pac::adc1::cmdh1::{Avgs, Cmpen, Next, Sts};
@@ -12,7 +16,7 @@ type Regs = pac::adc1::RegisterBlock;
12 16
13static INTERRUPT_TRIGGERED: AtomicBool = AtomicBool::new(false); 17static INTERRUPT_TRIGGERED: AtomicBool = AtomicBool::new(false);
14// Token-based instance pattern like embassy-imxrt 18// Token-based instance pattern like embassy-imxrt
15pub trait Instance { 19pub 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
29impl 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
72impl 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
97pub struct Adc<I: Instance> { 124pub struct Adc<'a, I: Instance> {
98 _inst: core::marker::PhantomData<I>, 125 _inst: core::marker::PhantomData<&'a mut I>,
99} 126}
100 127
101impl<I: Instance> Adc<I> { 128impl<'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]
83pub 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]
84pub unsafe fn pulse_reset<G: Gate>() { 89pub 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)]
280pub enum PoweredClock { 288pub 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 {
18pub struct Div4(pub(super) u8); 18pub struct Div4(pub(super) u8);
19 19
20impl Div4 { 20impl 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)]
84pub enum LpuartInstance { 90pub 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)]
105pub enum OstimerClockSel { 112pub 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)]
119pub enum AdcClockSel { 127pub 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 @@
6pub mod clocks; // still provide clock helpers 6pub mod clocks; // still provide clock helpers
7pub mod gpio; 7pub mod gpio;
8pub mod pins; // pin mux helpers 8pub mod pins; // pin mux helpers
9pub mod reset; // reset control helpers
10 9
11pub mod adc; 10pub mod adc;
12pub mod config; 11pub 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
30use core::sync::atomic::{AtomicBool, Ordering}; 30use core::sync::atomic::{AtomicBool, Ordering};
31 31
32use embassy_hal_internal::{Peri, PeripheralType};
33
34use crate::clocks::periph_helpers::{OsTimerConfig, OstimerClockSel};
35use crate::clocks::{assert_reset, enable_and_reset, is_reset_released, release_reset, Gate, PoweredClock};
32use crate::interrupt::InterruptExt; 36use crate::interrupt::InterruptExt;
33use crate::pac; 37use crate::pac;
38use crate::peripherals::OSTIMER0;
34 39
35// PAC defines the shared RegisterBlock under `ostimer0`. 40// PAC defines the shared RegisterBlock under `ostimer0`.
36type Regs = pac::ostimer0::RegisterBlock; 41type Regs = pac::ostimer0::RegisterBlock;
@@ -197,16 +202,16 @@ impl<'d> Alarm<'d> {
197pub struct Config { 202pub 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
204impl Default for Config { 209impl 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
479pub trait Instance { 489pub 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
494impl 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)]
502fn bin_to_gray(x: u64) -> u64 { 512fn 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.
2use crate::pac;
3
4/// Trait describing a reset line that can be asserted/deasserted.
5pub 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]
18pub 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]
24pub 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]
30pub 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
38macro_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
61pub 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]
74pub unsafe fn release_reset_port2(peripherals: &pac::Peripherals) {
75 release::<line::Port2>(peripherals);
76}
77
78#[inline]
79pub unsafe fn release_reset_port3(peripherals: &pac::Peripherals) {
80 release::<line::Port3>(peripherals);
81}
82
83#[inline]
84pub unsafe fn release_reset_gpio3(peripherals: &pac::Peripherals) {
85 release::<line::Gpio3>(peripherals);
86}
87
88#[inline]
89pub unsafe fn release_reset_lpuart2(peripherals: &pac::Peripherals) {
90 release::<line::Lpuart2>(peripherals);
91}
92
93#[inline]
94pub 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]
100pub unsafe fn reset_ostimer0(peripherals: &pac::Peripherals) {
101 pulse::<line::Ostimer0>(peripherals);
102}
103
104#[inline]
105pub unsafe fn release_reset_port1(peripherals: &pac::Peripherals) {
106 release::<line::Port1>(peripherals);
107}
108
109#[inline]
110pub unsafe fn release_reset_adc1(peripherals: &pac::Peripherals) {
111 release::<line::Adc1>(peripherals);
112}