Skip to main content

esp_hal/efuse/esp32c2/
mod.rs

1use crate::{analog::adc::Attenuation, peripherals::EFUSE};
2
3#[cfg_attr(not(feature = "unstable"), allow(dead_code))]
4mod fields;
5#[instability::unstable]
6pub use fields::*;
7
8/// Selects which ADC we are interested in the efuse calibration data for
9#[instability::unstable]
10pub enum AdcCalibUnit {
11    /// Select efuse calibration data for ADC1
12    ADC1,
13}
14
15/// Get status of SPI boot encryption.
16#[instability::unstable]
17pub fn flash_encryption() -> bool {
18    !super::read_field_le::<u8>(SPI_BOOT_CRYPT_CNT)
19        .count_ones()
20        .is_multiple_of(2)
21}
22
23/// Get the multiplier for the timeout value of the RWDT STAGE 0 register.
24#[instability::unstable]
25pub fn rwdt_multiplier() -> u8 {
26    super::read_field_le::<u8>(WDT_DELAY_SEL)
27}
28
29/// Get efuse block version
30///
31/// see <https://github.com/espressif/esp-idf/blob/dc016f5987/components/hal/efuse_hal.c#L27-L30>
32#[instability::unstable]
33pub fn block_version() -> (u8, u8) {
34    // see <https://github.com/espressif/esp-idf/blob/dc016f5987/components/hal/esp32c2/include/hal/efuse_ll.h#L65-L73>
35    // <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c2/esp_efuse_table.csv#L90-L91>
36    (
37        super::read_field_le::<u8>(BLK_VERSION_MAJOR),
38        super::read_field_le::<u8>(BLK_VERSION_MINOR),
39    )
40}
41
42/// Get version of RTC calibration block
43///
44/// see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c2/esp_efuse_rtc_calib.c#L14>
45#[instability::unstable]
46pub fn rtc_calib_version() -> u8 {
47    let (major, _minor) = block_version();
48    if major == 0 { 1 } else { 0 }
49}
50
51/// Get ADC initial code for specified attenuation from efuse
52///
53/// see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c2/esp_efuse_rtc_calib.c#L27>
54#[instability::unstable]
55pub fn rtc_calib_init_code(_unit: AdcCalibUnit, atten: Attenuation) -> Option<u16> {
56    let version = rtc_calib_version();
57
58    if version != 1 {
59        return None;
60    }
61
62    // see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c2/esp_efuse_table.csv#L94>
63    let diff_code0: u16 = super::read_field_le(ADC1_INIT_CODE_ATTEN0);
64    let code0 = if diff_code0 & (1 << 7) != 0 {
65        2160 - (diff_code0 & 0x7f)
66    } else {
67        2160 + diff_code0
68    };
69
70    if matches!(atten, Attenuation::_0dB) {
71        return Some(code0);
72    }
73
74    // see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c2/esp_efuse_table.csv#L95>
75    let diff_code11: u16 = super::read_field_le(ADC1_INIT_CODE_ATTEN3);
76    let code11 = code0 + diff_code11;
77
78    Some(code11)
79}
80
81/// Get ADC reference point voltage for specified attenuation in millivolts
82///
83/// see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c2/esp_efuse_rtc_calib.c#L65>
84#[instability::unstable]
85pub fn rtc_calib_cal_mv(_unit: AdcCalibUnit, atten: Attenuation) -> u16 {
86    match atten {
87        Attenuation::_0dB => 400,
88        Attenuation::_11dB => 1370,
89        _ => panic!("Unsupported attenuation"),
90    }
91}
92
93/// Get ADC reference point digital code for specified attenuation
94///
95/// see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c2/esp_efuse_rtc_calib.c#L65>
96#[instability::unstable]
97pub fn rtc_calib_cal_code(_unit: AdcCalibUnit, atten: Attenuation) -> Option<u16> {
98    let version = rtc_calib_version();
99
100    if version != 1 {
101        return None;
102    }
103
104    // see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c2/esp_efuse_table.csv#L96>
105    let diff_code0: u16 = super::read_field_le(ADC1_CAL_VOL_ATTEN0);
106    let code0 = if diff_code0 & (1 << 7) != 0 {
107        1540 - (diff_code0 & 0x7f)
108    } else {
109        1540 + diff_code0
110    };
111
112    if matches!(atten, Attenuation::_0dB) {
113        return Some(code0);
114    }
115
116    // see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c2/esp_efuse_table.csv#L97>
117    let diff_code11: u16 = super::read_field_le(ADC1_CAL_VOL_ATTEN3);
118    let code11 = if diff_code0 & (1 << 5) != 0 {
119        code0 - (diff_code11 & 0x1f)
120    } else {
121        code0 + diff_code11
122    } - 123;
123
124    Some(code11)
125}
126
127/// Returns the major hardware revision
128#[instability::unstable]
129pub fn major_chip_version() -> u8 {
130    super::read_field_le(WAFER_VERSION_MAJOR)
131}
132
133/// Returns the minor hardware revision
134#[instability::unstable]
135pub fn minor_chip_version() -> u8 {
136    super::read_field_le(WAFER_VERSION_MINOR)
137}
138
139#[derive(Debug, Clone, Copy, strum::FromRepr)]
140#[repr(u32)]
141pub(crate) enum EfuseBlock {
142    Block0,
143    Block1,
144    Block2,
145    Block3,
146}
147
148impl EfuseBlock {
149    pub(crate) fn address(self) -> *const u32 {
150        let efuse = EFUSE::regs();
151        match self {
152            Self::Block0 => efuse.rd_wr_dis().as_ptr(),
153            Self::Block1 => efuse.rd_blk1_data0().as_ptr(),
154            Self::Block2 => efuse.rd_blk2_data0().as_ptr(),
155            Self::Block3 => efuse.rd_blk3_data0().as_ptr(),
156        }
157    }
158}