diff options
Diffstat (limited to 'src')
| -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 |
7 files changed, 102 insertions, 168 deletions
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 | } | ||
