1use core::{
2 marker::PhantomData,
3 pin::Pin,
4 task::{Context, Poll},
5};
6
7use Interrupt::LP_ADC as InterruptSource;
9use portable_atomic::{AtomicU32, Ordering};
11use procmacros::handler;
12
13use super::{AdcCalScheme, AdcChannel, AdcConfig, AdcPin, Error};
14use crate::{
15 Async,
16 Blocking,
17 asynch::AtomicWaker,
18 interrupt::{InterruptConfigurable, InterruptHandler},
19 peripherals::{APB_SARADC, Interrupt, LP_PERI},
20 rtc_cntl::WakeLock,
21 system::{GenericPeripheralGuard, Peripheral},
22};
23
24pub(super) const NUM_ATTENS: usize = 8;
26
27const ADC_DATA_MASK: u32 = 0x1_ffff;
30
31#[instability::unstable]
40pub const FULL_SCALE: u16 = 4393;
41
42#[instability::unstable]
51pub const ZERO_DIFF_CODE: u16 = 2198;
52
53const TRIGGER_MODE_SW: u8 = 2;
55const TRIGGER_MODE_OFF: u8 = 0;
57
58const FORCE_XPD_SAR_PU: u8 = 3;
60
61const CLK_DIV_NUM: u8 = 4;
66
67const CLK_SRC_XTAL: u8 = 1;
69
70fn enable_refgen() {
72 APB_SARADC::regs().ref_control().modify(|_, w| {
73 w.rtc_xpd_refgen().set_bit();
74 w.rtc_pre_charge().set_bit();
75 w.rtc_ref_delay().set_bit()
76 });
77}
78
79fn power_on_sar_units() {
83 enable_refgen();
84
85 APB_SARADC::regs()
86 .ctrl0()
87 .modify(|_, w| unsafe { w.xpd_sar1_force().bits(FORCE_XPD_SAR_PU) });
88 APB_SARADC::regs()
89 .ctrl1()
90 .modify(|_, w| unsafe { w.xpd_sar2_force().bits(FORCE_XPD_SAR_PU) });
91}
92
93#[doc(hidden)]
94pub trait RegisterAccess {
95 fn prepare();
97
98 fn program_pattern(channel: u8);
100
101 fn start_sample();
103
104 fn is_done() -> bool;
106
107 fn read_data() -> u16;
109
110 fn reset();
112
113 fn start(channel: u8) {
118 Self::prepare();
119 Self::program_pattern(channel);
120 Self::start_sample();
121 }
122
123 fn sample(channel: u8) -> u16 {
125 Self::start(channel);
126
127 while !Self::is_done() {}
128
129 let converted_value = Self::read_data();
130 Self::reset();
131 converted_value
132 }
133}
134
135#[cfg(adc_adc1)]
136impl RegisterAccess for crate::peripherals::ADC1<'_> {
137 fn prepare() {
138 APB_SARADC::regs()
139 .ctrl2()
140 .modify(|_, w| w.timer_en().clear_bit());
141
142 power_on_sar_units();
143
144 APB_SARADC::regs().ctrl0().modify(|_, w| {
147 w.sar1_continue_mode_en().clear_bit();
148 w.sar1_trigger_stop().set_bit()
149 });
150 }
151
152 fn program_pattern(channel: u8) {
153 let regs = APB_SARADC::regs();
154
155 let entry = (((channel & 0xf) as u32) << 2) << 18;
158
159 regs.ctrl0().modify(|_, w| unsafe {
160 w.sar1_patt_type().set_bit();
161 w.sar1_patt_len().bits(0)
162 });
163 regs.sar1_patt_tab1()
164 .write(|w| unsafe { w.sar1_patt_tab1().bits(entry) });
165
166 regs.ctrl0().modify(|_, w| w.sar1_patt_p_clear().set_bit());
167 regs.ctrl0()
168 .modify(|_, w| w.sar1_patt_p_clear().clear_bit());
169
170 regs.ctrl0()
171 .modify(|_, w| unsafe { w.sar1_trigger_mode().bits(TRIGGER_MODE_SW) });
172 }
173
174 fn start_sample() {
175 APB_SARADC::regs()
176 .ctrl0()
177 .modify(|_, w| w.sar1_trigger_start().set_bit());
178 }
179
180 fn is_done() -> bool {
181 APB_SARADC::regs().int_raw().read().sar1_done().bit_is_set()
182 }
183
184 fn read_data() -> u16 {
185 (APB_SARADC::regs()
186 .sar1_data_status()
187 .read()
188 .apb_saradc1_data()
189 .bits()
190 & ADC_DATA_MASK) as u16
191 }
192
193 fn reset() {
194 APB_SARADC::regs()
195 .int_clr()
196 .write(|w| w.sar1_done().clear_bit_by_one());
197
198 APB_SARADC::regs()
199 .ctrl0()
200 .modify(|_, w| unsafe { w.sar1_trigger_mode().bits(TRIGGER_MODE_OFF) });
201 }
202}
203
204#[cfg(adc_adc2)]
205impl RegisterAccess for crate::peripherals::ADC2<'_> {
206 fn prepare() {
207 APB_SARADC::regs()
208 .ctrl2()
209 .modify(|_, w| w.timer_en().clear_bit());
210
211 power_on_sar_units();
212
213 APB_SARADC::regs().ctrl1().modify(|_, w| {
214 w.sar2_continue_mode_en().clear_bit();
215 w.sar2_trigger_stop().set_bit()
216 });
217 }
218
219 fn program_pattern(channel: u8) {
220 let regs = APB_SARADC::regs();
221
222 let entry = (((channel & 0xf) as u32) << 2) << 18;
223
224 regs.ctrl1().modify(|_, w| unsafe {
225 w.sar2_patt_type().set_bit();
226 w.sar2_patt_len().bits(0)
227 });
228 regs.sar2_patt_tab1()
229 .write(|w| unsafe { w.sar2_patt_tab1().bits(entry) });
230
231 regs.ctrl1().modify(|_, w| w.sar2_patt_p_clear().set_bit());
232 regs.ctrl1()
233 .modify(|_, w| w.sar2_patt_p_clear().clear_bit());
234
235 regs.ctrl1()
236 .modify(|_, w| unsafe { w.sar2_trigger_mode().bits(TRIGGER_MODE_SW) });
237 }
238
239 fn start_sample() {
240 APB_SARADC::regs()
241 .ctrl1()
242 .modify(|_, w| w.sar2_trigger_start().set_bit());
243 }
244
245 fn is_done() -> bool {
246 APB_SARADC::regs().int_raw().read().sar2_done().bit_is_set()
247 }
248
249 fn read_data() -> u16 {
250 (APB_SARADC::regs()
251 .sar2_data_status()
252 .read()
253 .apb_saradc2_data()
254 .bits()
255 & ADC_DATA_MASK) as u16
256 }
257
258 fn reset() {
259 APB_SARADC::regs()
260 .int_clr()
261 .write(|w| w.sar2_done().clear_bit_by_one());
262
263 APB_SARADC::regs()
264 .ctrl1()
265 .modify(|_, w| unsafe { w.sar2_trigger_mode().bits(TRIGGER_MODE_OFF) });
266 }
267}
268
269pub struct Adc<'d, ADC, Dm: crate::DriverMode> {
271 _adc: ADC,
272 configured: [bool; NUM_ATTENS],
273 active_channel: Option<u8>,
274 _guard: GenericPeripheralGuard<{ Peripheral::ApbSarAdc as u8 }>,
275 _phantom: PhantomData<(Dm, &'d mut ())>,
276}
277
278fn check_channel_configured(configured: &[bool; NUM_ATTENS], channel: u8) -> Result<(), Error> {
279 if configured[channel as usize] {
280 Ok(())
281 } else {
282 Err(Error::ChannelNotConfigured(channel))
283 }
284}
285
286impl<'d, ADCX> Adc<'d, ADCX, Blocking>
287where
288 ADCX: RegisterAccess + 'd,
289{
290 pub fn new(adc_instance: ADCX, config: AdcConfig<ADCX>) -> Result<Self, Error> {
295 let guard = GenericPeripheralGuard::new();
296
297 let configured = config.attenuations.map(|attenuation| attenuation.is_some());
298
299 LP_PERI::regs().adc_ctrl().modify(|_, w| unsafe {
301 w.lp_adc_clk_sel().bits(CLK_SRC_XTAL);
302 w.lp_adc_div_num().bits(CLK_DIV_NUM)
303 });
304
305 APB_SARADC::regs()
307 .ctrl_date()
308 .modify(|_, w| w.clk_en().set_bit());
309
310 ADCX::prepare();
311 ADCX::reset();
312
313 Ok(Adc {
314 _adc: adc_instance,
315 configured,
316 active_channel: None,
317 _guard: guard,
318 _phantom: PhantomData,
319 })
320 }
321
322 pub fn into_async(mut self) -> Adc<'d, ADCX, Async> {
324 acquire_async_adc();
325 self.set_interrupt_handler(adc_interrupt_handler);
326
327 ADCX::reset();
329
330 Adc {
331 _adc: self._adc,
332 configured: self.configured,
333 active_channel: self.active_channel,
334 _guard: self._guard,
335 _phantom: PhantomData,
336 }
337 }
338
339 pub fn read_blocking<PIN, CS>(&mut self, pin: &mut AdcPin<PIN, ADCX, CS>) -> Result<u16, Error>
350 where
351 PIN: AdcChannel,
352 CS: AdcCalScheme<ADCX>,
353 {
354 let channel = pin.pin.adc_channel();
355 check_channel_configured(&self.configured, channel)?;
356
357 Ok(ADCX::sample(channel))
358 }
359
360 pub fn read_oneshot<PIN, CS>(
374 &mut self,
375 pin: &mut super::AdcPin<PIN, ADCX, CS>,
376 ) -> nb::Result<u16, Error>
377 where
378 PIN: super::AdcChannel,
379 CS: super::AdcCalScheme<ADCX>,
380 {
381 let channel = pin.pin.adc_channel();
382 check_channel_configured(&self.configured, channel).map_err(nb::Error::Other)?;
383
384 if let Some(active_channel) = self.active_channel {
385 if active_channel != channel {
389 return Err(nb::Error::WouldBlock);
390 }
391 } else {
392 self.active_channel = Some(channel);
394
395 ADCX::start(channel);
396 }
397
398 if !ADCX::is_done() {
399 return Err(nb::Error::WouldBlock);
400 }
401
402 let converted_value = ADCX::read_data();
403 ADCX::reset();
404
405 self.active_channel = None;
407
408 Ok(converted_value)
409 }
410}
411
412impl<ADCX> crate::private::Sealed for Adc<'_, ADCX, Blocking> {}
413
414impl<ADCX> InterruptConfigurable for Adc<'_, ADCX, Blocking> {
415 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
416 for core in crate::system::Cpu::other() {
417 crate::interrupt::disable(core, InterruptSource);
418 }
419 crate::interrupt::bind_handler(InterruptSource, handler);
420 }
421}
422
423impl<'d, ADCX> Adc<'d, ADCX, Async>
424where
425 ADCX: RegisterAccess + 'd,
426{
427 pub fn into_blocking(self) -> Adc<'d, ADCX, Blocking> {
429 if release_async_adc() {
430 for cpu in crate::system::Cpu::all() {
432 crate::interrupt::disable(cpu, InterruptSource);
433 }
434 }
435 Adc {
436 _adc: self._adc,
437 configured: self.configured,
438 active_channel: self.active_channel,
439 _guard: self._guard,
440 _phantom: PhantomData,
441 }
442 }
443
444 pub async fn read_oneshot<PIN, CS>(
458 &mut self,
459 pin: &mut super::AdcPin<PIN, ADCX, CS>,
460 ) -> Result<u16, Error>
461 where
462 ADCX: Instance,
463 PIN: super::AdcChannel,
464 CS: super::AdcCalScheme<ADCX>,
465 {
466 let channel = pin.pin.adc_channel();
467 check_channel_configured(&self.configured, channel)?;
468
469 ADCX::start(channel);
470
471 AdcFuture::<ADCX>::new(self).await;
472
473 let converted_value = ADCX::read_data();
474 ADCX::reset();
475
476 Ok(converted_value)
477 }
478}
479
480static ASYNC_ADC_COUNT: AtomicU32 = AtomicU32::new(0);
481
482fn acquire_async_adc() {
483 ASYNC_ADC_COUNT.fetch_add(1, Ordering::Relaxed);
484}
485
486fn release_async_adc() -> bool {
487 ASYNC_ADC_COUNT.fetch_sub(1, Ordering::Relaxed) == 1
488}
489
490#[handler]
491pub(crate) fn adc_interrupt_handler() {
492 let interrupt_status = APB_SARADC::regs().int_st().read();
493
494 #[cfg(adc_adc1)]
495 if interrupt_status.sar1_done().bit_is_set() {
496 unsafe { handle_async(crate::peripherals::ADC1::steal()) }
497 }
498
499 #[cfg(adc_adc2)]
500 if interrupt_status.sar2_done().bit_is_set() {
501 unsafe { handle_async(crate::peripherals::ADC2::steal()) }
502 }
503}
504
505fn handle_async<ADCX: Instance>(_instance: ADCX) {
506 ADCX::waker().wake();
507 ADCX::unlisten();
508}
509
510pub trait Instance: crate::private::Sealed {
512 fn listen();
514
515 fn unlisten();
517
518 fn clear_interrupt();
520
521 fn waker() -> &'static AtomicWaker;
523}
524
525#[cfg(adc_adc1)]
526impl Instance for crate::peripherals::ADC1<'_> {
527 fn listen() {
528 APB_SARADC::regs()
529 .int_ena()
530 .modify(|_, w| w.sar1_done().set_bit());
531 }
532
533 fn unlisten() {
534 APB_SARADC::regs()
535 .int_ena()
536 .modify(|_, w| w.sar1_done().clear_bit());
537 }
538
539 fn clear_interrupt() {
540 APB_SARADC::regs()
541 .int_clr()
542 .write(|w| w.sar1_done().clear_bit_by_one());
543 }
544
545 fn waker() -> &'static AtomicWaker {
546 static WAKER: AtomicWaker = AtomicWaker::new();
547
548 &WAKER
549 }
550}
551
552#[cfg(adc_adc2)]
553impl Instance for crate::peripherals::ADC2<'_> {
554 fn listen() {
555 APB_SARADC::regs()
556 .int_ena()
557 .modify(|_, w| w.sar2_done().set_bit());
558 }
559
560 fn unlisten() {
561 APB_SARADC::regs()
562 .int_ena()
563 .modify(|_, w| w.sar2_done().clear_bit());
564 }
565
566 fn clear_interrupt() {
567 APB_SARADC::regs()
568 .int_clr()
569 .write(|w| w.sar2_done().clear_bit_by_one());
570 }
571
572 fn waker() -> &'static AtomicWaker {
573 static WAKER: AtomicWaker = AtomicWaker::new();
574
575 &WAKER
576 }
577}
578
579#[must_use = "futures do nothing unless you `.await` or poll them"]
580pub(crate) struct AdcFuture<ADCX: Instance> {
581 phantom: PhantomData<ADCX>,
582 _wake_lock: WakeLock,
583}
584
585impl<ADCX: Instance> AdcFuture<ADCX> {
586 pub fn new(_self: &super::Adc<'_, ADCX, Async>) -> Self {
587 Self {
588 phantom: PhantomData,
589 _wake_lock: WakeLock::new(),
590 }
591 }
592}
593
594impl<ADCX: Instance + super::RegisterAccess> core::future::Future for AdcFuture<ADCX> {
595 type Output = ();
596
597 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
598 if ADCX::is_done() {
599 ADCX::clear_interrupt();
600 Poll::Ready(())
601 } else {
602 ADCX::waker().register(cx.waker());
603 ADCX::listen();
604 Poll::Pending
605 }
606 }
607}
608
609impl<ADCX: Instance> Drop for AdcFuture<ADCX> {
610 fn drop(&mut self) {
611 ADCX::unlisten();
612 }
613}