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};
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
79#[doc(hidden)]
80pub trait RegisterAccess {
81 fn enable();
83
84 fn program_pattern(channel: u8);
86
87 fn start_sample();
89
90 fn is_done() -> bool;
92
93 fn read_data() -> u16;
95
96 fn reset();
98}
99
100#[cfg(adc_adc1)]
101impl RegisterAccess for crate::peripherals::ADC1<'_> {
102 fn enable() {
103 APB_SARADC::regs()
104 .ctrl2()
105 .modify(|_, w| w.timer_en().clear_bit());
106
107 enable_refgen();
108
109 APB_SARADC::regs().ctrl0().modify(|_, w| unsafe {
110 w.xpd_sar1_force().bits(FORCE_XPD_SAR_PU);
111 w.sar1_continue_mode_en().clear_bit();
112 w.sar1_trigger_stop().set_bit()
113 });
114 }
115
116 fn program_pattern(channel: u8) {
117 let regs = APB_SARADC::regs();
118
119 let entry = (((channel & 0xf) as u32) << 2) << 18;
122
123 regs.ctrl0().modify(|_, w| unsafe {
124 w.sar1_patt_type().set_bit();
125 w.sar1_patt_len().bits(0)
126 });
127 regs.sar1_patt_tab1()
128 .write(|w| unsafe { w.sar1_patt_tab1().bits(entry) });
129
130 regs.ctrl0().modify(|_, w| w.sar1_patt_p_clear().set_bit());
131 regs.ctrl0()
132 .modify(|_, w| w.sar1_patt_p_clear().clear_bit());
133
134 regs.ctrl0()
135 .modify(|_, w| unsafe { w.sar1_trigger_mode().bits(TRIGGER_MODE_SW) });
136 }
137
138 fn start_sample() {
139 APB_SARADC::regs()
140 .ctrl0()
141 .modify(|_, w| w.sar1_trigger_start().set_bit());
142 }
143
144 fn is_done() -> bool {
145 APB_SARADC::regs().int_raw().read().sar1_done().bit_is_set()
146 }
147
148 fn read_data() -> u16 {
149 (APB_SARADC::regs()
150 .sar1_data_status()
151 .read()
152 .apb_saradc1_data()
153 .bits()
154 & ADC_DATA_MASK) as u16
155 }
156
157 fn reset() {
158 APB_SARADC::regs()
159 .int_clr()
160 .write(|w| w.sar1_done().clear_bit_by_one());
161
162 APB_SARADC::regs()
163 .ctrl0()
164 .modify(|_, w| unsafe { w.sar1_trigger_mode().bits(TRIGGER_MODE_OFF) });
165 }
166}
167
168#[cfg(adc_adc2)]
169impl RegisterAccess for crate::peripherals::ADC2<'_> {
170 fn enable() {
171 APB_SARADC::regs()
172 .ctrl2()
173 .modify(|_, w| w.timer_en().clear_bit());
174
175 enable_refgen();
176
177 APB_SARADC::regs().ctrl1().modify(|_, w| unsafe {
178 w.xpd_sar2_force().bits(FORCE_XPD_SAR_PU);
179 w.sar2_continue_mode_en().clear_bit();
180 w.sar2_trigger_stop().set_bit()
181 });
182 }
183
184 fn program_pattern(channel: u8) {
185 let regs = APB_SARADC::regs();
186
187 let entry = (((channel & 0xf) as u32) << 2) << 18;
188
189 regs.ctrl1().modify(|_, w| unsafe {
190 w.sar2_patt_type().set_bit();
191 w.sar2_patt_len().bits(0)
192 });
193 regs.sar2_patt_tab1()
194 .write(|w| unsafe { w.sar2_patt_tab1().bits(entry) });
195
196 regs.ctrl1().modify(|_, w| w.sar2_patt_p_clear().set_bit());
197 regs.ctrl1()
198 .modify(|_, w| w.sar2_patt_p_clear().clear_bit());
199
200 regs.ctrl1()
201 .modify(|_, w| unsafe { w.sar2_trigger_mode().bits(TRIGGER_MODE_SW) });
202 }
203
204 fn start_sample() {
205 APB_SARADC::regs()
206 .ctrl1()
207 .modify(|_, w| w.sar2_trigger_start().set_bit());
208 }
209
210 fn is_done() -> bool {
211 APB_SARADC::regs().int_raw().read().sar2_done().bit_is_set()
212 }
213
214 fn read_data() -> u16 {
215 (APB_SARADC::regs()
216 .sar2_data_status()
217 .read()
218 .apb_saradc2_data()
219 .bits()
220 & ADC_DATA_MASK) as u16
221 }
222
223 fn reset() {
224 APB_SARADC::regs()
225 .int_clr()
226 .write(|w| w.sar2_done().clear_bit_by_one());
227
228 APB_SARADC::regs()
229 .ctrl1()
230 .modify(|_, w| unsafe { w.sar2_trigger_mode().bits(TRIGGER_MODE_OFF) });
231 }
232}
233
234pub struct Adc<'d, ADC, Dm: crate::DriverMode> {
236 _adc: ADC,
237 active_channel: Option<u8>,
238 _guard: GenericPeripheralGuard<{ Peripheral::ApbSarAdc as u8 }>,
239 _phantom: PhantomData<(Dm, &'d mut ())>,
240}
241
242impl<'d, ADCX> Adc<'d, ADCX, Blocking>
243where
244 ADCX: RegisterAccess + 'd,
245{
246 pub fn new(adc_instance: ADCX, _config: AdcConfig<ADCX>) -> Self {
252 let guard = GenericPeripheralGuard::new();
253
254 LP_PERI::regs().adc_ctrl().modify(|_, w| unsafe {
256 w.lp_adc_clk_sel().bits(CLK_SRC_XTAL);
257 w.lp_adc_div_num().bits(CLK_DIV_NUM)
258 });
259
260 APB_SARADC::regs()
262 .ctrl_date()
263 .modify(|_, w| w.clk_en().set_bit());
264
265 ADCX::enable();
266
267 Adc {
268 _adc: adc_instance,
269 active_channel: None,
270 _guard: guard,
271 _phantom: PhantomData,
272 }
273 }
274
275 pub fn into_async(mut self) -> Adc<'d, ADCX, Async> {
277 acquire_async_adc();
278 self.set_interrupt_handler(adc_interrupt_handler);
279
280 ADCX::reset();
282
283 Adc {
284 _adc: self._adc,
285 active_channel: self.active_channel,
286 _guard: self._guard,
287 _phantom: PhantomData,
288 }
289 }
290
291 pub fn read_blocking<PIN, CS>(&mut self, pin: &mut AdcPin<PIN, ADCX, CS>) -> u16
297 where
298 PIN: AdcChannel,
299 CS: AdcCalScheme<ADCX>,
300 {
301 ADCX::program_pattern(pin.pin.adc_channel());
302 ADCX::start_sample();
303
304 while !ADCX::is_done() {}
305
306 let converted_value = ADCX::read_data();
307 ADCX::reset();
308
309 converted_value
310 }
311
312 pub fn read_oneshot<PIN, CS>(
321 &mut self,
322 pin: &mut super::AdcPin<PIN, ADCX, CS>,
323 ) -> nb::Result<u16, ()>
324 where
325 PIN: super::AdcChannel,
326 CS: super::AdcCalScheme<ADCX>,
327 {
328 if let Some(active_channel) = self.active_channel {
329 if active_channel != pin.pin.adc_channel() {
333 return Err(nb::Error::WouldBlock);
334 }
335 } else {
336 self.active_channel = Some(pin.pin.adc_channel());
338
339 ADCX::program_pattern(pin.pin.adc_channel());
340 ADCX::start_sample();
341 }
342
343 if !ADCX::is_done() {
344 return Err(nb::Error::WouldBlock);
345 }
346
347 let converted_value = ADCX::read_data();
348 ADCX::reset();
349
350 self.active_channel = None;
352
353 Ok(converted_value)
354 }
355}
356
357impl<ADCX> crate::private::Sealed for Adc<'_, ADCX, Blocking> {}
358
359impl<ADCX> InterruptConfigurable for Adc<'_, ADCX, Blocking> {
360 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
361 for core in crate::system::Cpu::other() {
362 crate::interrupt::disable(core, InterruptSource);
363 }
364 crate::interrupt::bind_handler(InterruptSource, handler);
365 }
366}
367
368impl<'d, ADCX> Adc<'d, ADCX, Async>
369where
370 ADCX: RegisterAccess + 'd,
371{
372 pub fn into_blocking(self) -> Adc<'d, ADCX, Blocking> {
374 if release_async_adc() {
375 for cpu in crate::system::Cpu::all() {
377 crate::interrupt::disable(cpu, InterruptSource);
378 }
379 }
380 Adc {
381 _adc: self._adc,
382 active_channel: self.active_channel,
383 _guard: self._guard,
384 _phantom: PhantomData,
385 }
386 }
387
388 pub async fn read_oneshot<PIN, CS>(&mut self, pin: &mut super::AdcPin<PIN, ADCX, CS>) -> u16
397 where
398 ADCX: Instance,
399 PIN: super::AdcChannel,
400 CS: super::AdcCalScheme<ADCX>,
401 {
402 ADCX::program_pattern(pin.pin.adc_channel());
403 ADCX::start_sample();
404
405 AdcFuture::<ADCX>::new(self).await;
406
407 let converted_value = ADCX::read_data();
408 ADCX::reset();
409
410 converted_value
411 }
412}
413
414static ASYNC_ADC_COUNT: AtomicU32 = AtomicU32::new(0);
415
416fn acquire_async_adc() {
417 ASYNC_ADC_COUNT.fetch_add(1, Ordering::Relaxed);
418}
419
420fn release_async_adc() -> bool {
421 ASYNC_ADC_COUNT.fetch_sub(1, Ordering::Relaxed) == 1
422}
423
424#[handler]
425pub(crate) fn adc_interrupt_handler() {
426 let interrupt_status = APB_SARADC::regs().int_st().read();
427
428 #[cfg(adc_adc1)]
429 if interrupt_status.sar1_done().bit_is_set() {
430 unsafe { handle_async(crate::peripherals::ADC1::steal()) }
431 }
432
433 #[cfg(adc_adc2)]
434 if interrupt_status.sar2_done().bit_is_set() {
435 unsafe { handle_async(crate::peripherals::ADC2::steal()) }
436 }
437}
438
439fn handle_async<ADCX: Instance>(_instance: ADCX) {
440 ADCX::waker().wake();
441 ADCX::unlisten();
442}
443
444pub trait Instance: crate::private::Sealed {
446 fn listen();
448
449 fn unlisten();
451
452 fn clear_interrupt();
454
455 fn waker() -> &'static AtomicWaker;
457}
458
459#[cfg(adc_adc1)]
460impl Instance for crate::peripherals::ADC1<'_> {
461 fn listen() {
462 APB_SARADC::regs()
463 .int_ena()
464 .modify(|_, w| w.sar1_done().set_bit());
465 }
466
467 fn unlisten() {
468 APB_SARADC::regs()
469 .int_ena()
470 .modify(|_, w| w.sar1_done().clear_bit());
471 }
472
473 fn clear_interrupt() {
474 APB_SARADC::regs()
475 .int_clr()
476 .write(|w| w.sar1_done().clear_bit_by_one());
477 }
478
479 fn waker() -> &'static AtomicWaker {
480 static WAKER: AtomicWaker = AtomicWaker::new();
481
482 &WAKER
483 }
484}
485
486#[cfg(adc_adc2)]
487impl Instance for crate::peripherals::ADC2<'_> {
488 fn listen() {
489 APB_SARADC::regs()
490 .int_ena()
491 .modify(|_, w| w.sar2_done().set_bit());
492 }
493
494 fn unlisten() {
495 APB_SARADC::regs()
496 .int_ena()
497 .modify(|_, w| w.sar2_done().clear_bit());
498 }
499
500 fn clear_interrupt() {
501 APB_SARADC::regs()
502 .int_clr()
503 .write(|w| w.sar2_done().clear_bit_by_one());
504 }
505
506 fn waker() -> &'static AtomicWaker {
507 static WAKER: AtomicWaker = AtomicWaker::new();
508
509 &WAKER
510 }
511}
512
513#[must_use = "futures do nothing unless you `.await` or poll them"]
514pub(crate) struct AdcFuture<ADCX: Instance> {
515 phantom: PhantomData<ADCX>,
516 _wake_lock: WakeLock,
517}
518
519impl<ADCX: Instance> AdcFuture<ADCX> {
520 pub fn new(_self: &super::Adc<'_, ADCX, Async>) -> Self {
521 Self {
522 phantom: PhantomData,
523 _wake_lock: WakeLock::new(),
524 }
525 }
526}
527
528impl<ADCX: Instance + super::RegisterAccess> core::future::Future for AdcFuture<ADCX> {
529 type Output = ();
530
531 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
532 if ADCX::is_done() {
533 ADCX::clear_interrupt();
534 Poll::Ready(())
535 } else {
536 ADCX::waker().register(cx.waker());
537 ADCX::listen();
538 Poll::Pending
539 }
540 }
541}
542
543impl<ADCX: Instance> Drop for AdcFuture<ADCX> {
544 fn drop(&mut self) {
545 ADCX::unlisten();
546 }
547}