aboutsummaryrefslogtreecommitdiff
path: root/embassy-mcxa/src
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-mcxa/src')
-rw-r--r--embassy-mcxa/src/adc.rs784
-rw-r--r--embassy-mcxa/src/clocks/mod.rs3
-rw-r--r--embassy-mcxa/src/clocks/periph_helpers.rs1
-rw-r--r--embassy-mcxa/src/i2c/controller.rs2
-rw-r--r--embassy-mcxa/src/interrupt.rs41
-rw-r--r--embassy-mcxa/src/lib.rs10
-rw-r--r--embassy-mcxa/src/lpuart/mod.rs4
-rw-r--r--embassy-mcxa/src/pins.rs33
-rw-r--r--embassy-mcxa/src/reset_reason.rs106
-rw-r--r--embassy-mcxa/src/rtc.rs78
10 files changed, 766 insertions, 296 deletions
diff --git a/embassy-mcxa/src/adc.rs b/embassy-mcxa/src/adc.rs
index 7475299ba..f88bb6b37 100644
--- a/embassy-mcxa/src/adc.rs
+++ b/embassy-mcxa/src/adc.rs
@@ -1,42 +1,23 @@
1//! ADC driver 1//! ADC driver
2use core::sync::atomic::{AtomicBool, Ordering}; 2use core::future::Future;
3use core::marker::PhantomData;
3 4
4use embassy_hal_internal::{Peri, PeripheralType}; 5use embassy_hal_internal::{Peri, PeripheralType};
6use maitake_sync::WaitCell;
7use paste::paste;
5 8
6use crate::clocks::periph_helpers::{AdcClockSel, AdcConfig, Div4}; 9use crate::clocks::periph_helpers::{AdcClockSel, AdcConfig, Div4};
7use crate::clocks::{Gate, PoweredClock, enable_and_reset}; 10use crate::clocks::{ClockError, Gate, PoweredClock, enable_and_reset};
11use crate::gpio::{GpioPin, SealedPin};
12use crate::interrupt::typelevel::{Handler, Interrupt};
8use crate::pac; 13use crate::pac;
9use crate::pac::adc1::cfg::{HptExdi, Pwrsel, Refsel, Tcmdres, Tprictrl, Tres}; 14use crate::pac::adc1::cfg::{HptExdi, Pwrsel, Refsel, Tcmdres, Tprictrl, Tres};
10use crate::pac::adc1::cmdh1::{Avgs, Cmpen, Next, Sts}; 15use crate::pac::adc1::cmdh1::{Avgs, Cmpen, Next, Sts};
11use crate::pac::adc1::cmdl1::{Adch, Ctype, Mode}; 16use crate::pac::adc1::cmdl1::Mode;
12use crate::pac::adc1::ctrl::CalAvgs; 17use crate::pac::adc1::ctrl::CalAvgs;
13use crate::pac::adc1::tctrl::{Tcmd, Tpri}; 18use crate::pac::adc1::tctrl::{Tcmd, Tpri};
14 19
15type Regs = pac::adc1::RegisterBlock; 20/// Trigger priority policy for ADC conversions.
16
17static INTERRUPT_TRIGGERED: AtomicBool = AtomicBool::new(false);
18// Token-based instance pattern like embassy-imxrt
19pub trait Instance: Gate<MrccPeriphConfig = AdcConfig> + PeripheralType {
20 fn ptr() -> *const Regs;
21}
22
23/// Token for ADC1
24pub type Adc1 = crate::peripherals::ADC1;
25impl Instance for crate::peripherals::ADC1 {
26 #[inline(always)]
27 fn ptr() -> *const Regs {
28 pac::Adc1::ptr()
29 }
30}
31
32// Also implement Instance for the Peri wrapper type
33// impl Instance for embassy_hal_internal::Peri<'_, crate::peripherals::ADC1> {
34// #[inline(always)]
35// fn ptr() -> *const Regs {
36// pac::Adc1::ptr()
37// }
38// }
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq)] 21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
41#[repr(u8)] 22#[repr(u8)]
42pub enum TriggerPriorityPolicy { 23pub enum TriggerPriorityPolicy {
@@ -52,20 +33,36 @@ pub enum TriggerPriorityPolicy {
52 TriggerPriorityExceptionDisabled = 16, 33 TriggerPriorityExceptionDisabled = 16,
53} 34}
54 35
36/// Configuration for the LPADC peripheral.
55#[derive(Debug, Clone, Copy, PartialEq, Eq)] 37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
56pub struct LpadcConfig { 38pub struct LpadcConfig {
39 /// Control system transition to Stop and Wait power modes while ADC is converting.
40 /// When enabled in Doze mode, immediate entries to Wait or Stop are allowed.
41 /// When disabled, the ADC will wait for the current averaging iteration/FIFO storage to complete before acknowledging stop or wait mode entry.
57 pub enable_in_doze_mode: bool, 42 pub enable_in_doze_mode: bool,
43 /// Auto-Calibration Averages.
58 pub conversion_average_mode: CalAvgs, 44 pub conversion_average_mode: CalAvgs,
45 /// ADC analog circuits are pre-enabled and ready to execute conversions without startup delays(at the cost of higher DC current consumption).
59 pub enable_analog_preliminary: bool, 46 pub enable_analog_preliminary: bool,
47 /// Power-up delay value (in ADC clock cycles)
60 pub power_up_delay: u8, 48 pub power_up_delay: u8,
49 /// Reference voltage source selection
61 pub reference_voltage_source: Refsel, 50 pub reference_voltage_source: Refsel,
51 /// Power configuration selection.
62 pub power_level_mode: Pwrsel, 52 pub power_level_mode: Pwrsel,
53 /// Trigger priority policy for handling multiple triggers
63 pub trigger_priority_policy: TriggerPriorityPolicy, 54 pub trigger_priority_policy: TriggerPriorityPolicy,
55 /// Enables the ADC pausing function. When enabled, a programmable delay is inserted during command execution sequencing between LOOP iterations,
56 /// between commands in a sequence, and between conversions when command is executing in "Compare Until True" configuration.
64 pub enable_conv_pause: bool, 57 pub enable_conv_pause: bool,
58 /// Controls the duration of pausing during command execution sequencing. The pause delay is a count of (convPauseDelay*4) ADCK cycles.
59 /// Only available when ADC pausing function is enabled. The available value range is in 9-bit.
65 pub conv_pause_delay: u16, 60 pub conv_pause_delay: u16,
66 pub fifo_watermark: u8, 61 /// Power configuration (normal/deep sleep behavior)
67 pub power: PoweredClock, 62 pub power: PoweredClock,
63 /// ADC clock source selection
68 pub source: AdcClockSel, 64 pub source: AdcClockSel,
65 /// Clock divider for ADC clock
69 pub div: Div4, 66 pub div: Div4,
70} 67}
71 68
@@ -81,7 +78,6 @@ impl Default for LpadcConfig {
81 trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, 78 trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed,
82 enable_conv_pause: false, 79 enable_conv_pause: false,
83 conv_pause_delay: 0, 80 conv_pause_delay: 0,
84 fifo_watermark: 0,
85 power: PoweredClock::NormalEnabledDeepSleepDisabled, 81 power: PoweredClock::NormalEnabledDeepSleepDisabled,
86 source: AdcClockSel::FroLfDiv, 82 source: AdcClockSel::FroLfDiv,
87 div: Div4::no_div(), 83 div: Div4::no_div(),
@@ -89,10 +85,11 @@ impl Default for LpadcConfig {
89 } 85 }
90} 86}
91 87
88/// Configuration for a conversion command.
89///
90/// Defines the parameters for a single ADC conversion operation.
92#[derive(Debug, Clone, Copy, PartialEq, Eq)] 91#[derive(Debug, Clone, Copy, PartialEq, Eq)]
93pub struct ConvCommandConfig { 92pub struct ConvCommandConfig {
94 pub sample_channel_mode: Ctype,
95 pub channel_number: Adch,
96 pub chained_next_command_number: Next, 93 pub chained_next_command_number: Next,
97 pub enable_auto_channel_increment: bool, 94 pub enable_auto_channel_increment: bool,
98 pub loop_count: u8, 95 pub loop_count: u8,
@@ -105,6 +102,26 @@ pub struct ConvCommandConfig {
105 pub enable_wait_trigger: bool, 102 pub enable_wait_trigger: bool,
106} 103}
107 104
105impl Default for ConvCommandConfig {
106 fn default() -> Self {
107 ConvCommandConfig {
108 chained_next_command_number: Next::NoNextCmdTerminateOnFinish,
109 enable_auto_channel_increment: false,
110 loop_count: 0,
111 hardware_average_mode: Avgs::NoAverage,
112 sample_time_mode: Sts::Sample3p5,
113 hardware_compare_mode: Cmpen::DisabledAlwaysStoreResult,
114 hardware_compare_value_high: 0,
115 hardware_compare_value_low: 0,
116 conversion_resolution_mode: Mode::Data12Bits,
117 enable_wait_trigger: false,
118 }
119 }
120}
121
122/// Configuration for a conversion trigger.
123///
124/// Defines how a trigger initiates ADC conversions.
108#[derive(Debug, Clone, Copy, PartialEq, Eq)] 125#[derive(Debug, Clone, Copy, PartialEq, Eq)]
109pub struct ConvTriggerConfig { 126pub struct ConvTriggerConfig {
110 pub target_command_id: Tcmd, 127 pub target_command_id: Tcmd,
@@ -113,32 +130,298 @@ pub struct ConvTriggerConfig {
113 pub enable_hardware_trigger: bool, 130 pub enable_hardware_trigger: bool,
114} 131}
115 132
133impl Default for ConvTriggerConfig {
134 fn default() -> Self {
135 ConvTriggerConfig {
136 target_command_id: Tcmd::NotValid,
137 delay_power: 0,
138 priority: Tpri::HighestPriority,
139 enable_hardware_trigger: false,
140 }
141 }
142}
143
144/// Shorthand for `Result<T>`.
145pub type Result<T> = core::result::Result<T, Error>;
146
147/// ADC Error types
148#[derive(Debug, Clone, Copy, PartialEq, Eq)]
149#[cfg_attr(feature = "defmt", derive(defmt::Format))]
150pub enum Error {
151 /// FIFO is empty, no conversion result available
152 FifoEmpty,
153 /// Invalid configuration
154 InvalidConfig,
155 /// Clock configuration error.
156 ClockSetup(ClockError),
157}
158
159/// Result of an ADC conversion.
160///
161/// Contains the conversion value and metadata about the conversion.
116#[derive(Debug, Clone, Copy, PartialEq, Eq)] 162#[derive(Debug, Clone, Copy, PartialEq, Eq)]
117pub struct ConvResult { 163pub struct ConvResult {
118 pub command_id_source: u32, 164 pub command_id_source: u8,
119 pub loop_count_index: u32, 165 pub loop_count_index: u8,
120 pub trigger_id_source: u32, 166 pub trigger_id_source: u8,
121 pub conv_value: u16, 167 pub conv_value: u16,
122} 168}
123 169
124pub struct Adc<'a, I: Instance> { 170/// ADC interrupt handler.
125 _inst: core::marker::PhantomData<&'a mut I>, 171pub struct InterruptHandler<I: Instance> {
172 _phantom: PhantomData<I>,
173}
174
175/// ADC driver instance.
176pub struct Adc<'a, M: ModeAdc> {
177 _inst: PhantomData<&'a mut ()>,
178 mode: M,
179
180 // The channel index of the pin used to create our ADC instance
181 channel_idx: u8,
182
183 // The register block of the ADC instance
184 info: &'static pac::adc0::RegisterBlock,
185}
186
187impl<'a> Adc<'a, Blocking> {
188 /// Create a new blocking instance of the ADC driver.
189 /// # Arguments
190 /// * `_inst` - ADC peripheral instance
191 /// * `pin` - GPIO pin to use for ADC
192 /// * `config` - ADC configuration
193 pub fn new_blocking<I: Instance>(
194 _inst: Peri<'a, I>,
195 pin: Peri<'a, impl AdcPin<I>>,
196 config: LpadcConfig,
197 ) -> Result<Self> {
198 Self::new_inner(_inst, pin, config, Blocking)
199 }
200
201 /// Enable ADC interrupts.
202 ///
203 /// Enables the interrupt sources specified in the bitmask.
204 ///
205 /// # Arguments
206 /// * `mask` - Bitmask of interrupt sources to enable
207 pub fn enable_interrupt(&mut self, mask: u32) {
208 self.info.ie().modify(|r, w| unsafe { w.bits(r.bits() | mask) });
209 }
210
211 /// Disable ADC interrupts.
212 ///
213 /// Disables the interrupt sources specified in the bitmask.
214 ///
215 /// # Arguments
216 /// * `mask` - Bitmask of interrupt sources to disable
217 pub fn disable_interrupt(&mut self, mask: u32) {
218 self.info.ie().modify(|r, w| unsafe { w.bits(r.bits() & !mask) });
219 }
220
221 pub fn set_fifo_watermark(&mut self, watermark: u8) -> Result<()> {
222 if watermark > 0b111 {
223 return Err(Error::InvalidConfig);
224 }
225 self.info.fctrl0().modify(|_r, w| unsafe { w.fwmark().bits(watermark) });
226 Ok(())
227 }
228
229 /// Trigger ADC conversion(s) via software.
230 ///
231 /// Initiates conversion(s) for the trigger(s) specified in the bitmask.
232 /// Each bit in the mask corresponds to a trigger ID (bit 0 = trigger 0, etc.).
233 ///
234 /// # Arguments
235 /// * `trigger_id_mask` - Bitmask of trigger IDs to activate (bit N = trigger N)
236 ///
237 /// # Returns
238 /// * `Ok(())` if the triger mask was valid
239 /// * `Err(Error::InvalidConfig)` if the mask was greater than `0b1111`
240 pub fn do_software_trigger(&self, trigger_id_mask: u8) -> Result<()> {
241 if trigger_id_mask > 0b1111 {
242 return Err(Error::InvalidConfig);
243 }
244 self.info.swtrig().write(|w| unsafe { w.bits(trigger_id_mask as u32) });
245 Ok(())
246 }
247
248 /// Set conversion command configuration.
249 ///
250 /// Configures a conversion command slot with the specified parameters.
251 /// Commands define how conversions are performed (channel, resolution, etc.).
252 ///
253 /// # Arguments
254 /// * `index` - Command index (Must be in range 1..=7)
255 /// * `config` - Command configuration
256 ///
257 /// # Returns
258 /// * `Ok(())` if the command was configured successfully
259 /// * `Err(Error::InvalidConfig)` if the index is out of range
260 pub fn set_conv_command_config(&self, index: usize, config: &ConvCommandConfig) -> Result<()> {
261 self.set_conv_command_config_inner(index, config)
262 }
263
264 /// Set conversion trigger configuration.
265 ///
266 /// Configures a trigger to initiate conversions. Triggers can be
267 /// activated by software or hardware signals.
268 ///
269 /// # Arguments
270 /// * `trigger_id` - Trigger index (0..=3)
271 /// * `config` - Trigger configuration
272 pub fn set_conv_trigger_config(&self, trigger_id: usize, config: &ConvTriggerConfig) -> Result<()> {
273 self.set_conv_trigger_config_inner(trigger_id, config)
274 }
275
276 /// Reset the FIFO buffer.
277 ///
278 /// Clears all pending conversion results from the FIFO.
279 pub fn do_reset_fifo(&self) {
280 self.info.ctrl().modify(|_, w| w.rstfifo0().trigger_reset());
281 }
282
283 /// Get conversion result from FIFO.
284 ///
285 /// Reads and returns the next conversion result from the FIFO.
286 /// Returns `None` if the FIFO is empty.
287 ///
288 /// # Returns
289 /// - `Some(ConvResult)` if a result is available
290 /// - `Err(Error::FifoEmpty)` if the FIFO is empty
291 pub fn get_conv_result(&self) -> Result<ConvResult> {
292 self.get_conv_result_inner()
293 }
126} 294}
127 295
128impl<'a, I: Instance> Adc<'a, I> { 296impl<'a> Adc<'a, Async> {
129 /// initialize ADC 297 /// Initialize ADC with interrupt support.
130 pub fn new(_inst: Peri<'a, I>, config: LpadcConfig) -> Self { 298 ///
131 let adc = unsafe { &*I::ptr() }; 299 /// # Arguments
300 /// * `_inst` - ADC peripheral instance
301 /// * `pin` - GPIO pin to use for ADC
302 /// * `_irq` - Interrupt binding for this ADC instance
303 /// * `config` - ADC configuration
304 pub fn new_async<I: Instance>(
305 _inst: Peri<'a, I>,
306 pin: Peri<'a, impl AdcPin<I>>,
307 _irq: impl crate::interrupt::typelevel::Binding<I::Interrupt, InterruptHandler<I>> + 'a,
308 config: LpadcConfig,
309 ) -> Result<Self> {
310 let adc = Self::new_inner(_inst, pin, config, Async { waiter: I::wait_cell() })?;
311
312 I::Interrupt::unpend();
313 unsafe { I::Interrupt::enable() };
314
315 let cfg = ConvCommandConfig {
316 chained_next_command_number: Next::NoNextCmdTerminateOnFinish,
317 enable_auto_channel_increment: false,
318 loop_count: 0,
319 hardware_average_mode: Avgs::NoAverage,
320 sample_time_mode: Sts::Sample3p5,
321 hardware_compare_mode: Cmpen::DisabledAlwaysStoreResult,
322 hardware_compare_value_high: 0,
323 hardware_compare_value_low: 0,
324 conversion_resolution_mode: Mode::Data16Bits,
325 enable_wait_trigger: false,
326 };
327
328 // We always use command 1, so this cannot fail
329 _ = adc.set_conv_command_config_inner(1, &cfg);
330
331 let cfg = ConvTriggerConfig {
332 target_command_id: Tcmd::ExecuteCmd1,
333 delay_power: 0,
334 priority: Tpri::HighestPriority,
335 enable_hardware_trigger: false,
336 };
337
338 // We always use trigger 0, so this cannot fail
339 _ = adc.set_conv_trigger_config_inner(0, &cfg);
340
341 // We always set the watermark to 0 (trigger when 1 is available)
342 I::ptr().fctrl0().modify(|_r, w| unsafe { w.fwmark().bits(0) });
343
344 Ok(adc)
345 }
346
347 /// Set the number of averages
348 pub fn set_averages(&mut self, avgs: Avgs) {
349 // TODO: we should probably return a result or wait for idle?
350 // "A write to a CMD buffer while that CMD buffer is controlling the ADC operation may cause unpredictable behavior."
351 self.info.cmdh1().modify(|_r, w| w.avgs().variant(avgs));
352 }
132 353
133 let _clock_freq = unsafe { 354 /// Set the sample time
355 pub fn set_sample_time(&mut self, st: Sts) {
356 // TODO: we should probably return a result or wait for idle?
357 // "A write to a CMD buffer while that CMD buffer is controlling the ADC operation may cause unpredictable behavior."
358 self.info.cmdh1().modify(|_r, w| w.sts().variant(st));
359 }
360
361 pub fn set_resolution(&mut self, mode: Mode) {
362 // TODO: we should probably return a result or wait for idle?
363 // "A write to a CMD buffer while that CMD buffer is controlling the ADC operation may cause unpredictable behavior."
364 self.info.cmdl1().modify(|_r, w| w.mode().variant(mode));
365 }
366
367 fn wait_idle(&mut self) -> impl Future<Output = core::result::Result<(), maitake_sync::Closed>> + use<'_> {
368 self.mode
369 .waiter
370 .wait_for(|| self.info.ie().read().fwmie0().bit_is_clear())
371 }
372
373 /// Read ADC value asynchronously.
374 ///
375 /// Performs a single ADC conversion and returns the result when the ADC interrupt is triggered.
376 ///
377 /// The function:
378 /// 1. Enables the FIFO watermark interrupt
379 /// 2. Triggers a software conversion on trigger 0
380 /// 3. Waits for the conversion to complete
381 /// 4. Returns the conversion result
382 ///
383 /// # Returns
384 /// 16-bit ADC conversion value
385 pub async fn read(&mut self) -> Result<u16> {
386 // If we cancelled a previous read, we might still be busy, wait
387 // until the interrupt is cleared (done by the interrupt)
388 _ = self.wait_idle().await;
389
390 // Clear the fifo
391 self.info.ctrl().modify(|_, w| w.rstfifo0().trigger_reset());
392
393 // Trigger a new conversion
394 self.info.ie().modify(|_r, w| w.fwmie0().set_bit());
395 self.info.swtrig().write(|w| w.swt0().set_bit());
396
397 // Wait for completion
398 _ = self.wait_idle().await;
399
400 self.get_conv_result_inner().map(|r| r.conv_value)
401 }
402}
403
404impl<'a, M: ModeAdc> Adc<'a, M> {
405 /// Internal initialization function shared by `new_async` and `new_blocking`.
406 fn new_inner<I: Instance, P: AdcPin<I>>(
407 _inst: Peri<'a, I>,
408 pin: Peri<'a, P>,
409 config: LpadcConfig,
410 mode: M,
411 ) -> Result<Self> {
412 let adc = I::ptr();
413
414 _ = unsafe {
134 enable_and_reset::<I>(&AdcConfig { 415 enable_and_reset::<I>(&AdcConfig {
135 power: config.power, 416 power: config.power,
136 source: config.source, 417 source: config.source,
137 div: config.div, 418 div: config.div,
138 }) 419 })
139 .expect("Adc Init should not fail") 420 .map_err(Error::ClockSetup)?
140 }; 421 };
141 422
423 pin.mux();
424
142 /* Reset the module. */ 425 /* Reset the module. */
143 adc.ctrl().modify(|_, w| w.rst().held_in_reset()); 426 adc.ctrl().modify(|_, w| w.rst().held_in_reset());
144 adc.ctrl().modify(|_, w| w.rst().released_from_reset()); 427 adc.ctrl().modify(|_, w| w.rst().released_from_reset());
@@ -149,22 +432,14 @@ impl<'a, I: Instance> Adc<'a, I> {
149 adc.ctrl().modify(|_, w| w.adcen().disabled()); 432 adc.ctrl().modify(|_, w| w.adcen().disabled());
150 433
151 /* Configure the module generally. */ 434 /* Configure the module generally. */
152 if config.enable_in_doze_mode { 435 adc.ctrl().modify(|_, w| w.dozen().bit(config.enable_in_doze_mode));
153 adc.ctrl().modify(|_, w| w.dozen().enabled());
154 } else {
155 adc.ctrl().modify(|_, w| w.dozen().disabled());
156 }
157 436
158 /* Set calibration average mode. */ 437 /* Set calibration average mode. */
159 adc.ctrl() 438 adc.ctrl()
160 .modify(|_, w| w.cal_avgs().variant(config.conversion_average_mode)); 439 .modify(|_, w| w.cal_avgs().variant(config.conversion_average_mode));
161 440
162 adc.cfg().write(|w| unsafe { 441 adc.cfg().write(|w| unsafe {
163 let w = if config.enable_analog_preliminary { 442 w.pwren().bit(config.enable_analog_preliminary);
164 w.pwren().pre_enabled()
165 } else {
166 w
167 };
168 443
169 w.pudly() 444 w.pudly()
170 .bits(config.power_up_delay) 445 .bits(config.power_up_delay)
@@ -214,32 +489,38 @@ impl<'a, I: Instance> Adc<'a, I> {
214 adc.pause().write(|w| unsafe { w.bits(0) }); 489 adc.pause().write(|w| unsafe { w.bits(0) });
215 } 490 }
216 491
217 adc.fctrl0() 492 adc.fctrl0().write(|w| unsafe { w.fwmark().bits(0) });
218 .write(|w| unsafe { w.fwmark().bits(config.fifo_watermark) });
219 493
220 // Enable ADC 494 // Enable ADC
221 adc.ctrl().modify(|_, w| w.adcen().enabled()); 495 adc.ctrl().modify(|_, w| w.adcen().enabled());
222 496
223 Self { 497 Ok(Self {
224 _inst: core::marker::PhantomData, 498 _inst: PhantomData,
225 } 499 mode,
226 } 500 channel_idx: P::CHANNEL,
227 501 info: adc,
228 pub fn deinit(&self) { 502 })
229 let adc = unsafe { &*I::ptr() };
230 adc.ctrl().modify(|_, w| w.adcen().disabled());
231 } 503 }
232 504
505 /// Perform offset calibration.
506 /// Waits for calibration to complete before returning.
233 pub fn do_offset_calibration(&self) { 507 pub fn do_offset_calibration(&self) {
234 let adc = unsafe { &*I::ptr() };
235 // Enable calibration mode 508 // Enable calibration mode
236 adc.ctrl() 509 self.info
510 .ctrl()
237 .modify(|_, w| w.calofs().offset_calibration_request_pending()); 511 .modify(|_, w| w.calofs().offset_calibration_request_pending());
238 512
239 // Wait for calibration to complete (polling status register) 513 // Wait for calibration to complete (polling status register)
240 while adc.stat().read().cal_rdy().is_not_set() {} 514 while self.info.stat().read().cal_rdy().is_not_set() {}
241 } 515 }
242 516
517 /// Calculate gain conversion result from gain adjustment factor.
518 ///
519 /// # Arguments
520 /// * `gain_adjustment` - Gain adjustment factor
521 ///
522 /// # Returns
523 /// Gain calibration register value
243 pub fn get_gain_conv_result(&self, mut gain_adjustment: f32) -> u32 { 524 pub fn get_gain_conv_result(&self, mut gain_adjustment: f32) -> u32 {
244 let mut gcra_array = [0u32; 17]; 525 let mut gcra_array = [0u32; 17];
245 let mut gcalr: u32 = 0; 526 let mut gcalr: u32 = 0;
@@ -258,102 +539,80 @@ impl<'a, I: Instance> Adc<'a, I> {
258 gcalr 539 gcalr
259 } 540 }
260 541
542 /// Perform automatic gain calibration.
261 pub fn do_auto_calibration(&self) { 543 pub fn do_auto_calibration(&self) {
262 let adc = unsafe { &*I::ptr() }; 544 self.info
263 adc.ctrl().modify(|_, w| w.cal_req().calibration_request_pending()); 545 .ctrl()
546 .modify(|_, w| w.cal_req().calibration_request_pending());
264 547
265 while adc.gcc0().read().rdy().is_gain_cal_not_valid() {} 548 while self.info.gcc0().read().rdy().is_gain_cal_not_valid() {}
266 549
267 let mut gcca = adc.gcc0().read().gain_cal().bits() as u32; 550 let mut gcca = self.info.gcc0().read().gain_cal().bits() as u32;
268 if gcca & ((0xFFFF + 1) >> 1) != 0 { 551 if gcca & 0x8000 != 0 {
269 gcca |= !0xFFFF; 552 gcca |= !0xFFFF;
270 } 553 }
271 554
272 let gcra = 131072.0 / (131072.0 - gcca as f32); 555 let gcra = 131072.0 / (131072.0 - gcca as f32);
273 556
274 // Write to GCR0 557 // Write to GCR0
275 adc.gcr0().write(|w| unsafe { w.bits(self.get_gain_conv_result(gcra)) }); 558 self.info
559 .gcr0()
560 .write(|w| unsafe { w.bits(self.get_gain_conv_result(gcra)) });
276 561
277 adc.gcr0().modify(|_, w| w.rdy().set_bit()); 562 self.info.gcr0().modify(|_, w| w.rdy().set_bit());
278 563
279 // Wait for calibration to complete (polling status register) 564 // Wait for calibration to complete (polling status register)
280 while adc.stat().read().cal_rdy().is_not_set() {} 565 while self.info.stat().read().cal_rdy().is_not_set() {}
281 } 566 }
282 567
283 pub fn do_software_trigger(&self, trigger_id_mask: u32) { 568 fn set_conv_command_config_inner(&self, index: usize, config: &ConvCommandConfig) -> Result<()> {
284 let adc = unsafe { &*I::ptr() }; 569 let (cmdl, cmdh) = match index {
285 adc.swtrig().write(|w| unsafe { w.bits(trigger_id_mask) }); 570 1 => (self.info.cmdl1(), self.info.cmdh1()),
286 } 571 2 => (self.info.cmdl2(), self.info.cmdh2()),
572 3 => (self.info.cmdl3(), self.info.cmdh3()),
573 4 => (self.info.cmdl4(), self.info.cmdh4()),
574 5 => (self.info.cmdl5(), self.info.cmdh5()),
575 6 => (self.info.cmdl6(), self.info.cmdh6()),
576 7 => (self.info.cmdl7(), self.info.cmdh7()),
577 _ => return Err(Error::InvalidConfig),
578 };
287 579
288 pub fn get_default_conv_command_config(&self) -> ConvCommandConfig { 580 cmdl.write(|w| {
289 ConvCommandConfig { 581 unsafe {
290 sample_channel_mode: Ctype::SingleEndedASideChannel, 582 w.adch().bits(self.channel_idx);
291 channel_number: Adch::SelectCh0, 583 }
292 chained_next_command_number: Next::NoNextCmdTerminateOnFinish, 584 w.mode().variant(config.conversion_resolution_mode)
293 enable_auto_channel_increment: false, 585 });
294 loop_count: 0,
295 hardware_average_mode: Avgs::NoAverage,
296 sample_time_mode: Sts::Sample3p5,
297 hardware_compare_mode: Cmpen::DisabledAlwaysStoreResult,
298 hardware_compare_value_high: 0,
299 hardware_compare_value_low: 0,
300 conversion_resolution_mode: Mode::Data12Bits,
301 enable_wait_trigger: false,
302 }
303 }
304 586
305 //TBD Need to add cmdlx and cmdhx with x {2..7} 587 cmdh.write(|w| {
306 pub fn set_conv_command_config(&self, index: u32, config: &ConvCommandConfig) { 588 w.next().variant(config.chained_next_command_number);
307 let adc = unsafe { &*I::ptr() }; 589 unsafe {
308 590 w.loop_().bits(config.loop_count);
309 match index {
310 1 => {
311 adc.cmdl1().write(|w| {
312 w.adch()
313 .variant(config.channel_number)
314 .mode()
315 .variant(config.conversion_resolution_mode)
316 });
317 adc.cmdh1().write(|w| unsafe {
318 w.next()
319 .variant(config.chained_next_command_number)
320 .loop_()
321 .bits(config.loop_count)
322 .avgs()
323 .variant(config.hardware_average_mode)
324 .sts()
325 .variant(config.sample_time_mode)
326 .cmpen()
327 .variant(config.hardware_compare_mode);
328 if config.enable_wait_trigger {
329 w.wait_trig().enabled();
330 }
331 if config.enable_auto_channel_increment {
332 w.lwi().enabled();
333 }
334 w
335 });
336 } 591 }
337 _ => panic!("Invalid command index: must be between 1 and 7"), 592 w.avgs().variant(config.hardware_average_mode);
338 } 593 w.sts().variant(config.sample_time_mode);
594 w.cmpen().variant(config.hardware_compare_mode);
595 w.wait_trig().bit(config.enable_wait_trigger);
596 w.lwi().bit(config.enable_auto_channel_increment);
597 w
598 });
599
600 Ok(())
339 } 601 }
340 602
341 pub fn get_default_conv_trigger_config(&self) -> ConvTriggerConfig { 603 fn set_conv_trigger_config_inner(&self, trigger_id: usize, config: &ConvTriggerConfig) -> Result<()> {
342 ConvTriggerConfig { 604 // 0..4 are valid
343 target_command_id: Tcmd::NotValid, 605 if trigger_id >= 4 {
344 delay_power: 0, 606 return Err(Error::InvalidConfig);
345 priority: Tpri::HighestPriority,
346 enable_hardware_trigger: false,
347 } 607 }
348 }
349 608
350 pub fn set_conv_trigger_config(&self, trigger_id: usize, config: &ConvTriggerConfig) { 609 let tctrl = &self.info.tctrl(trigger_id);
351 let adc = unsafe { &*I::ptr() };
352 let tctrl = &adc.tctrl(trigger_id);
353 610
354 tctrl.write(|w| unsafe { 611 tctrl.write(|w| {
355 let w = w.tcmd().variant(config.target_command_id); 612 w.tcmd().variant(config.target_command_id);
356 let w = w.tdly().bits(config.delay_power); 613 unsafe {
614 w.tdly().bits(config.delay_power);
615 }
357 w.tpri().variant(config.priority); 616 w.tpri().variant(config.priority);
358 if config.enable_hardware_trigger { 617 if config.enable_hardware_trigger {
359 w.hten().enabled() 618 w.hten().enabled()
@@ -361,49 +620,230 @@ impl<'a, I: Instance> Adc<'a, I> {
361 w 620 w
362 } 621 }
363 }); 622 });
364 }
365 623
366 pub fn do_reset_fifo(&self) { 624 Ok(())
367 let adc = unsafe { &*I::ptr() };
368 adc.ctrl().modify(|_, w| w.rstfifo0().trigger_reset());
369 } 625 }
370 626
371 pub fn enable_interrupt(&self, mask: u32) { 627 /// Get conversion result from FIFO.
372 let adc = unsafe { &*I::ptr() }; 628 ///
373 adc.ie().modify(|r, w| unsafe { w.bits(r.bits() | mask) }); 629 /// Reads and returns the next conversion result from the FIFO.
374 INTERRUPT_TRIGGERED.store(false, Ordering::SeqCst); 630 /// Returns `None` if the FIFO is empty.
375 } 631 ///
632 /// # Returns
633 /// - `Some(ConvResult)` if a result is available
634 /// - `Err(Error::FifoEmpty)` if the FIFO is empty
635 fn get_conv_result_inner(&self) -> Result<ConvResult> {
636 let fifo = self.info.resfifo0().read();
637 if !fifo.valid().is_valid() {
638 return Err(Error::FifoEmpty);
639 }
376 640
377 pub fn is_interrupt_triggered(&self) -> bool { 641 Ok(ConvResult {
378 INTERRUPT_TRIGGERED.load(Ordering::Relaxed) 642 command_id_source: fifo.cmdsrc().bits(),
643 loop_count_index: fifo.loopcnt().bits(),
644 trigger_id_source: fifo.tsrc().bits(),
645 conv_value: fifo.d().bits(),
646 })
379 } 647 }
380} 648}
381 649
382pub fn get_conv_result() -> Option<ConvResult> { 650impl<T: Instance> Handler<T::Interrupt> for InterruptHandler<T> {
383 let adc = unsafe { &*pac::Adc1::ptr() }; 651 unsafe fn on_interrupt() {
384 let fifo = adc.resfifo0().read().bits(); 652 T::ptr().ie().modify(|_r, w| w.fwmie0().clear_bit());
385 const VALID_MASK: u32 = 1 << 31; 653 T::wait_cell().wake();
386 if fifo & VALID_MASK == 0 {
387 return None;
388 } 654 }
655}
389 656
390 Some(ConvResult { 657mod sealed {
391 command_id_source: (fifo >> 24) & 0x0F, 658 /// Seal a trait
392 loop_count_index: (fifo >> 20) & 0x0F, 659 pub trait Sealed {}
393 trigger_id_source: (fifo >> 16) & 0x0F,
394 conv_value: (fifo & 0xFFFF) as u16,
395 })
396} 660}
397 661
398pub fn on_interrupt() { 662impl<I: GpioPin> sealed::Sealed for I {}
399 if get_conv_result().is_some() { 663
400 INTERRUPT_TRIGGERED.store(true, Ordering::SeqCst); 664trait SealedInstance {
401 } 665 fn ptr() -> &'static pac::adc0::RegisterBlock;
666 fn wait_cell() -> &'static WaitCell;
402} 667}
403 668
404pub struct AdcHandler; 669/// ADC Instance
405impl crate::interrupt::typelevel::Handler<crate::interrupt::typelevel::ADC1> for AdcHandler { 670#[allow(private_bounds)]
406 unsafe fn on_interrupt() { 671pub trait Instance: SealedInstance + PeripheralType + Gate<MrccPeriphConfig = AdcConfig> {
407 on_interrupt(); 672 /// Interrupt for this ADC instance.
408 } 673 type Interrupt: Interrupt;
409} 674}
675
676macro_rules! impl_instance {
677 ($($n:expr),*) => {
678 $(
679 paste!{
680 impl SealedInstance for crate::peripherals::[<ADC $n>] {
681 fn ptr() -> &'static pac::adc0::RegisterBlock {
682 unsafe { &*pac::[<Adc $n>]::ptr() }
683 }
684
685 fn wait_cell() -> &'static WaitCell {
686 static WAIT_CELL: WaitCell = WaitCell::new();
687 &WAIT_CELL
688 }
689
690 }
691
692 impl Instance for crate::peripherals::[<ADC $n>] {
693 type Interrupt = crate::interrupt::typelevel::[<ADC $n>];
694 }
695 }
696 )*
697 };
698}
699
700impl_instance!(0, 1, 2, 3);
701
702pub trait AdcPin<Instance>: GpioPin + sealed::Sealed + PeripheralType {
703 const CHANNEL: u8;
704
705 /// Set the given pin to the correct muxing state
706 fn mux(&self);
707}
708
709/// Driver mode.
710#[allow(private_bounds)]
711pub trait ModeAdc: sealed::Sealed {}
712
713/// Blocking mode.
714pub struct Blocking;
715impl sealed::Sealed for Blocking {}
716impl ModeAdc for Blocking {}
717
718/// Async mode.
719pub struct Async {
720 waiter: &'static WaitCell,
721}
722impl sealed::Sealed for Async {}
723impl ModeAdc for Async {}
724
725macro_rules! impl_pin {
726 ($pin:ident, $peri:ident, $func:ident, $channel:literal) => {
727 impl AdcPin<crate::peripherals::$peri> for crate::peripherals::$pin {
728 const CHANNEL: u8 = $channel;
729
730 fn mux(&self) {
731 self.set_pull(crate::gpio::Pull::Disabled);
732 self.set_slew_rate(crate::gpio::SlewRate::Fast.into());
733 self.set_drive_strength(crate::gpio::DriveStrength::Normal.into());
734 self.set_function(crate::pac::port0::pcr0::Mux::$func);
735 }
736 }
737 };
738}
739
740impl_pin!(P2_0, ADC0, Mux0, 0);
741impl_pin!(P2_4, ADC0, Mux0, 1);
742impl_pin!(P2_15, ADC0, Mux0, 2);
743impl_pin!(P2_3, ADC0, Mux0, 3);
744impl_pin!(P2_2, ADC0, Mux0, 4);
745impl_pin!(P2_12, ADC0, Mux0, 5);
746impl_pin!(P2_16, ADC0, Mux0, 6);
747impl_pin!(P2_7, ADC0, Mux0, 7);
748impl_pin!(P0_18, ADC0, Mux0, 8);
749impl_pin!(P0_19, ADC0, Mux0, 9);
750impl_pin!(P0_20, ADC0, Mux0, 10);
751impl_pin!(P0_21, ADC0, Mux0, 11);
752impl_pin!(P0_22, ADC0, Mux0, 12);
753impl_pin!(P0_23, ADC0, Mux0, 13);
754impl_pin!(P0_3, ADC0, Mux0, 14);
755impl_pin!(P0_6, ADC0, Mux0, 15);
756impl_pin!(P1_0, ADC0, Mux0, 16);
757impl_pin!(P1_1, ADC0, Mux0, 17);
758impl_pin!(P1_2, ADC0, Mux0, 18);
759impl_pin!(P1_3, ADC0, Mux0, 19);
760impl_pin!(P1_4, ADC0, Mux0, 20);
761impl_pin!(P1_5, ADC0, Mux0, 21);
762impl_pin!(P1_6, ADC0, Mux0, 22);
763impl_pin!(P1_7, ADC0, Mux0, 23);
764
765// ???
766// impl_pin!(P1_10, ADC0, Mux0, 255);
767
768impl_pin!(P2_1, ADC1, Mux0, 0);
769impl_pin!(P2_5, ADC1, Mux0, 1);
770impl_pin!(P2_19, ADC1, Mux0, 2);
771impl_pin!(P2_6, ADC1, Mux0, 3);
772impl_pin!(P2_3, ADC1, Mux0, 4);
773impl_pin!(P2_13, ADC1, Mux0, 5);
774impl_pin!(P2_17, ADC1, Mux0, 6);
775impl_pin!(P2_7, ADC1, Mux0, 7);
776impl_pin!(P1_10, ADC1, Mux0, 8);
777impl_pin!(P1_11, ADC1, Mux0, 9);
778impl_pin!(P1_12, ADC1, Mux0, 10);
779impl_pin!(P1_13, ADC1, Mux0, 11);
780impl_pin!(P1_14, ADC1, Mux0, 12);
781impl_pin!(P1_15, ADC1, Mux0, 13);
782// ???
783// impl_pin!(P1_16, ADC1, Mux0, 255);
784// impl_pin!(P1_17, ADC1, Mux0, 255);
785// impl_pin!(P1_18, ADC1, Mux0, 255);
786// impl_pin!(P1_19, ADC1, Mux0, 255);
787// ???
788impl_pin!(P3_31, ADC1, Mux0, 20);
789impl_pin!(P3_30, ADC1, Mux0, 21);
790impl_pin!(P3_29, ADC1, Mux0, 22);
791
792impl_pin!(P2_4, ADC2, Mux0, 0);
793impl_pin!(P2_10, ADC2, Mux0, 1);
794impl_pin!(P4_4, ADC2, Mux0, 2);
795// impl_pin!(P2_24, ADC2, Mux0, 255); ???
796impl_pin!(P2_16, ADC2, Mux0, 4);
797impl_pin!(P2_12, ADC2, Mux0, 5);
798impl_pin!(P2_20, ADC2, Mux0, 6);
799impl_pin!(P2_7, ADC2, Mux0, 7);
800impl_pin!(P0_2, ADC2, Mux0, 8);
801// ???
802// impl_pin!(P0_4, ADC2, Mux0, 255);
803// impl_pin!(P0_5, ADC2, Mux0, 255);
804// impl_pin!(P0_6, ADC2, Mux0, 255);
805// impl_pin!(P0_7, ADC2, Mux0, 255);
806// impl_pin!(P0_12, ADC2, Mux0, 255);
807// impl_pin!(P0_13, ADC2, Mux0, 255);
808// ???
809impl_pin!(P0_14, ADC2, Mux0, 14);
810impl_pin!(P0_15, ADC2, Mux0, 15);
811// ???
812// impl_pin!(P4_0, ADC2, Mux0, 255);
813// impl_pin!(P4_1, ADC2, Mux0, 255);
814// ???
815impl_pin!(P4_2, ADC2, Mux0, 18);
816impl_pin!(P4_3, ADC2, Mux0, 19);
817//impl_pin!(P4_4, ADC2, Mux0, 20); // Conflit with ADC2_A3 and ADC2_A20 using the same pin
818impl_pin!(P4_5, ADC2, Mux0, 21);
819impl_pin!(P4_6, ADC2, Mux0, 22);
820impl_pin!(P4_7, ADC2, Mux0, 23);
821
822impl_pin!(P2_5, ADC3, Mux0, 0);
823impl_pin!(P2_11, ADC3, Mux0, 1);
824impl_pin!(P2_23, ADC3, Mux0, 2);
825// impl_pin!(P2_25, ADC3, Mux0, 255); // ???
826impl_pin!(P2_17, ADC3, Mux0, 4);
827impl_pin!(P2_13, ADC3, Mux0, 5);
828impl_pin!(P2_21, ADC3, Mux0, 6);
829impl_pin!(P2_7, ADC3, Mux0, 7);
830// ???
831// impl_pin!(P3_2, ADC3, Mux0, 255);
832// impl_pin!(P3_3, ADC3, Mux0, 255);
833// impl_pin!(P3_4, ADC3, Mux0, 255);
834// impl_pin!(P3_5, ADC3, Mux0, 255);
835// ???
836impl_pin!(P3_6, ADC3, Mux0, 12);
837impl_pin!(P3_7, ADC3, Mux0, 13);
838impl_pin!(P3_12, ADC3, Mux0, 14);
839impl_pin!(P3_13, ADC3, Mux0, 15);
840impl_pin!(P3_14, ADC3, Mux0, 16);
841impl_pin!(P3_15, ADC3, Mux0, 17);
842impl_pin!(P3_20, ADC3, Mux0, 18);
843impl_pin!(P3_21, ADC3, Mux0, 19);
844impl_pin!(P3_22, ADC3, Mux0, 20);
845// ???
846// impl_pin!(P3_23, ADC3, Mux0, 255);
847// impl_pin!(P3_24, ADC3, Mux0, 255);
848// impl_pin!(P3_25, ADC3, Mux0, 255);
849// ???
diff --git a/embassy-mcxa/src/clocks/mod.rs b/embassy-mcxa/src/clocks/mod.rs
index 9288f5dc1..b96d9612a 100644
--- a/embassy-mcxa/src/clocks/mod.rs
+++ b/embassy-mcxa/src/clocks/mod.rs
@@ -945,7 +945,10 @@ pub(crate) mod gate {
945 impl_cc_gate!(LPUART3, mrcc_glb_cc0, mrcc_glb_rst0, lpuart3, LpuartConfig); 945 impl_cc_gate!(LPUART3, mrcc_glb_cc0, mrcc_glb_rst0, lpuart3, LpuartConfig);
946 impl_cc_gate!(LPUART4, mrcc_glb_cc0, mrcc_glb_rst0, lpuart4, LpuartConfig); 946 impl_cc_gate!(LPUART4, mrcc_glb_cc0, mrcc_glb_rst0, lpuart4, LpuartConfig);
947 impl_cc_gate!(LPUART5, mrcc_glb_cc1, mrcc_glb_rst1, lpuart5, LpuartConfig); 947 impl_cc_gate!(LPUART5, mrcc_glb_cc1, mrcc_glb_rst1, lpuart5, LpuartConfig);
948 impl_cc_gate!(ADC0, mrcc_glb_cc1, mrcc_glb_rst1, adc0, AdcConfig);
948 impl_cc_gate!(ADC1, mrcc_glb_cc1, mrcc_glb_rst1, adc1, AdcConfig); 949 impl_cc_gate!(ADC1, mrcc_glb_cc1, mrcc_glb_rst1, adc1, AdcConfig);
950 impl_cc_gate!(ADC2, mrcc_glb_cc1, mrcc_glb_rst1, adc2, AdcConfig);
951 impl_cc_gate!(ADC3, mrcc_glb_cc1, mrcc_glb_rst1, adc3, AdcConfig);
949 952
950 // DMA0 peripheral - uses NoConfig since it has no selectable clock source 953 // DMA0 peripheral - uses NoConfig since it has no selectable clock source
951 impl_cc_gate!(DMA0, mrcc_glb_cc0, mrcc_glb_rst0, dma0, NoConfig); 954 impl_cc_gate!(DMA0, mrcc_glb_cc0, mrcc_glb_rst0, dma0, NoConfig);
diff --git a/embassy-mcxa/src/clocks/periph_helpers.rs b/embassy-mcxa/src/clocks/periph_helpers.rs
index fed5e558e..f2f51c60c 100644
--- a/embassy-mcxa/src/clocks/periph_helpers.rs
+++ b/embassy-mcxa/src/clocks/periph_helpers.rs
@@ -427,6 +427,7 @@ impl SPConfHelper for OsTimerConfig {
427 427
428/// Selectable clocks for the ADC peripheral 428/// Selectable clocks for the ADC peripheral
429#[derive(Copy, Clone, Debug, PartialEq, Eq)] 429#[derive(Copy, Clone, Debug, PartialEq, Eq)]
430#[cfg_attr(feature = "defmt", derive(defmt::Format))]
430pub enum AdcClockSel { 431pub enum AdcClockSel {
431 /// Divided `fro_lf`/`clk_12m`/FRO12M source 432 /// Divided `fro_lf`/`clk_12m`/FRO12M source
432 FroLfDiv, 433 FroLfDiv,
diff --git a/embassy-mcxa/src/i2c/controller.rs b/embassy-mcxa/src/i2c/controller.rs
index c27d508b0..62789f85f 100644
--- a/embassy-mcxa/src/i2c/controller.rs
+++ b/embassy-mcxa/src/i2c/controller.rs
@@ -8,9 +8,9 @@ use embassy_hal_internal::drop::OnDrop;
8use mcxa_pac::lpi2c0::mtdr::Cmd; 8use mcxa_pac::lpi2c0::mtdr::Cmd;
9 9
10use super::{Async, Blocking, Error, Instance, InterruptHandler, Mode, Result, SclPin, SdaPin}; 10use super::{Async, Blocking, Error, Instance, InterruptHandler, Mode, Result, SclPin, SdaPin};
11use crate::AnyPin;
12use crate::clocks::periph_helpers::{Div4, Lpi2cClockSel, Lpi2cConfig}; 11use crate::clocks::periph_helpers::{Div4, Lpi2cClockSel, Lpi2cConfig};
13use crate::clocks::{PoweredClock, enable_and_reset}; 12use crate::clocks::{PoweredClock, enable_and_reset};
13use crate::gpio::AnyPin;
14use crate::interrupt::typelevel::Interrupt; 14use crate::interrupt::typelevel::Interrupt;
15 15
16/// Bus speed (nominal SCL, no clock stretching) 16/// Bus speed (nominal SCL, no clock stretching)
diff --git a/embassy-mcxa/src/interrupt.rs b/embassy-mcxa/src/interrupt.rs
index be2704454..b662f7ee0 100644
--- a/embassy-mcxa/src/interrupt.rs
+++ b/embassy-mcxa/src/interrupt.rs
@@ -9,7 +9,10 @@
9mod generated { 9mod generated {
10 #[rustfmt::skip] 10 #[rustfmt::skip]
11 embassy_hal_internal::interrupt_mod!( 11 embassy_hal_internal::interrupt_mod!(
12 ADC0,
12 ADC1, 13 ADC1,
14 ADC2,
15 ADC3,
13 DMA_CH0, 16 DMA_CH0,
14 DMA_CH1, 17 DMA_CH1,
15 DMA_CH2, 18 DMA_CH2,
@@ -281,44 +284,6 @@ impl InterruptExt for Rtc {
281 } 284 }
282} 285}
283 286
284pub struct Adc;
285pub const ADC1: Adc = Adc;
286
287impl InterruptExt for Adc {
288 /// Clear any pending ADC1 in NVIC.
289 #[inline]
290 fn unpend(&self) {
291 cortex_m::peripheral::NVIC::unpend(Interrupt::ADC1);
292 }
293
294 /// Set NVIC priority for ADC1.
295 #[inline]
296 fn set_priority(&self, priority: Priority) {
297 unsafe {
298 let mut nvic = cortex_m::peripheral::Peripherals::steal().NVIC;
299 nvic.set_priority(Interrupt::ADC1, u8::from(priority));
300 }
301 }
302
303 /// Enable ADC1 in NVIC.
304 #[inline]
305 unsafe fn enable(&self) {
306 cortex_m::peripheral::NVIC::unmask(Interrupt::ADC1);
307 }
308
309 /// Disable ADC1 in NVIC.
310 #[inline]
311 unsafe fn disable(&self) {
312 cortex_m::peripheral::NVIC::mask(Interrupt::ADC1);
313 }
314
315 /// Check if ADC1 is pending in NVIC.
316 #[inline]
317 fn is_pending(&self) -> bool {
318 cortex_m::peripheral::NVIC::is_pending(Interrupt::ADC1)
319 }
320}
321
322pub struct Gpio0; 287pub struct Gpio0;
323pub const GPIO0: Gpio0 = Gpio0; 288pub const GPIO0: Gpio0 = Gpio0;
324 289
diff --git a/embassy-mcxa/src/lib.rs b/embassy-mcxa/src/lib.rs
index 12c2708de..6383353db 100644
--- a/embassy-mcxa/src/lib.rs
+++ b/embassy-mcxa/src/lib.rs
@@ -8,7 +8,6 @@
8pub mod clocks; // still provide clock helpers 8pub mod clocks; // still provide clock helpers
9pub mod dma; 9pub mod dma;
10pub mod gpio; 10pub mod gpio;
11pub mod pins; // pin mux helpers
12 11
13pub mod adc; 12pub mod adc;
14pub mod clkout; 13pub mod clkout;
@@ -18,15 +17,19 @@ pub mod i2c;
18pub mod interrupt; 17pub mod interrupt;
19pub mod lpuart; 18pub mod lpuart;
20pub mod ostimer; 19pub mod ostimer;
20pub mod reset_reason;
21pub mod rtc; 21pub mod rtc;
22pub mod trng; 22pub mod trng;
23 23
24use crate::interrupt::InterruptExt;
24pub use crate::pac::NVIC_PRIO_BITS; 25pub use crate::pac::NVIC_PRIO_BITS;
25 26
26#[rustfmt::skip] 27#[rustfmt::skip]
27embassy_hal_internal::peripherals!( 28embassy_hal_internal::peripherals!(
28 ADC0, 29 ADC0,
29 ADC1, 30 ADC1,
31 ADC2,
32 ADC3,
30 33
31 AOI0, 34 AOI0,
32 AOI1, 35 AOI1,
@@ -337,9 +340,6 @@ embassy_hal_internal::peripherals!(
337// Use cortex-m-rt's #[interrupt] attribute directly; PAC does not re-export it. 340// Use cortex-m-rt's #[interrupt] attribute directly; PAC does not re-export it.
338 341
339// Re-export interrupt traits and types 342// Re-export interrupt traits and types
340pub use adc::Adc1 as Adc1Token;
341pub use gpio::{AnyPin, Flex, Gpio as GpioToken, Input, Level, Output};
342pub use interrupt::InterruptExt;
343#[cfg(feature = "unstable-pac")] 343#[cfg(feature = "unstable-pac")]
344pub use mcxa_pac as pac; 344pub use mcxa_pac as pac;
345#[cfg(not(feature = "unstable-pac"))] 345#[cfg(not(feature = "unstable-pac"))]
@@ -355,8 +355,6 @@ pub fn init(cfg: crate::config::Config) -> Peripherals {
355 // Apply user-configured priority early; enabling is left to examples/apps 355 // Apply user-configured priority early; enabling is left to examples/apps
356 crate::interrupt::RTC.set_priority(cfg.rtc_interrupt_priority); 356 crate::interrupt::RTC.set_priority(cfg.rtc_interrupt_priority);
357 // Apply user-configured priority early; enabling is left to examples/apps 357 // Apply user-configured priority early; enabling is left to examples/apps
358 crate::interrupt::ADC1.set_priority(cfg.adc_interrupt_priority);
359 // Apply user-configured priority early; enabling is left to examples/apps
360 crate::interrupt::GPIO0.set_priority(cfg.gpio_interrupt_priority); 358 crate::interrupt::GPIO0.set_priority(cfg.gpio_interrupt_priority);
361 // Apply user-configured priority early; enabling is left to examples/apps 359 // Apply user-configured priority early; enabling is left to examples/apps
362 crate::interrupt::GPIO1.set_priority(cfg.gpio_interrupt_priority); 360 crate::interrupt::GPIO1.set_priority(cfg.gpio_interrupt_priority);
diff --git a/embassy-mcxa/src/lpuart/mod.rs b/embassy-mcxa/src/lpuart/mod.rs
index e59ce8140..bce3986b5 100644
--- a/embassy-mcxa/src/lpuart/mod.rs
+++ b/embassy-mcxa/src/lpuart/mod.rs
@@ -6,12 +6,12 @@ use paste::paste;
6 6
7use crate::clocks::periph_helpers::{Div4, LpuartClockSel, LpuartConfig}; 7use crate::clocks::periph_helpers::{Div4, LpuartClockSel, LpuartConfig};
8use crate::clocks::{ClockError, Gate, PoweredClock, enable_and_reset}; 8use crate::clocks::{ClockError, Gate, PoweredClock, enable_and_reset};
9use crate::gpio::SealedPin; 9use crate::gpio::{AnyPin, SealedPin};
10use crate::pac::lpuart0::baud::Sbns as StopBits; 10use crate::pac::lpuart0::baud::Sbns as StopBits;
11use crate::pac::lpuart0::ctrl::{Idlecfg as IdleConfig, Ilt as IdleType, M as DataBits, Pt as Parity}; 11use crate::pac::lpuart0::ctrl::{Idlecfg as IdleConfig, Ilt as IdleType, M as DataBits, Pt as Parity};
12use crate::pac::lpuart0::modir::{Txctsc as TxCtsConfig, Txctssrc as TxCtsSource}; 12use crate::pac::lpuart0::modir::{Txctsc as TxCtsConfig, Txctssrc as TxCtsSource};
13use crate::pac::lpuart0::stat::Msbf as MsbFirst; 13use crate::pac::lpuart0::stat::Msbf as MsbFirst;
14use crate::{AnyPin, interrupt, pac}; 14use crate::{interrupt, pac};
15 15
16pub mod buffered; 16pub mod buffered;
17 17
diff --git a/embassy-mcxa/src/pins.rs b/embassy-mcxa/src/pins.rs
deleted file mode 100644
index 9adbe64c8..000000000
--- a/embassy-mcxa/src/pins.rs
+++ /dev/null
@@ -1,33 +0,0 @@
1//! Pin configuration helpers (separate from peripheral drivers).
2use crate::pac;
3
4/// Configure pins for ADC usage.
5///
6/// # Safety
7///
8/// Must be called after PORT clocks are enabled.
9pub unsafe fn configure_adc_pins() {
10 // P1_10 = ADC1_A8
11 let port1 = &*pac::Port1::ptr();
12 port1.pcr10().write(|w| {
13 w.ps()
14 .ps0()
15 .pe()
16 .pe0()
17 .sre()
18 .sre0()
19 .ode()
20 .ode0()
21 .dse()
22 .dse0()
23 .mux()
24 .mux0()
25 .ibe()
26 .ibe0()
27 .inv()
28 .inv0()
29 .lk()
30 .lk0()
31 });
32 core::arch::asm!("dsb sy; isb sy");
33}
diff --git a/embassy-mcxa/src/reset_reason.rs b/embassy-mcxa/src/reset_reason.rs
new file mode 100644
index 000000000..f9a9ce096
--- /dev/null
+++ b/embassy-mcxa/src/reset_reason.rs
@@ -0,0 +1,106 @@
1//! Reset reason
2//!
3//! MCXA families keep the most recent reset reason in the SRS
4//! register of the CMC block. This lets users understand why the MCU
5//! has reset and take appropriate corrective actions if required.
6
7/// Reads the most recent reset reason from the Core Mode Controller
8/// (CMC).
9pub fn reset_reason() -> ResetReason {
10 let regs = unsafe { &*crate::pac::Cmc::steal() };
11
12 let srs = regs.srs().read();
13
14 if srs.wakeup().is_enabled() {
15 ResetReason::WakeUp
16 } else if srs.por().bit_is_set() {
17 ResetReason::Por
18 } else if srs.vd().bit_is_set() {
19 ResetReason::VoltageDetect
20 } else if srs.warm().bit_is_set() {
21 ResetReason::Warm
22 } else if srs.fatal().bit_is_set() {
23 ResetReason::Fatal
24 } else if srs.pin().bit_is_set() {
25 ResetReason::Pin
26 } else if srs.dap().bit_is_set() {
27 ResetReason::Dap
28 } else if srs.rstack().bit_is_set() {
29 ResetReason::ResetAckTimeout
30 } else if srs.lpack().bit_is_set() {
31 ResetReason::LowPowerAckTimeout
32 } else if srs.scg().bit_is_set() {
33 ResetReason::SystemClockGeneration
34 } else if srs.wwdt0().bit_is_set() {
35 ResetReason::Wwdt0
36 } else if srs.sw().bit_is_set() {
37 ResetReason::Software
38 } else if srs.lockup().bit_is_set() {
39 ResetReason::Lockup
40 } else if srs.cdog0().bit_is_set() {
41 ResetReason::Cdog0
42 } else if srs.cdog1().bit_is_set() {
43 ResetReason::Cdog1
44 } else if srs.jtag().bit_is_set() {
45 ResetReason::Jtag
46 } else {
47 ResetReason::Tamper
48 }
49}
50
51/// Indicates the type and source of the most recent reset.
52#[derive(Clone, Copy, Debug)]
53#[cfg_attr(feature = "defmt", derive(defmt::Format))]
54#[non_exhaustive]
55pub enum ResetReason {
56 /// Tamper reset.
57 Tamper,
58
59 /// JTAG System Reset request.
60 Jtag,
61
62 /// Code Watchdog 0 reset.
63 Cdog0,
64
65 /// Code Watchdog 1 reset.
66 Cdog1,
67
68 /// Lockup reset.
69 Lockup,
70
71 /// Software reset.
72 Software,
73
74 /// Windowed Watchdog 0 reset.
75 Wwdt0,
76
77 /// System clock generation reset.
78 SystemClockGeneration,
79
80 /// Low Power Acknowledge Timeout reset.
81 LowPowerAckTimeout,
82
83 /// Reset Timeout.
84 ResetAckTimeout,
85
86 /// Debug Access Port reset.
87 Dap,
88
89 /// External assertion of RESET_b pin.
90 Pin,
91
92 /// Fatal reset.
93 Fatal,
94
95 /// Warm reset.
96 Warm,
97
98 /// Voltage detect reset.
99 VoltageDetect,
100
101 /// Power-on reset.
102 Por,
103
104 /// Wake-up reset.
105 WakeUp,
106}
diff --git a/embassy-mcxa/src/rtc.rs b/embassy-mcxa/src/rtc.rs
index f975d9c9f..c5474d34a 100644
--- a/embassy-mcxa/src/rtc.rs
+++ b/embassy-mcxa/src/rtc.rs
@@ -9,8 +9,6 @@ use crate::interrupt::typelevel::{Handler, Interrupt};
9use crate::pac; 9use crate::pac;
10use crate::pac::rtc0::cr::Um; 10use crate::pac::rtc0::cr::Um;
11 11
12type Regs = pac::rtc0::RegisterBlock;
13
14/// Global wait cell for alarm notifications 12/// Global wait cell for alarm notifications
15static WAKER: WaitCell = WaitCell::new(); 13static WAKER: WaitCell = WaitCell::new();
16 14
@@ -22,7 +20,7 @@ pub struct InterruptHandler<I: Instance> {
22/// Trait for RTC peripheral instances 20/// Trait for RTC peripheral instances
23pub trait Instance: PeripheralType { 21pub trait Instance: PeripheralType {
24 type Interrupt: Interrupt; 22 type Interrupt: Interrupt;
25 fn ptr() -> *const Regs; 23 fn ptr() -> &'static pac::rtc0::RegisterBlock;
26} 24}
27 25
28/// Token for RTC0 26/// Token for RTC0
@@ -30,8 +28,8 @@ pub type Rtc0 = crate::peripherals::RTC0;
30impl Instance for crate::peripherals::RTC0 { 28impl Instance for crate::peripherals::RTC0 {
31 type Interrupt = crate::interrupt::typelevel::RTC; 29 type Interrupt = crate::interrupt::typelevel::RTC;
32 #[inline(always)] 30 #[inline(always)]
33 fn ptr() -> *const Regs { 31 fn ptr() -> &'static pac::rtc0::RegisterBlock {
34 pac::Rtc0::ptr() 32 unsafe { &*pac::Rtc0::ptr() }
35 } 33 }
36} 34}
37 35
@@ -204,18 +202,19 @@ pub fn get_default_config() -> RtcConfig {
204 } 202 }
205} 203}
206/// Minimal RTC handle for a specific instance I (store the zero-sized token like embassy) 204/// Minimal RTC handle for a specific instance I (store the zero-sized token like embassy)
207pub struct Rtc<'a, I: Instance> { 205pub struct Rtc<'a> {
208 _inst: core::marker::PhantomData<&'a mut I>, 206 _inst: core::marker::PhantomData<&'a mut ()>,
207 info: &'static pac::rtc0::RegisterBlock,
209} 208}
210 209
211impl<'a, I: Instance> Rtc<'a, I> { 210impl<'a> Rtc<'a> {
212 /// Create a new instance of the real time clock. 211 /// Create a new instance of the real time clock.
213 pub fn new( 212 pub fn new<I: Instance>(
214 _inst: Peri<'a, I>, 213 _inst: Peri<'a, I>,
215 _irq: impl crate::interrupt::typelevel::Binding<I::Interrupt, InterruptHandler<I>> + 'a, 214 _irq: impl crate::interrupt::typelevel::Binding<I::Interrupt, InterruptHandler<I>> + 'a,
216 config: RtcConfig, 215 config: RtcConfig,
217 ) -> Self { 216 ) -> Self {
218 let rtc = unsafe { &*I::ptr() }; 217 let info = I::ptr();
219 218
220 // The RTC is NOT gated by the MRCC, but we DO need to make sure the 16k clock 219 // The RTC is NOT gated by the MRCC, but we DO need to make sure the 16k clock
221 // on the vsys domain is active 220 // on the vsys domain is active
@@ -227,13 +226,13 @@ impl<'a, I: Instance> Rtc<'a, I> {
227 } 226 }
228 227
229 // RTC reset 228 // RTC reset
230 rtc.cr().modify(|_, w| w.swr().set_bit()); 229 info.cr().modify(|_, w| w.swr().set_bit());
231 rtc.cr().modify(|_, w| w.swr().clear_bit()); 230 info.cr().modify(|_, w| w.swr().clear_bit());
232 rtc.tsr().write(|w| unsafe { w.bits(1) }); 231 info.tsr().write(|w| unsafe { w.bits(1) });
233 232
234 rtc.cr().modify(|_, w| w.um().variant(config.update_mode)); 233 info.cr().modify(|_, w| w.um().variant(config.update_mode));
235 234
236 rtc.tcr().modify(|_, w| unsafe { 235 info.tcr().modify(|_, w| unsafe {
237 w.cir() 236 w.cir()
238 .bits(config.compensation_interval) 237 .bits(config.compensation_interval)
239 .tcr() 238 .tcr()
@@ -246,6 +245,7 @@ impl<'a, I: Instance> Rtc<'a, I> {
246 245
247 Self { 246 Self {
248 _inst: core::marker::PhantomData, 247 _inst: core::marker::PhantomData,
248 info,
249 } 249 }
250 } 250 }
251 251
@@ -259,9 +259,8 @@ impl<'a, I: Instance> Rtc<'a, I> {
259 /// 259 ///
260 /// The datetime is converted to Unix timestamp and written to the time seconds register. 260 /// The datetime is converted to Unix timestamp and written to the time seconds register.
261 pub fn set_datetime(&self, datetime: RtcDateTime) { 261 pub fn set_datetime(&self, datetime: RtcDateTime) {
262 let rtc = unsafe { &*I::ptr() };
263 let seconds = convert_datetime_to_seconds(&datetime); 262 let seconds = convert_datetime_to_seconds(&datetime);
264 rtc.tsr().write(|w| unsafe { w.bits(seconds) }); 263 self.info.tsr().write(|w| unsafe { w.bits(seconds) });
265 } 264 }
266 265
267 /// Get the current date and time 266 /// Get the current date and time
@@ -274,8 +273,7 @@ impl<'a, I: Instance> Rtc<'a, I> {
274 /// 273 ///
275 /// Reads the current Unix timestamp from the time seconds register and converts it. 274 /// Reads the current Unix timestamp from the time seconds register and converts it.
276 pub fn get_datetime(&self) -> RtcDateTime { 275 pub fn get_datetime(&self) -> RtcDateTime {
277 let rtc = unsafe { &*I::ptr() }; 276 let seconds = self.info.tsr().read().bits();
278 let seconds = rtc.tsr().read().bits();
279 convert_seconds_to_datetime(seconds) 277 convert_seconds_to_datetime(seconds)
280 } 278 }
281 279
@@ -295,19 +293,18 @@ impl<'a, I: Instance> Rtc<'a, I> {
295 /// - Uses timeouts to prevent infinite loops 293 /// - Uses timeouts to prevent infinite loops
296 /// - Enables the alarm interrupt after setting 294 /// - Enables the alarm interrupt after setting
297 pub fn set_alarm(&self, alarm: RtcDateTime) { 295 pub fn set_alarm(&self, alarm: RtcDateTime) {
298 let rtc = unsafe { &*I::ptr() };
299 let seconds = convert_datetime_to_seconds(&alarm); 296 let seconds = convert_datetime_to_seconds(&alarm);
300 297
301 rtc.tar().write(|w| unsafe { w.bits(0) }); 298 self.info.tar().write(|w| unsafe { w.bits(0) });
302 let mut timeout = 10000; 299 let mut timeout = 10000;
303 while rtc.tar().read().bits() != 0 && timeout > 0 { 300 while self.info.tar().read().bits() != 0 && timeout > 0 {
304 timeout -= 1; 301 timeout -= 1;
305 } 302 }
306 303
307 rtc.tar().write(|w| unsafe { w.bits(seconds) }); 304 self.info.tar().write(|w| unsafe { w.bits(seconds) });
308 305
309 let mut timeout = 10000; 306 let mut timeout = 10000;
310 while rtc.tar().read().bits() != seconds && timeout > 0 { 307 while self.info.tar().read().bits() != seconds && timeout > 0 {
311 timeout -= 1; 308 timeout -= 1;
312 } 309 }
313 310
@@ -324,8 +321,7 @@ impl<'a, I: Instance> Rtc<'a, I> {
324 /// 321 ///
325 /// Reads the alarm timestamp from the time alarm register and converts it. 322 /// Reads the alarm timestamp from the time alarm register and converts it.
326 pub fn get_alarm(&self) -> RtcDateTime { 323 pub fn get_alarm(&self) -> RtcDateTime {
327 let rtc = unsafe { &*I::ptr() }; 324 let alarm_seconds = self.info.tar().read().bits();
328 let alarm_seconds = rtc.tar().read().bits();
329 convert_seconds_to_datetime(alarm_seconds) 325 convert_seconds_to_datetime(alarm_seconds)
330 } 326 }
331 327
@@ -335,8 +331,7 @@ impl<'a, I: Instance> Rtc<'a, I> {
335 /// 331 ///
336 /// Sets the Time Counter Enable (TCE) bit in the status register. 332 /// Sets the Time Counter Enable (TCE) bit in the status register.
337 pub fn start(&self) { 333 pub fn start(&self) {
338 let rtc = unsafe { &*I::ptr() }; 334 self.info.sr().modify(|_, w| w.tce().set_bit());
339 rtc.sr().modify(|_, w| w.tce().set_bit());
340 } 335 }
341 336
342 /// Stop the RTC time counter 337 /// Stop the RTC time counter
@@ -345,8 +340,7 @@ impl<'a, I: Instance> Rtc<'a, I> {
345 /// 340 ///
346 /// Clears the Time Counter Enable (TCE) bit in the status register. 341 /// Clears the Time Counter Enable (TCE) bit in the status register.
347 pub fn stop(&self) { 342 pub fn stop(&self) {
348 let rtc = unsafe { &*I::ptr() }; 343 self.info.sr().modify(|_, w| w.tce().clear_bit());
349 rtc.sr().modify(|_, w| w.tce().clear_bit());
350 } 344 }
351 345
352 /// Enable specific RTC interrupts 346 /// Enable specific RTC interrupts
@@ -364,19 +358,17 @@ impl<'a, I: Instance> Rtc<'a, I> {
364 /// - Alarm Interrupt 358 /// - Alarm Interrupt
365 /// - Seconds Interrupt 359 /// - Seconds Interrupt
366 pub fn set_interrupt(&self, mask: u32) { 360 pub fn set_interrupt(&self, mask: u32) {
367 let rtc = unsafe { &*I::ptr() };
368
369 if (RtcInterruptEnable::RTC_TIME_INVALID_INTERRUPT_ENABLE & mask) != 0 { 361 if (RtcInterruptEnable::RTC_TIME_INVALID_INTERRUPT_ENABLE & mask) != 0 {
370 rtc.ier().modify(|_, w| w.tiie().tiie_1()); 362 self.info.ier().modify(|_, w| w.tiie().tiie_1());
371 } 363 }
372 if (RtcInterruptEnable::RTC_TIME_OVERFLOW_INTERRUPT_ENABLE & mask) != 0 { 364 if (RtcInterruptEnable::RTC_TIME_OVERFLOW_INTERRUPT_ENABLE & mask) != 0 {
373 rtc.ier().modify(|_, w| w.toie().toie_1()); 365 self.info.ier().modify(|_, w| w.toie().toie_1());
374 } 366 }
375 if (RtcInterruptEnable::RTC_ALARM_INTERRUPT_ENABLE & mask) != 0 { 367 if (RtcInterruptEnable::RTC_ALARM_INTERRUPT_ENABLE & mask) != 0 {
376 rtc.ier().modify(|_, w| w.taie().taie_1()); 368 self.info.ier().modify(|_, w| w.taie().taie_1());
377 } 369 }
378 if (RtcInterruptEnable::RTC_SECONDS_INTERRUPT_ENABLE & mask) != 0 { 370 if (RtcInterruptEnable::RTC_SECONDS_INTERRUPT_ENABLE & mask) != 0 {
379 rtc.ier().modify(|_, w| w.tsie().tsie_1()); 371 self.info.ier().modify(|_, w| w.tsie().tsie_1());
380 } 372 }
381 } 373 }
382 374
@@ -390,19 +382,17 @@ impl<'a, I: Instance> Rtc<'a, I> {
390 /// 382 ///
391 /// This function disables the specified interrupt types. 383 /// This function disables the specified interrupt types.
392 pub fn disable_interrupt(&self, mask: u32) { 384 pub fn disable_interrupt(&self, mask: u32) {
393 let rtc = unsafe { &*I::ptr() };
394
395 if (RtcInterruptEnable::RTC_TIME_INVALID_INTERRUPT_ENABLE & mask) != 0 { 385 if (RtcInterruptEnable::RTC_TIME_INVALID_INTERRUPT_ENABLE & mask) != 0 {
396 rtc.ier().modify(|_, w| w.tiie().tiie_0()); 386 self.info.ier().modify(|_, w| w.tiie().tiie_0());
397 } 387 }
398 if (RtcInterruptEnable::RTC_TIME_OVERFLOW_INTERRUPT_ENABLE & mask) != 0 { 388 if (RtcInterruptEnable::RTC_TIME_OVERFLOW_INTERRUPT_ENABLE & mask) != 0 {
399 rtc.ier().modify(|_, w| w.toie().toie_0()); 389 self.info.ier().modify(|_, w| w.toie().toie_0());
400 } 390 }
401 if (RtcInterruptEnable::RTC_ALARM_INTERRUPT_ENABLE & mask) != 0 { 391 if (RtcInterruptEnable::RTC_ALARM_INTERRUPT_ENABLE & mask) != 0 {
402 rtc.ier().modify(|_, w| w.taie().taie_0()); 392 self.info.ier().modify(|_, w| w.taie().taie_0());
403 } 393 }
404 if (RtcInterruptEnable::RTC_SECONDS_INTERRUPT_ENABLE & mask) != 0 { 394 if (RtcInterruptEnable::RTC_SECONDS_INTERRUPT_ENABLE & mask) != 0 {
405 rtc.ier().modify(|_, w| w.tsie().tsie_0()); 395 self.info.ier().modify(|_, w| w.tsie().tsie_0());
406 } 396 }
407 } 397 }
408 398
@@ -412,8 +402,7 @@ impl<'a, I: Instance> Rtc<'a, I> {
412 /// 402 ///
413 /// This function clears the Time Alarm Interrupt Enable bit. 403 /// This function clears the Time Alarm Interrupt Enable bit.
414 pub fn clear_alarm_flag(&self) { 404 pub fn clear_alarm_flag(&self) {
415 let rtc = unsafe { &*I::ptr() }; 405 self.info.ier().modify(|_, w| w.taie().clear_bit());
416 rtc.ier().modify(|_, w| w.taie().clear_bit());
417 } 406 }
418 407
419 /// Wait for an RTC alarm to trigger. 408 /// Wait for an RTC alarm to trigger.
@@ -421,6 +410,7 @@ impl<'a, I: Instance> Rtc<'a, I> {
421 /// # Arguments 410 /// # Arguments
422 /// 411 ///
423 /// * `alarm` - The date and time when the alarm should trigger 412 /// * `alarm` - The date and time when the alarm should trigger
413 ///
424 /// This function will wait until the RTC alarm is triggered. 414 /// This function will wait until the RTC alarm is triggered.
425 /// If no alarm is scheduled, it will wait indefinitely until one is scheduled and triggered. 415 /// If no alarm is scheduled, it will wait indefinitely until one is scheduled and triggered.
426 pub async fn wait_for_alarm(&mut self, alarm: RtcDateTime) { 416 pub async fn wait_for_alarm(&mut self, alarm: RtcDateTime) {