Skip to content

Commit 7cd7186

Browse files
ervanalbbugadani
andauthored
Don't use ADC2 efuse calibration parameters for ADC1, and write appropriate DREF values (#4286)
* Switch rtc_calib_init_code and friends to use an enum to select an ADC, instead of a u8 * Write to SAR1_DREF / SAR2_DREF before writing initial code * Update esp-hal/CHANGELOG.md Co-authored-by: Dániel Buga <[email protected]> --------- Co-authored-by: Dániel Buga <[email protected]>
1 parent 4e585ca commit 7cd7186

File tree

8 files changed

+125
-49
lines changed

8 files changed

+125
-49
lines changed

esp-hal/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
105105
- TWAI: Fixed receive_async erroneously returning RX FIFO overrun errors (#4244)
106106
- Subtracting Instant values with large difference no longer panics (#4249)
107107
- ADC: Fixed integer overflow in curve calibration polynomial evaluation (#4240)
108+
- ADC: Fixed bug where ADC1 would use ADC2 efuse calibration data (#4286)
108109
- RMT: `Channel::transmit_continuously` also triggers the loopcount interrupt when only using a single repetition. (#4260)
109110
- I2C: Fix position of SDA sampling point (#4268)
110111

esp-hal/src/analog/adc/riscv.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use procmacros::handler;
2121
pub use self::calibration::*;
2222
use super::{AdcCalSource, AdcConfig, Attenuation};
2323
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2))]
24-
use crate::efuse::Efuse;
24+
use crate::efuse::{AdcCalibUnit, Efuse};
2525
use crate::{
2626
Async,
2727
Blocking,
@@ -88,6 +88,7 @@ where
8888
// Connect calibration source
8989
ADCI::connect_cal(source, true);
9090

91+
ADCI::calibration_init();
9192
for _ in 0..ADC_CAL_CNT_MAX {
9293
ADCI::set_init_code(0);
9394

@@ -132,6 +133,9 @@ pub trait RegisterAccess {
132133
/// Reset flags
133134
fn reset();
134135

136+
/// Set up ADC hardware for calibration
137+
fn calibration_init();
138+
135139
/// Set calibration parameter to ADC hardware
136140
fn set_init_code(data: u16);
137141
}
@@ -177,6 +181,16 @@ impl RegisterAccess for crate::peripherals::ADC1<'_> {
177181
.modify(|_, w| w.onetime_start().clear_bit());
178182
}
179183

184+
// Currently #[cfg] covers all supported RISC-V devices,
185+
// but, for example, esp32p4 uses the value 4 instead of 1,
186+
// so it is not standard across all RISC-V devices.
187+
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2))]
188+
fn calibration_init() {
189+
// e.g.
190+
// https://github.com/espressif/esp-idf/blob/800f141f94c0f880c162de476512e183df671307/components/hal/esp32c3/include/hal/adc_ll.h#L702
191+
regi2c::ADC_SAR1_DREF.write_field(1);
192+
}
193+
180194
fn set_init_code(data: u16) {
181195
let [msb, lsb] = data.to_be_bytes();
182196

@@ -249,6 +263,11 @@ impl RegisterAccess for crate::peripherals::ADC2<'_> {
249263
.modify(|_, w| w.onetime_start().clear_bit());
250264
}
251265

266+
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2))]
267+
fn calibration_init() {
268+
regi2c::ADC_SAR2_DREF.write_field(1);
269+
}
270+
252271
fn set_init_code(data: u16) {
253272
let [msb, lsb] = data.to_be_bytes();
254273

@@ -360,6 +379,7 @@ where
360379
self.active_channel = Some(pin.pin.adc_channel());
361380

362381
// Set ADC unit calibration according used scheme for pin
382+
ADCI::calibration_init();
363383
ADCI::set_init_code(pin.cal_scheme.adc_cal());
364384

365385
let channel = self.active_channel.unwrap();
@@ -424,30 +444,30 @@ impl<ADCI> InterruptConfigurable for Adc<'_, ADCI, Blocking> {
424444
#[cfg(adc_adc1)]
425445
impl super::AdcCalEfuse for crate::peripherals::ADC1<'_> {
426446
fn init_code(atten: Attenuation) -> Option<u16> {
427-
Efuse::rtc_calib_init_code(1, atten)
447+
Efuse::rtc_calib_init_code(AdcCalibUnit::ADC1, atten)
428448
}
429449

430450
fn cal_mv(atten: Attenuation) -> u16 {
431-
Efuse::rtc_calib_cal_mv(1, atten)
451+
Efuse::rtc_calib_cal_mv(AdcCalibUnit::ADC1, atten)
432452
}
433453

434454
fn cal_code(atten: Attenuation) -> Option<u16> {
435-
Efuse::rtc_calib_cal_code(1, atten)
455+
Efuse::rtc_calib_cal_code(AdcCalibUnit::ADC1, atten)
436456
}
437457
}
438458

439459
#[cfg(adc_adc2)]
440460
impl super::AdcCalEfuse for crate::peripherals::ADC2<'_> {
441461
fn init_code(atten: Attenuation) -> Option<u16> {
442-
Efuse::rtc_calib_init_code(2, atten)
462+
Efuse::rtc_calib_init_code(AdcCalibUnit::ADC2, atten)
443463
}
444464

445465
fn cal_mv(atten: Attenuation) -> u16 {
446-
Efuse::rtc_calib_cal_mv(2, atten)
466+
Efuse::rtc_calib_cal_mv(AdcCalibUnit::ADC2, atten)
447467
}
448468

449469
fn cal_code(atten: Attenuation) -> Option<u16> {
450-
Efuse::rtc_calib_cal_code(2, atten)
470+
Efuse::rtc_calib_cal_code(AdcCalibUnit::ADC2, atten)
451471
}
452472
}
453473

@@ -489,6 +509,7 @@ where
489509
}
490510

491511
// Set ADC unit calibration according used scheme for pin
512+
ADCI::calibration_init();
492513
ADCI::set_init_code(pin.cal_scheme.adc_cal());
493514

494515
let attenuation = self.attenuations[channel as usize].unwrap() as u8;

esp-hal/src/analog/adc/xtensa.rs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use core::marker::PhantomData;
44
pub use self::calibration::*;
55
use super::{AdcCalScheme, AdcCalSource, AdcChannel, AdcConfig, AdcPin, Attenuation};
66
#[cfg(esp32s3)]
7-
use crate::efuse::Efuse;
7+
use crate::efuse::{AdcCalibUnit, Efuse};
88
use crate::{
99
peripherals::{APB_SARADC, SENS},
1010
soc::regi2c,
@@ -55,6 +55,7 @@ where
5555
// Connect calibration source
5656
ADCI::connect_cal(source, true);
5757

58+
ADCI::calibration_init();
5859
ADCI::set_init_code(0);
5960

6061
for _ in 0..ADCI::ADC_CAL_CNT_MAX {
@@ -105,6 +106,9 @@ pub trait RegisterAccess {
105106
/// Read sample data
106107
fn read_data() -> u16;
107108

109+
/// Set up ADC hardware for calibration
110+
fn calibration_init();
111+
108112
/// Set calibration parameter to ADC hardware
109113
fn set_init_code(data: u16);
110114

@@ -174,6 +178,13 @@ impl RegisterAccess for crate::peripherals::ADC1<'_> {
174178
.bits()
175179
}
176180

181+
#[cfg(any(esp32s2, esp32s3))]
182+
fn calibration_init() {
183+
// https://github.com/espressif/esp-idf/blob/800f141f94c0f880c162de476512e183df671307/components/hal/esp32s3/include/hal/adc_ll.h#L833
184+
// https://github.com/espressif/esp-idf/blob/800f141f94c0f880c162de476512e183df671307/components/hal/esp32s2/include/hal/adc_ll.h#L1145
185+
regi2c::ADC_SAR1_DREF.write_field(4);
186+
}
187+
177188
fn set_init_code(data: u16) {
178189
let [msb, lsb] = data.to_be_bytes();
179190

@@ -277,6 +288,11 @@ impl RegisterAccess for crate::peripherals::ADC2<'_> {
277288
.bits()
278289
}
279290

291+
#[cfg(any(esp32s2, esp32s3))]
292+
fn calibration_init() {
293+
regi2c::ADC_SAR2_DREF.write_field(4);
294+
}
295+
280296
fn set_init_code(data: u16) {
281297
let [msb, lsb] = data.to_be_bytes();
282298

@@ -478,6 +494,7 @@ where
478494
// Set ADC unit calibration according used scheme for pin
479495
let init_code = pin.cal_scheme.adc_cal();
480496
if self.last_init_code != init_code {
497+
ADCI::calibration_init();
481498
ADCI::set_init_code(init_code);
482499
self.last_init_code = init_code;
483500
}
@@ -492,29 +509,29 @@ where
492509
#[cfg(esp32s3)]
493510
impl super::AdcCalEfuse for crate::peripherals::ADC1<'_> {
494511
fn init_code(atten: Attenuation) -> Option<u16> {
495-
Efuse::rtc_calib_init_code(1, atten)
512+
Efuse::rtc_calib_init_code(AdcCalibUnit::ADC1, atten)
496513
}
497514

498515
fn cal_mv(atten: Attenuation) -> u16 {
499-
Efuse::rtc_calib_cal_mv(1, atten)
516+
Efuse::rtc_calib_cal_mv(AdcCalibUnit::ADC1, atten)
500517
}
501518

502519
fn cal_code(atten: Attenuation) -> Option<u16> {
503-
Efuse::rtc_calib_cal_code(1, atten)
520+
Efuse::rtc_calib_cal_code(AdcCalibUnit::ADC1, atten)
504521
}
505522
}
506523

507524
#[cfg(esp32s3)]
508525
impl super::AdcCalEfuse for crate::peripherals::ADC2<'_> {
509526
fn init_code(atten: Attenuation) -> Option<u16> {
510-
Efuse::rtc_calib_init_code(2, atten)
527+
Efuse::rtc_calib_init_code(AdcCalibUnit::ADC2, atten)
511528
}
512529

513530
fn cal_mv(atten: Attenuation) -> u16 {
514-
Efuse::rtc_calib_cal_mv(2, atten)
531+
Efuse::rtc_calib_cal_mv(AdcCalibUnit::ADC2, atten)
515532
}
516533

517534
fn cal_code(atten: Attenuation) -> Option<u16> {
518-
Efuse::rtc_calib_cal_code(2, atten)
535+
Efuse::rtc_calib_cal_code(AdcCalibUnit::ADC2, atten)
519536
}
520537
}

esp-hal/src/efuse/esp32c2/mod.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ use crate::{analog::adc::Attenuation, peripherals::EFUSE};
33
mod fields;
44
pub use fields::*;
55

6+
/// Selects which ADC we are interested in the efuse calibration data for
7+
pub enum AdcCalibUnit {
8+
/// Select efuse calibration data for ADC1
9+
ADC1,
10+
}
11+
612
impl super::Efuse {
713
/// Get status of SPI boot encryption.
814
pub fn flash_encryption() -> bool {
@@ -39,7 +45,7 @@ impl super::Efuse {
3945
/// Get ADC initial code for specified attenuation from efuse
4046
///
4147
/// see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c2/esp_efuse_rtc_calib.c#L27>
42-
pub fn rtc_calib_init_code(_unit: u8, atten: Attenuation) -> Option<u16> {
48+
pub fn rtc_calib_init_code(_unit: AdcCalibUnit, atten: Attenuation) -> Option<u16> {
4349
let version = Self::rtc_calib_version();
4450

4551
if version != 1 {
@@ -68,7 +74,7 @@ impl super::Efuse {
6874
/// Get ADC reference point voltage for specified attenuation in millivolts
6975
///
7076
/// see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c2/esp_efuse_rtc_calib.c#L65>
71-
pub fn rtc_calib_cal_mv(_unit: u8, atten: Attenuation) -> u16 {
77+
pub fn rtc_calib_cal_mv(_unit: AdcCalibUnit, atten: Attenuation) -> u16 {
7278
match atten {
7379
Attenuation::_0dB => 400,
7480
Attenuation::_11dB => 1370,
@@ -78,7 +84,7 @@ impl super::Efuse {
7884
/// Get ADC reference point digital code for specified attenuation
7985
///
8086
/// see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c2/esp_efuse_rtc_calib.c#L65>
81-
pub fn rtc_calib_cal_code(_unit: u8, atten: Attenuation) -> Option<u16> {
87+
pub fn rtc_calib_cal_code(_unit: AdcCalibUnit, atten: Attenuation) -> Option<u16> {
8288
let version = Self::rtc_calib_version();
8389

8490
if version != 1 {

esp-hal/src/efuse/esp32c3/mod.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ use crate::{analog::adc::Attenuation, peripherals::EFUSE};
33
mod fields;
44
pub use fields::*;
55

6+
/// Selects which ADC we are interested in the efuse calibration data for
7+
pub enum AdcCalibUnit {
8+
/// Select efuse calibration data for ADC1
9+
ADC1,
10+
/// Select efuse calibration data for ADC2
11+
ADC2,
12+
}
13+
614
impl super::Efuse {
715
/// Get status of SPI boot encryption.
816
pub fn flash_encryption() -> bool {
@@ -40,7 +48,7 @@ impl super::Efuse {
4048
/// Get ADC initial code for specified attenuation from efuse
4149
///
4250
/// see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c3/esp_efuse_rtc_calib.c#L25>
43-
pub fn rtc_calib_init_code(_unit: u8, atten: Attenuation) -> Option<u16> {
51+
pub fn rtc_calib_init_code(_unit: AdcCalibUnit, atten: Attenuation) -> Option<u16> {
4452
let version = Self::rtc_calib_version();
4553

4654
if version != 1 {
@@ -61,7 +69,7 @@ impl super::Efuse {
6169
/// Get ADC reference point voltage for specified attenuation in millivolts
6270
///
6371
/// see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c3/esp_efuse_rtc_calib.c#L49>
64-
pub fn rtc_calib_cal_mv(_unit: u8, atten: Attenuation) -> u16 {
72+
pub fn rtc_calib_cal_mv(_unit: AdcCalibUnit, atten: Attenuation) -> u16 {
6573
match atten {
6674
Attenuation::_0dB => 400,
6775
Attenuation::_2p5dB => 550,
@@ -73,7 +81,7 @@ impl super::Efuse {
7381
/// Get ADC reference point digital code for specified attenuation
7482
///
7583
/// see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c3/esp_efuse_rtc_calib.c#L49>
76-
pub fn rtc_calib_cal_code(_unit: u8, atten: Attenuation) -> Option<u16> {
84+
pub fn rtc_calib_cal_code(_unit: AdcCalibUnit, atten: Attenuation) -> Option<u16> {
7785
let version = Self::rtc_calib_version();
7886

7987
if version != 1 {

esp-hal/src/efuse/esp32c6/mod.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ use crate::{analog::adc::Attenuation, peripherals::EFUSE};
33
mod fields;
44
pub use fields::*;
55

6+
/// Selects which ADC we are interested in the efuse calibration data for
7+
pub enum AdcCalibUnit {
8+
/// Select efuse calibration data for ADC1
9+
ADC1,
10+
/// Select efuse calibration data for ADC2
11+
ADC2,
12+
}
13+
614
impl super::Efuse {
715
/// Get status of SPI boot encryption.
816
pub fn flash_encryption() -> bool {
@@ -39,7 +47,7 @@ impl super::Efuse {
3947
/// Get ADC initial code for specified attenuation from efuse
4048
///
4149
/// see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c6/esp_efuse_rtc_calib.c#L32>
42-
pub fn rtc_calib_init_code(_unit: u8, atten: Attenuation) -> Option<u16> {
50+
pub fn rtc_calib_init_code(_unit: AdcCalibUnit, atten: Attenuation) -> Option<u16> {
4351
let version = Self::rtc_calib_version();
4452

4553
if version != 1 {
@@ -60,7 +68,7 @@ impl super::Efuse {
6068
/// Get ADC reference point voltage for specified attenuation in millivolts
6169
///
6270
/// see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c6/esp_efuse_rtc_calib.c#L42>
63-
pub fn rtc_calib_cal_mv(_unit: u8, atten: Attenuation) -> u16 {
71+
pub fn rtc_calib_cal_mv(_unit: AdcCalibUnit, atten: Attenuation) -> u16 {
6472
match atten {
6573
Attenuation::_0dB => 400,
6674
Attenuation::_2p5dB => 550,
@@ -72,7 +80,7 @@ impl super::Efuse {
7280
/// Get ADC reference point digital code for specified attenuation
7381
///
7482
/// see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c6/esp_efuse_rtc_calib.c#L42>
75-
pub fn rtc_calib_cal_code(_unit: u8, atten: Attenuation) -> Option<u16> {
83+
pub fn rtc_calib_cal_code(_unit: AdcCalibUnit, atten: Attenuation) -> Option<u16> {
7684
let version = Self::rtc_calib_version();
7785

7886
if version != 1 {

esp-hal/src/efuse/esp32h2/mod.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ use crate::{analog::adc::Attenuation, peripherals::EFUSE};
33
mod fields;
44
pub use fields::*;
55

6+
/// Selects which ADC we are interested in the efuse calibration data for
7+
pub enum AdcCalibUnit {
8+
/// Select efuse calibration data for ADC1
9+
ADC1,
10+
}
11+
612
impl super::Efuse {
713
/// Get status of SPI boot encryption.
814
pub fn flash_encryption() -> bool {
@@ -38,7 +44,7 @@ impl super::Efuse {
3844
/// Get ADC initial code for specified attenuation from efuse
3945
///
4046
/// See: <https://github.com/espressif/esp-idf/blob/be06a6f/components/efuse/esp32h2/esp_efuse_rtc_calib.c#L33>
41-
pub fn rtc_calib_init_code(_unit: u8, atten: Attenuation) -> Option<u16> {
47+
pub fn rtc_calib_init_code(_unit: AdcCalibUnit, atten: Attenuation) -> Option<u16> {
4248
let version = Self::rtc_calib_version();
4349

4450
if version > 4 {
@@ -59,7 +65,7 @@ impl super::Efuse {
5965
/// Get ADC reference point voltage for specified attenuation in millivolts
6066
///
6167
/// See: <https://github.com/espressif/esp-idf/blob/be06a6f/components/efuse/esp32h2/esp_efuse_rtc_calib.c#L91>
62-
pub fn rtc_calib_cal_mv(_unit: u8, atten: Attenuation) -> u16 {
68+
pub fn rtc_calib_cal_mv(_unit: AdcCalibUnit, atten: Attenuation) -> u16 {
6369
const INPUT_VOUT_MV: [[u16; 4]; 1] = [
6470
[750, 1000, 1500, 2800], // Calibration V1 coefficients
6571
];
@@ -83,7 +89,7 @@ impl super::Efuse {
8389
/// Returns the call code
8490
///
8591
/// See: <https://github.com/espressif/esp-idf/blob/17a2461297076481858b7f76482676a521cc727a/components/efuse/esp32h2/esp_efuse_rtc_calib.c#L91>
86-
pub fn rtc_calib_cal_code(_unit: u8, atten: Attenuation) -> Option<u16> {
92+
pub fn rtc_calib_cal_code(_unit: AdcCalibUnit, atten: Attenuation) -> Option<u16> {
8793
let cal_code: u16 = Self::read_field_le(match atten {
8894
Attenuation::_0dB => ADC1_HI_DOUT_ATTEN0,
8995
Attenuation::_2p5dB => ADC1_HI_DOUT_ATTEN1,

0 commit comments

Comments
 (0)