1use core::{
2 marker::PhantomData,
3 pin::Pin,
4 task::{Context, Poll},
5};
6
7use portable_atomic::{AtomicU32, Ordering};
8use procmacros::{handler, ram};
9
10pub use self::calibration::*;
11use super::{AdcCalScheme, AdcChannel, AdcConfig, AdcPin, Attenuation, Error};
12use crate::{
13 Async,
14 Blocking,
15 asynch::AtomicWaker,
16 efuse::AdcCalibUnit,
17 interrupt::{InterruptConfigurable, InterruptHandler},
18 peripherals::{APB_SARADC, Interrupt, LPWR, SENS},
19 rtc_cntl::WakeLock,
20 soc::regi2c,
21 system::{GenericPeripheralGuard, Peripheral},
22};
23
24mod calibration;
25
26pub(super) const NUM_ATTENS: usize = 10;
27
28cfg_select! {
29 esp32s2 => {
30 const ADC_VAL_MASK: u16 = 0x1fff;
31 }
32 esp32s3 => {
33 const ADC_VAL_MASK: u16 = 0xfff;
34 }
35}
36
37impl<ADCX> AdcConfig<ADCX>
38where
39 ADCX: RegisterAccess,
40{
41 pub fn adc_calibrate(atten: Attenuation) -> u16
43 where
44 ADCX: super::CalibrationAccess,
45 {
46 let _guard = GenericPeripheralGuard::<{ Peripheral::ApbSarAdc as u8 }>::new();
49 init_hardware::<ADCX>();
50
51 ADCX::enable_vdef(true);
52
53 ADCX::setup_calibration(atten);
55
56 ADCX::connect_gnd(true);
58
59 ADCX::calibration_init();
60 let cal_val = super::search_init_code::<ADCX>(|| {
61 ADCX::reset();
64 ADCX::start_sample();
65 while !ADCX::is_done() {}
66
67 ADCX::read_data() & ADCX::ADC_VAL_MASK
68 });
69 ADCX::reset();
70
71 ADCX::connect_gnd(false);
73
74 cal_val
75 }
76}
77
78fn init_hardware<ADCX: RegisterAccess>() {
82 let sensors = SENS::regs();
83
84 ADCX::clear_dig_force();
86 ADCX::set_start_force();
87 ADCX::set_en_pad_force();
88 sensors.sar_hall_ctrl().modify(|_, w| {
89 w.xpd_hall_force().set_bit();
90 w.hall_phase_force().set_bit()
91 });
92
93 cfg_select! {
95 esp32s2 => {
96 sensors
97 .sar_meas1_ctrl1()
98 .modify(|_, w| w.rtc_saradc_clkgate_en().set_bit());
99 }
100 _ => {
101 sensors
102 .sar_peri_clk_gate_conf()
103 .modify(|_, w| w.saradc_clk_en().set_bit());
104 }
105 }
106
107 sensors.sar_power_xpd_sar().modify(|_, w| unsafe {
108 w.sarclk_en().set_bit();
109 w.force_xpd_sar().bits(0b11)
110 });
111
112 ADCX::set_sar_clk_div();
113
114 sensors
116 .sar_meas1_ctrl1()
117 .modify(|_, w| unsafe { w.force_xpd_amp().bits(0b11) });
118 sensors.sar_amp_ctrl3().modify(|_, w| unsafe {
119 w.amp_rst_fb_fsm().bits(0);
120 w.amp_short_ref_fsm().bits(0);
121 w.amp_short_ref_gnd_fsm().bits(0)
122 });
123 sensors.sar_amp_ctrl1().modify(|_, w| unsafe {
124 w.sar_amp_wait1().bits(1);
125 w.sar_amp_wait2().bits(1)
126 });
127 sensors
128 .sar_amp_ctrl2()
129 .modify(|_, w| unsafe { w.sar_amp_wait3().bits(1) });
130}
131
132#[doc(hidden)]
133pub trait RegisterAccess {
134 fn set_attenuation(channel: usize, attenuation: u8);
135
136 fn clear_dig_force();
137
138 fn set_start_force();
139
140 fn set_en_pad_force();
141
142 fn set_en_pad(channel: u8);
143
144 fn clear_start_sample();
145
146 fn start_sample();
147
148 fn is_done() -> bool;
150
151 fn read_data() -> u16;
153
154 fn set_sar_clk_div();
158
159 fn calibration_init();
161
162 fn set_init_code(data: u16);
164
165 fn reset();
167}
168
169impl RegisterAccess for crate::peripherals::ADC1<'_> {
170 fn set_attenuation(channel: usize, attenuation: u8) {
171 SENS::regs().sar_atten1().modify(|r, w| {
172 let new_value = (r.bits() & !(0b11 << (channel * 2)))
173 | (((attenuation & 0b11) as u32) << (channel * 2));
174
175 unsafe { w.sar1_atten().bits(new_value) }
176 });
177 }
178
179 fn clear_dig_force() {
180 SENS::regs()
181 .sar_meas1_mux()
182 .modify(|_, w| w.sar1_dig_force().clear_bit());
183 }
184
185 fn set_start_force() {
186 SENS::regs()
187 .sar_meas1_ctrl2()
188 .modify(|_, w| w.meas1_start_force().set_bit());
189 }
190
191 fn set_en_pad_force() {
192 SENS::regs()
193 .sar_meas1_ctrl2()
194 .modify(|_, w| w.sar1_en_pad_force().set_bit());
195 }
196
197 fn set_en_pad(channel: u8) {
198 SENS::regs()
199 .sar_meas1_ctrl2()
200 .modify(|_, w| unsafe { w.sar1_en_pad().bits(1 << channel) });
201 }
202
203 fn clear_start_sample() {
204 SENS::regs()
205 .sar_meas1_ctrl2()
206 .modify(|_, w| w.meas1_start_sar().clear_bit());
207 }
208
209 fn start_sample() {
210 while meas1_busy() {}
213
214 SENS::regs()
215 .sar_meas1_ctrl2()
216 .modify(|_, w| w.meas1_start_sar().set_bit());
217 }
218
219 fn is_done() -> bool {
220 SENS::regs()
221 .sar_meas1_ctrl2()
222 .read()
223 .meas1_done_sar()
224 .bit_is_set()
225 }
226
227 fn read_data() -> u16 {
228 SENS::regs()
229 .sar_meas1_ctrl2()
230 .read()
231 .meas1_data_sar()
232 .bits()
233 }
234
235 fn set_sar_clk_div() {
236 SENS::regs().sar_reader1_ctrl().modify(|_, w| unsafe {
237 cfg_select! {
238 esp32s2 => w.sar1_clk_div().bits(1),
239 _ => w.sar_sar1_clk_div().bits(1),
240 }
241 });
242 }
243
244 fn calibration_init() {
245 regi2c::ADC_SAR1_DREF.write_field(4);
248 }
249
250 fn set_init_code(data: u16) {
251 let [msb, lsb] = data.to_be_bytes();
252
253 regi2c::ADC_SAR1_INITIAL_CODE_HIGH.write_field(msb);
254 regi2c::ADC_SAR1_INITIAL_CODE_LOW.write_field(lsb);
255 }
256
257 fn reset() {
258 let adc = APB_SARADC::regs();
259 let sensors = SENS::regs();
260
261 adc.int_clr().write(|w| w.adc1_done().clear_bit_by_one());
262 LPWR::regs()
263 .int_clr()
264 .write(|w| w.saradc1().clear_bit_by_one());
265
266 sensors
267 .sar_meas1_ctrl2()
268 .modify(|_, w| w.meas1_start_sar().clear_bit());
269 }
270}
271
272fn meas1_busy() -> bool {
273 let status = SENS::regs().sar_slave_addr1().read();
274 cfg_select! {
275 esp32s3 => status.sar_saradc_meas_status().bits() != 0,
276 _ => status.meas_status().bits() != 0,
277 }
278}
279
280impl super::CalibrationAccess for crate::peripherals::ADC1<'_> {
281 const ADC_VAL_MASK: u16 = ADC_VAL_MASK;
282
283 fn enable_vdef(enable: bool) {
284 regi2c::ADC_SAR1_DREF.write_field(enable as u8);
285 }
286
287 fn connect_gnd(enable: bool) {
288 regi2c::ADC_SAR1_ENCAL_GND.write_field(enable as u8);
289 }
290
291 fn setup_calibration(atten: Attenuation) {
292 SENS::regs()
295 .sar_meas1_ctrl2()
296 .modify(|_, w| unsafe { w.sar1_en_pad().bits(0) });
297 Self::set_attenuation(0, atten as u8);
298 }
299}
300
301impl RegisterAccess for crate::peripherals::ADC2<'_> {
302 fn set_attenuation(channel: usize, attenuation: u8) {
303 SENS::regs().sar_atten2().modify(|r, w| {
304 let new_value = (r.bits() & !(0b11 << (channel * 2)))
305 | (((attenuation & 0b11) as u32) << (channel * 2));
306
307 unsafe { w.sar2_atten().bits(new_value) }
308 });
309 }
310
311 fn clear_dig_force() {
312 SENS::regs()
313 .sar_meas2_mux()
314 .modify(|_, w| w.sar2_rtc_force().set_bit());
315
316 APB_SARADC::regs()
317 .arb_ctrl()
318 .modify(|_, w| w.rtc_force().set_bit());
319 }
320
321 fn set_start_force() {
322 SENS::regs()
323 .sar_meas2_ctrl2()
324 .modify(|_, w| w.meas2_start_force().set_bit());
325 }
326
327 fn set_en_pad_force() {
328 SENS::regs()
329 .sar_meas2_ctrl2()
330 .modify(|_, w| w.sar2_en_pad_force().set_bit());
331 }
332
333 fn set_en_pad(channel: u8) {
334 SENS::regs()
335 .sar_meas2_ctrl2()
336 .modify(|_, w| unsafe { w.sar2_en_pad().bits(1 << channel) });
337 }
338
339 fn clear_start_sample() {
340 SENS::regs()
341 .sar_meas2_ctrl2()
342 .modify(|_, w| w.meas2_start_sar().clear_bit());
343 }
344
345 fn start_sample() {
346 SENS::regs()
347 .sar_meas2_ctrl2()
348 .modify(|_, w| w.meas2_start_sar().set_bit());
349 }
350
351 fn is_done() -> bool {
352 SENS::regs()
353 .sar_meas2_ctrl2()
354 .read()
355 .meas2_done_sar()
356 .bit_is_set()
357 }
358
359 fn read_data() -> u16 {
360 SENS::regs()
361 .sar_meas2_ctrl2()
362 .read()
363 .meas2_data_sar()
364 .bits()
365 }
366
367 fn set_sar_clk_div() {
368 SENS::regs().sar_reader2_ctrl().modify(|_, w| unsafe {
369 cfg_select! {
370 esp32s2 => w.sar2_clk_div().bits(1),
371 _ => w.sar_sar2_clk_div().bits(1),
372 }
373 });
374 }
375
376 fn calibration_init() {
377 regi2c::ADC_SAR2_DREF.write_field(4);
378 }
379
380 fn set_init_code(data: u16) {
381 let [msb, lsb] = data.to_be_bytes();
382
383 regi2c::ADC_SAR2_INITIAL_CODE_HIGH.write_field(msb);
384 regi2c::ADC_SAR2_INITIAL_CODE_LOW.write_field(lsb);
385 }
386
387 fn reset() {
388 let adc = APB_SARADC::regs();
389 let sensors = SENS::regs();
390
391 adc.int_clr().write(|w| w.adc2_done().clear_bit_by_one());
392 LPWR::regs()
393 .int_clr()
394 .write(|w| w.saradc2().clear_bit_by_one());
395
396 sensors
397 .sar_meas2_ctrl2()
398 .modify(|_, w| w.meas2_start_sar().clear_bit());
399 }
400}
401
402impl super::CalibrationAccess for crate::peripherals::ADC2<'_> {
403 const ADC_VAL_MASK: u16 = ADC_VAL_MASK;
404
405 fn enable_vdef(enable: bool) {
406 regi2c::ADC_SAR2_DREF.write_field(enable as u8);
407 }
408
409 fn connect_gnd(enable: bool) {
410 regi2c::ADC_SAR2_ENCAL_GND.write_field(enable as u8);
411 }
412
413 fn setup_calibration(atten: Attenuation) {
414 SENS::regs()
415 .sar_meas2_ctrl2()
416 .modify(|_, w| unsafe { w.sar2_en_pad().bits(0) });
417 Self::set_attenuation(0, atten as u8);
418 }
419}
420
421pub struct Adc<'d, ADC, Dm: crate::DriverMode> {
423 _adc: ADC,
424 attenuations: [Option<Attenuation>; NUM_ATTENS],
425 init_codes: [u16; super::ATTENUATION_COUNT],
427 active_channel: Option<u8>,
428 _guard: GenericPeripheralGuard<{ Peripheral::ApbSarAdc as u8 }>,
429 _phantom: PhantomData<(Dm, &'d mut ())>,
430}
431
432impl<'d, ADCX> Adc<'d, ADCX, Blocking>
433where
434 ADCX: RegisterAccess + 'd,
435{
436 pub fn new(adc_instance: ADCX, config: AdcConfig<ADCX>) -> Result<Self, Error>
438 where
439 ADCX: super::AdcCalEfuse + super::CalibrationAccess,
440 {
441 let guard = GenericPeripheralGuard::new();
442
443 let attenuations = config.attenuations;
444
445 init_hardware::<ADCX>();
446
447 let init_codes = super::hw_init_codes::<ADCX>(&attenuations);
448
449 for (channel, attenuation) in attenuations.iter().enumerate() {
450 if let Some(attenuation) = attenuation {
451 ADCX::set_attenuation(channel, *attenuation as u8);
452 }
453 }
454
455 ADCX::reset();
458
459 Ok(Adc {
460 _adc: adc_instance,
461 attenuations,
462 init_codes,
463 active_channel: None,
464 _guard: guard,
465 _phantom: PhantomData,
466 })
467 }
468
469 pub fn into_async(mut self) -> Adc<'d, ADCX, Async> {
471 acquire_async_adc();
472 self.set_interrupt_handler(adc_interrupt_handler);
473
474 ADCX::reset();
477
478 Adc {
479 _adc: self._adc,
480 attenuations: self.attenuations,
481 init_codes: self.init_codes,
482 active_channel: self.active_channel,
483 _guard: self._guard,
484 _phantom: PhantomData,
485 }
486 }
487
488 pub fn read_blocking<PIN, CS>(&mut self, pin: &mut AdcPin<PIN, ADCX, CS>) -> Result<u16, Error>
496 where
497 PIN: AdcChannel,
498 CS: AdcCalScheme<ADCX>,
499 {
500 self.start_sample(pin)?;
501
502 while !ADCX::is_done() {}
504
505 let converted_value = ADCX::read_data();
507 ADCX::reset();
508
509 Ok(pin.cal_scheme.adc_val(converted_value))
511 }
512
513 pub fn read_oneshot<PIN, CS>(
524 &mut self,
525 pin: &mut super::AdcPin<PIN, ADCX, CS>,
526 ) -> nb::Result<u16, Error>
527 where
528 PIN: super::AdcChannel,
529 CS: super::AdcCalScheme<ADCX>,
530 {
531 if let Some(active_channel) = self.active_channel {
532 if active_channel != pin.pin.adc_channel() {
536 return Err(nb::Error::WouldBlock);
537 }
538 } else {
539 self.start_sample(pin).map_err(nb::Error::Other)?;
541 self.active_channel = Some(pin.pin.adc_channel());
542 }
543
544 let conversion_finished = ADCX::is_done();
546 if !conversion_finished {
547 return Err(nb::Error::WouldBlock);
548 }
549
550 let converted_value = ADCX::read_data();
552 ADCX::reset();
553
554 let converted_value = pin.cal_scheme.adc_val(converted_value);
556
557 self.active_channel = None;
559
560 Ok(converted_value)
561 }
562}
563
564fn adc_interrupt_sources() -> [Interrupt; 2] {
565 [Interrupt::APB_ADC, Interrupt::RTC_CORE]
569}
570
571impl<ADCX> crate::private::Sealed for Adc<'_, ADCX, Blocking> {}
572
573impl<ADCX> InterruptConfigurable for Adc<'_, ADCX, Blocking> {
574 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
575 for interrupt in adc_interrupt_sources() {
576 for core in crate::system::Cpu::other() {
577 crate::interrupt::disable(core, interrupt);
578 }
579 crate::interrupt::bind_handler(interrupt, handler);
580 }
581 }
582}
583
584impl<'d, ADCX, Dm> Adc<'d, ADCX, Dm>
585where
586 ADCX: RegisterAccess + 'd,
587 Dm: crate::DriverMode,
588{
589 fn start_sample<PIN, CS>(&mut self, pin: &mut AdcPin<PIN, ADCX, CS>) -> Result<(), Error>
590 where
591 PIN: AdcChannel,
592 CS: AdcCalScheme<ADCX>,
593 {
594 let channel = pin.pin.adc_channel();
595 let attenuation = super::channel_attenuation(&self.attenuations, channel)?;
596
597 ADCX::calibration_init();
600 ADCX::set_init_code(self.init_codes[attenuation as usize]);
601
602 ADCX::set_en_pad(channel);
603
604 ADCX::clear_start_sample();
605 ADCX::start_sample();
606
607 Ok(())
608 }
609}
610
611impl<'d, ADCX> Adc<'d, ADCX, Async>
612where
613 ADCX: RegisterAccess + 'd,
614{
615 pub fn into_blocking(self) -> Adc<'d, ADCX, Blocking> {
617 if release_async_adc() {
618 for interrupt in adc_interrupt_sources() {
620 for cpu in crate::system::Cpu::all() {
621 crate::interrupt::disable(cpu, interrupt);
622 }
623 }
624 }
625 Adc {
626 _adc: self._adc,
627 attenuations: self.attenuations,
628 init_codes: self.init_codes,
629 active_channel: self.active_channel,
630 _guard: self._guard,
631 _phantom: PhantomData,
632 }
633 }
634
635 pub async fn read_oneshot<PIN, CS>(
645 &mut self,
646 pin: &mut AdcPin<PIN, ADCX, CS>,
647 ) -> Result<u16, Error>
648 where
649 ADCX: Instance,
650 PIN: AdcChannel,
651 CS: AdcCalScheme<ADCX>,
652 {
653 self.start_sample(pin)?;
654
655 AdcFuture::new(self).await;
656
657 let converted_value = ADCX::read_data();
658 ADCX::reset();
659
660 Ok(pin.cal_scheme.adc_val(converted_value))
661 }
662}
663
664static ASYNC_ADC_COUNT: AtomicU32 = AtomicU32::new(0);
665
666fn acquire_async_adc() {
667 ASYNC_ADC_COUNT.fetch_add(1, Ordering::Relaxed);
668}
669
670fn release_async_adc() -> bool {
671 ASYNC_ADC_COUNT.fetch_sub(1, Ordering::Relaxed) == 1
672}
673
674#[handler]
675#[ram]
676fn adc_interrupt_handler() {
677 let apb_status = APB_SARADC::regs().int_st().read();
678 let rtc_status = LPWR::regs().int_st().read();
679
680 if apb_status.adc1_done().bit_is_set() || rtc_status.saradc1().bit_is_set() {
681 unsafe { handle_async(crate::peripherals::ADC1::steal()) }
682 }
683
684 if apb_status.adc2_done().bit_is_set() || rtc_status.saradc2().bit_is_set() {
685 unsafe { handle_async(crate::peripherals::ADC2::steal()) }
686 }
687}
688
689fn handle_async<ADCX: Instance>(_instance: ADCX) {
690 ADCX::clear_interrupt();
691 ADCX::unlisten();
692 ADCX::waker().wake();
693}
694
695pub trait Instance: crate::private::Sealed {
697 fn listen();
699
700 fn unlisten();
702
703 fn clear_interrupt();
705
706 fn waker() -> &'static AtomicWaker;
708}
709
710impl Instance for crate::peripherals::ADC1<'_> {
711 fn listen() {
712 APB_SARADC::regs()
713 .int_ena()
714 .modify(|_, w| w.adc1_done().set_bit());
715
716 SENS::regs().sar_reader1_ctrl().modify(|_, w| {
717 cfg_select! {
718 esp32s3 => w.sar_sar1_int_en().set_bit(),
719 _ => w.sar1_int_en().set_bit(),
720 }
721 });
722
723 LPWR::regs().int_ena().modify(|_, w| w.saradc1().set_bit());
724 }
725
726 fn unlisten() {
727 APB_SARADC::regs()
728 .int_ena()
729 .modify(|_, w| w.adc1_done().clear_bit());
730
731 SENS::regs().sar_reader1_ctrl().modify(|_, w| {
732 cfg_select! {
733 esp32s3 => w.sar_sar1_int_en().clear_bit(),
734 _ => w.sar1_int_en().clear_bit(),
735 }
736 });
737
738 LPWR::regs()
739 .int_ena()
740 .modify(|_, w| w.saradc1().clear_bit());
741 }
742
743 fn clear_interrupt() {
744 APB_SARADC::regs()
745 .int_clr()
746 .write(|w| w.adc1_done().clear_bit_by_one());
747 LPWR::regs()
748 .int_clr()
749 .write(|w| w.saradc1().clear_bit_by_one());
750 }
751
752 fn waker() -> &'static AtomicWaker {
753 static WAKER: AtomicWaker = AtomicWaker::new();
754
755 &WAKER
756 }
757}
758
759impl Instance for crate::peripherals::ADC2<'_> {
760 fn listen() {
761 APB_SARADC::regs()
762 .int_ena()
763 .modify(|_, w| w.adc2_done().set_bit());
764
765 SENS::regs().sar_reader2_ctrl().modify(|_, w| {
766 cfg_select! {
767 esp32s3 => w.sar_sar2_int_en().set_bit(),
768 _ => w.sar2_int_en().set_bit(),
769 }
770 });
771
772 LPWR::regs().int_ena().modify(|_, w| w.saradc2().set_bit());
773 }
774
775 fn unlisten() {
776 APB_SARADC::regs()
777 .int_ena()
778 .modify(|_, w| w.adc2_done().clear_bit());
779
780 SENS::regs().sar_reader2_ctrl().modify(|_, w| {
781 cfg_select! {
782 esp32s3 => w.sar_sar2_int_en().clear_bit(),
783 _ => w.sar2_int_en().clear_bit(),
784 }
785 });
786
787 LPWR::regs()
788 .int_ena()
789 .modify(|_, w| w.saradc2().clear_bit());
790 }
791
792 fn clear_interrupt() {
793 APB_SARADC::regs()
794 .int_clr()
795 .write(|w| w.adc2_done().clear_bit_by_one());
796 LPWR::regs()
797 .int_clr()
798 .write(|w| w.saradc2().clear_bit_by_one());
799 }
800
801 fn waker() -> &'static AtomicWaker {
802 static WAKER: AtomicWaker = AtomicWaker::new();
803
804 &WAKER
805 }
806}
807
808#[must_use = "futures do nothing unless you `.await` or poll them"]
809struct AdcFuture<ADCX: Instance> {
810 phantom: PhantomData<ADCX>,
811 _wake_lock: WakeLock,
812}
813
814impl<ADCX: Instance> AdcFuture<ADCX> {
815 fn new(_self: &Adc<'_, ADCX, Async>) -> Self {
816 ADCX::listen();
817 Self {
818 phantom: PhantomData,
819 _wake_lock: WakeLock::new(),
820 }
821 }
822}
823
824impl<ADCX: Instance + RegisterAccess> core::future::Future for AdcFuture<ADCX> {
825 type Output = ();
826
827 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
828 ADCX::waker().register(cx.waker());
829 if ADCX::is_done() {
830 ADCX::clear_interrupt();
831 Poll::Ready(())
832 } else {
833 Poll::Pending
834 }
835 }
836}
837
838impl<ADCX: Instance> Drop for AdcFuture<ADCX> {
839 fn drop(&mut self) {
840 ADCX::unlisten();
841 }
842}
843
844impl super::AdcCalEfuse for crate::peripherals::ADC1<'_> {
845 fn init_code(atten: Attenuation) -> Option<u16> {
846 crate::efuse::rtc_calib_init_code(AdcCalibUnit::ADC1, atten)
847 }
848
849 fn cal_mv(atten: Attenuation) -> Option<u16> {
850 crate::efuse::rtc_calib_cal_mv(AdcCalibUnit::ADC1, atten)
851 }
852
853 fn cal_code(atten: Attenuation) -> Option<u16> {
854 crate::efuse::rtc_calib_cal_code(AdcCalibUnit::ADC1, atten)
855 }
856}
857
858impl super::AdcCalEfuse for crate::peripherals::ADC2<'_> {
859 fn init_code(atten: Attenuation) -> Option<u16> {
860 crate::efuse::rtc_calib_init_code(AdcCalibUnit::ADC2, atten)
861 }
862
863 fn cal_mv(atten: Attenuation) -> Option<u16> {
864 crate::efuse::rtc_calib_cal_mv(AdcCalibUnit::ADC2, atten)
865 }
866
867 fn cal_code(atten: Attenuation) -> Option<u16> {
868 crate::efuse::rtc_calib_cal_code(AdcCalibUnit::ADC2, atten)
869 }
870}