esp_hal/efuse/esp32c6/
mod.rs

1use crate::{analog::adc::Attenuation, peripherals::EFUSE};
2
3mod fields;
4pub use fields::*;
5
6/// Selects which ADC we are interested in the efuse calibration data for
7pub enum AdcCalibUnit {
8    /// Select efuse calibration data for ADC1
9    ADC1,
10    /// Select efuse calibration data for ADC2
11    ADC2,
12}
13
14impl super::Efuse {
15    /// Get status of SPI boot encryption.
16    pub fn flash_encryption() -> bool {
17        !Self::read_field_le::<u8>(SPI_BOOT_CRYPT_CNT)
18            .count_ones()
19            .is_multiple_of(2)
20    }
21
22    /// Get the multiplier for the timeout value of the RWDT STAGE 0 register.
23    pub fn rwdt_multiplier() -> u8 {
24        Self::read_field_le::<u8>(WDT_DELAY_SEL)
25    }
26
27    /// Get efuse block version
28    ///
29    /// see <https://github.com/espressif/esp-idf/blob/dc016f5987/components/hal/efuse_hal.c#L27-L30>
30    pub fn block_version() -> (u8, u8) {
31        // see <https://github.com/espressif/esp-idf/blob/dc016f5987/components/hal/esp32c6/include/hal/efuse_ll.h#L65-L73>
32        // <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c6/esp_efuse_table.csv#L156>
33        (
34            Self::read_field_le::<u8>(BLK_VERSION_MAJOR),
35            Self::read_field_le::<u8>(BLK_VERSION_MINOR),
36        )
37    }
38
39    /// Get version of RTC calibration block
40    ///
41    /// see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c6/esp_efuse_rtc_calib.c#L20>
42    pub fn rtc_calib_version() -> u8 {
43        let (_major, minor) = Self::block_version();
44        if minor >= 1 { 1 } else { 0 }
45    }
46
47    /// Get ADC initial code for specified attenuation from efuse
48    ///
49    /// see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c6/esp_efuse_rtc_calib.c#L32>
50    pub fn rtc_calib_init_code(_unit: AdcCalibUnit, atten: Attenuation) -> Option<u16> {
51        let version = Self::rtc_calib_version();
52
53        if version != 1 {
54            return None;
55        }
56
57        // See <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c6/esp_efuse_table.csv#L147-L152>
58        let init_code: u16 = Self::read_field_le(match atten {
59            Attenuation::_0dB => ADC1_INIT_CODE_ATTEN0,
60            Attenuation::_2p5dB => ADC1_INIT_CODE_ATTEN1,
61            Attenuation::_6dB => ADC1_INIT_CODE_ATTEN2,
62            Attenuation::_11dB => ADC1_INIT_CODE_ATTEN3,
63        });
64
65        Some(init_code + 1600) // version 1 logic
66    }
67
68    /// Get ADC reference point voltage for specified attenuation in millivolts
69    ///
70    /// see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c6/esp_efuse_rtc_calib.c#L42>
71    pub fn rtc_calib_cal_mv(_unit: AdcCalibUnit, atten: Attenuation) -> u16 {
72        match atten {
73            Attenuation::_0dB => 400,
74            Attenuation::_2p5dB => 550,
75            Attenuation::_6dB => 750,
76            Attenuation::_11dB => 1370,
77        }
78    }
79
80    /// Get ADC reference point digital code for specified attenuation
81    ///
82    /// see <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c6/esp_efuse_rtc_calib.c#L42>
83    pub fn rtc_calib_cal_code(_unit: AdcCalibUnit, atten: Attenuation) -> Option<u16> {
84        let version = Self::rtc_calib_version();
85
86        if version != 1 {
87            return None;
88        }
89
90        // See <https://github.com/espressif/esp-idf/blob/903af13e8/components/efuse/esp32c6/esp_efuse_table.csv#L153-L156>
91        let cal_code: u16 = Self::read_field_le(match atten {
92            Attenuation::_0dB => ADC1_CAL_VOL_ATTEN0,
93            Attenuation::_2p5dB => ADC1_CAL_VOL_ATTEN1,
94            Attenuation::_6dB => ADC1_CAL_VOL_ATTEN2,
95            Attenuation::_11dB => ADC1_CAL_VOL_ATTEN3,
96        });
97
98        let cal_code = if cal_code & (1 << 9) != 0 {
99            1500 - (cal_code & !(1 << 9))
100        } else {
101            1500 + cal_code
102        };
103
104        Some(cal_code)
105    }
106
107    /// Returns the major hardware revision
108    pub fn major_chip_version() -> u8 {
109        Self::read_field_le(WAFER_VERSION_MAJOR)
110    }
111
112    /// Returns the minor hardware revision
113    pub fn minor_chip_version() -> u8 {
114        Self::read_field_le(WAFER_VERSION_MINOR)
115    }
116}
117
118#[derive(Debug, Clone, Copy, strum::FromRepr)]
119#[repr(u32)]
120pub(crate) enum EfuseBlock {
121    Block0,
122    Block1,
123    Block2,
124    Block3,
125    Block4,
126    Block5,
127    Block6,
128    Block7,
129    Block8,
130    Block9,
131    Block10,
132}
133
134impl EfuseBlock {
135    pub(crate) fn address(self) -> *const u32 {
136        let efuse = EFUSE::regs();
137        match self {
138            Self::Block0 => efuse.rd_wr_dis().as_ptr(),
139            Self::Block1 => efuse.rd_mac_spi_sys_0().as_ptr(),
140            Self::Block2 => efuse.rd_sys_part1_data0().as_ptr(),
141            Self::Block3 => efuse.rd_usr_data0().as_ptr(),
142            Self::Block4 => efuse.rd_key0_data0().as_ptr(),
143            Self::Block5 => efuse.rd_key1_data0().as_ptr(),
144            Self::Block6 => efuse.rd_key2_data0().as_ptr(),
145            Self::Block7 => efuse.rd_key3_data0().as_ptr(),
146            Self::Block8 => efuse.rd_key4_data0().as_ptr(),
147            Self::Block9 => efuse.rd_key5_data0().as_ptr(),
148            Self::Block10 => efuse.rd_sys_part2_data0().as_ptr(),
149        }
150    }
151}