Skip to main content

esp_hal/efuse/esp32s2/
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 the eFuse calibration data applies to.
9#[instability::unstable]
10pub enum AdcCalibUnit {
11    /// Selects efuse calibration data for ADC1.
12    ADC1,
13    /// Selects efuse calibration data for ADC2.
14    ADC2,
15}
16
17impl AdcCalibUnit {
18    fn index(self) -> u8 {
19        match self {
20            Self::ADC1 => 0,
21            Self::ADC2 => 1,
22        }
23    }
24}
25
26/// Parameter selected from the ESP32-S2 RTC calibration table
27#[derive(Clone, Copy)]
28#[instability::unstable]
29pub enum RtcCalibParam {
30    /// Low-voltage ADC reading (calibration v1)
31    Vlow,
32    /// High-voltage ADC reading
33    Vhigh,
34    /// Initial code (calibration v2)
35    Vinit,
36}
37
38struct RtcCalibEntry {
39    begin_bit: u16,
40    length: u8,
41    multiplier: i16,
42    base: i16,
43    depends: u8,
44}
45
46// See <https://github.com/espressif/esp-idf/blob/027613140/components/efuse/esp32s2/esp_efuse_rtc_table.c#L48-L89>
47const RTC_CALIB_MAP: [RtcCalibEntry; 33] = [
48    RtcCalibEntry {
49        begin_bit: 0,
50        length: 0,
51        multiplier: 0,
52        base: 0,
53        depends: 0,
54    },
55    // V1 low (tags 1-8)
56    RtcCalibEntry {
57        begin_bit: 208,
58        length: 6,
59        multiplier: 4,
60        base: 2231,
61        depends: 0,
62    },
63    RtcCalibEntry {
64        begin_bit: 214,
65        length: 6,
66        multiplier: 4,
67        base: 1643,
68        depends: 0,
69    },
70    RtcCalibEntry {
71        begin_bit: 220,
72        length: 6,
73        multiplier: 4,
74        base: 1290,
75        depends: 0,
76    },
77    RtcCalibEntry {
78        begin_bit: 226,
79        length: 6,
80        multiplier: 4,
81        base: 701,
82        depends: 0,
83    },
84    RtcCalibEntry {
85        begin_bit: 232,
86        length: 6,
87        multiplier: 4,
88        base: 2305,
89        depends: 0,
90    },
91    RtcCalibEntry {
92        begin_bit: 238,
93        length: 6,
94        multiplier: 4,
95        base: 1693,
96        depends: 0,
97    },
98    RtcCalibEntry {
99        begin_bit: 244,
100        length: 6,
101        multiplier: 4,
102        base: 1343,
103        depends: 0,
104    },
105    RtcCalibEntry {
106        begin_bit: 250,
107        length: 6,
108        multiplier: 4,
109        base: 723,
110        depends: 0,
111    },
112    // V1 high (tags 9-16)
113    RtcCalibEntry {
114        begin_bit: 144,
115        length: 8,
116        multiplier: 4,
117        base: 5775,
118        depends: 0,
119    },
120    RtcCalibEntry {
121        begin_bit: 152,
122        length: 8,
123        multiplier: 4,
124        base: 5693,
125        depends: 0,
126    },
127    RtcCalibEntry {
128        begin_bit: 160,
129        length: 8,
130        multiplier: 4,
131        base: 5723,
132        depends: 0,
133    },
134    RtcCalibEntry {
135        begin_bit: 168,
136        length: 8,
137        multiplier: 4,
138        base: 6209,
139        depends: 0,
140    },
141    RtcCalibEntry {
142        begin_bit: 176,
143        length: 8,
144        multiplier: 4,
145        base: 5817,
146        depends: 0,
147    },
148    RtcCalibEntry {
149        begin_bit: 184,
150        length: 8,
151        multiplier: 4,
152        base: 5703,
153        depends: 0,
154    },
155    RtcCalibEntry {
156        begin_bit: 192,
157        length: 8,
158        multiplier: 4,
159        base: 5731,
160        depends: 0,
161    },
162    RtcCalibEntry {
163        begin_bit: 200,
164        length: 8,
165        multiplier: 4,
166        base: 6157,
167        depends: 0,
168    },
169    // V2 high (tags 17-24)
170    RtcCalibEntry {
171        begin_bit: 197,
172        length: 6,
173        multiplier: 2,
174        base: 169,
175        depends: 19,
176    },
177    RtcCalibEntry {
178        begin_bit: 203,
179        length: 6,
180        multiplier: 2,
181        base: -26,
182        depends: 19,
183    },
184    RtcCalibEntry {
185        begin_bit: 209,
186        length: 9,
187        multiplier: 2,
188        base: 126,
189        depends: 22,
190    },
191    RtcCalibEntry {
192        begin_bit: 218,
193        length: 7,
194        multiplier: 2,
195        base: 387,
196        depends: 19,
197    },
198    RtcCalibEntry {
199        begin_bit: 225,
200        length: 7,
201        multiplier: 2,
202        base: 177,
203        depends: 22,
204    },
205    RtcCalibEntry {
206        begin_bit: 232,
207        length: 10,
208        multiplier: 2,
209        base: 5815,
210        depends: 0,
211    },
212    RtcCalibEntry {
213        begin_bit: 242,
214        length: 7,
215        multiplier: 2,
216        base: 27,
217        depends: 22,
218    },
219    RtcCalibEntry {
220        begin_bit: 249,
221        length: 7,
222        multiplier: 2,
223        base: 410,
224        depends: 22,
225    },
226    // V2 init (tags 25-32)
227    RtcCalibEntry {
228        begin_bit: 147,
229        length: 8,
230        multiplier: 2,
231        base: 1519,
232        depends: 0,
233    },
234    RtcCalibEntry {
235        begin_bit: 155,
236        length: 6,
237        multiplier: 2,
238        base: 88,
239        depends: 25,
240    },
241    RtcCalibEntry {
242        begin_bit: 161,
243        length: 5,
244        multiplier: 2,
245        base: 8,
246        depends: 26,
247    },
248    RtcCalibEntry {
249        begin_bit: 166,
250        length: 6,
251        multiplier: 2,
252        base: 70,
253        depends: 27,
254    },
255    RtcCalibEntry {
256        begin_bit: 172,
257        length: 8,
258        multiplier: 2,
259        base: 1677,
260        depends: 0,
261    },
262    RtcCalibEntry {
263        begin_bit: 180,
264        length: 6,
265        multiplier: 2,
266        base: 23,
267        depends: 29,
268    },
269    RtcCalibEntry {
270        begin_bit: 186,
271        length: 5,
272        multiplier: 2,
273        base: 6,
274        depends: 30,
275    },
276    RtcCalibEntry {
277        begin_bit: 191,
278        length: 6,
279        multiplier: 2,
280        base: 13,
281        depends: 31,
282    },
283];
284
285fn signed_bit_to_int(number: u32, len: u32) -> i32 {
286    if number >> (len - 1) != 0 {
287        -((number ^ (1 << (len - 1))) as i32)
288    } else {
289        number as i32
290    }
291}
292
293fn rtc_calib_tag(version: u8, unit: u8, atten: Attenuation, param: RtcCalibParam) -> Option<u8> {
294    let atten = atten as u8;
295    let offset = match (version, param) {
296        (1, RtcCalibParam::Vlow) => 1,
297        (1, RtcCalibParam::Vhigh) => 9,
298        (2, RtcCalibParam::Vhigh) => 17,
299        (2, RtcCalibParam::Vinit) => 25,
300        _ => return None,
301    };
302    Some(offset + unit * 4 + atten)
303}
304
305fn rtc_calib_parsed(tag: u8, skip_efuse: bool) -> i32 {
306    if tag == 0 {
307        return 0;
308    }
309    let entry = &RTC_CALIB_MAP[tag as usize];
310    let raw = if skip_efuse {
311        0
312    } else {
313        let field = crate::efuse::EfuseField::new(
314            2,
315            (entry.begin_bit as u32) / 32,
316            entry.begin_bit as u32,
317            entry.length as u32,
318        );
319        let bits = super::read_field_le::<u32>(field);
320        signed_bit_to_int(bits, entry.length as u32) * i32::from(entry.multiplier)
321    };
322    raw + i32::from(entry.base) + rtc_calib_parsed(entry.depends, skip_efuse)
323}
324
325/// Reads a parsed RTC calibration table value.
326///
327/// See <https://github.com/espressif/esp-idf/blob/027613140/components/efuse/esp32s2/esp_efuse_rtc_table.c#L145>
328#[instability::unstable]
329pub fn rtc_calib_reading(version: u8, unit: u8, atten: Attenuation, param: RtcCalibParam) -> i32 {
330    rtc_calib_reading_inner(version, unit, atten, param, false)
331}
332
333pub(crate) fn rtc_calib_reading_inner(
334    version: u8,
335    unit: u8,
336    atten: Attenuation,
337    param: RtcCalibParam,
338    skip_efuse: bool,
339) -> i32 {
340    rtc_calib_tag(version, unit, atten, param)
341        .map(|tag| rtc_calib_parsed(tag, skip_efuse))
342        .unwrap_or(0)
343}
344
345/// Returns the version of RTC calibration block.
346///
347/// See <https://github.com/espressif/esp-idf/blob/027613140/components/efuse/esp32s2/esp_efuse_rtc_table.c#L92>
348#[instability::unstable]
349pub fn rtc_calib_version() -> u8 {
350    super::read_field_le::<u8>(BLK_VERSION_MINOR)
351}
352
353/// Returns the ADC initial code for specified attenuation from efuse.
354#[instability::unstable]
355pub fn rtc_calib_init_code(unit: AdcCalibUnit, atten: Attenuation) -> Option<u16> {
356    if rtc_calib_version() != 2 {
357        return None;
358    }
359    Some(rtc_calib_reading(2, unit.index(), atten, RtcCalibParam::Vinit) as u16)
360}
361
362/// Returns the ADC reference point voltage for specified attenuation in millivolts.
363#[instability::unstable]
364pub fn rtc_calib_cal_mv(_unit: AdcCalibUnit, atten: Attenuation) -> u16 {
365    match atten {
366        Attenuation::_0dB => 600,
367        Attenuation::_2p5dB => 800,
368        Attenuation::_6dB => 1000,
369        Attenuation::_11dB => 2000,
370    }
371}
372
373/// Returns the ADC reference point digital code for specified attenuation.
374#[instability::unstable]
375pub fn rtc_calib_cal_code(unit: AdcCalibUnit, atten: Attenuation) -> Option<u16> {
376    if rtc_calib_version() != 2 {
377        return None;
378    }
379    Some(rtc_calib_reading(2, unit.index(), atten, RtcCalibParam::Vhigh) as u16)
380}
381
382/// Returns whether SPI boot encryption is enabled.
383#[instability::unstable]
384pub fn flash_encryption() -> bool {
385    !super::read_field_le::<u8>(SPI_BOOT_CRYPT_CNT)
386        .count_ones()
387        .is_multiple_of(2)
388}
389
390/// Returns the multiplier for the timeout value of the RWDT STAGE 0 register.
391#[instability::unstable]
392pub fn rwdt_multiplier() -> u8 {
393    super::read_field_le::<u8>(WDT_DELAY_SEL)
394}
395
396/// Returns the major hardware revision.
397#[instability::unstable]
398pub fn major_chip_version() -> u8 {
399    super::read_field_le(WAFER_VERSION_MAJOR)
400}
401
402/// Returns the minor hardware revision.
403#[instability::unstable]
404pub fn minor_chip_version() -> u8 {
405    super::read_field_le::<u8>(WAFER_VERSION_MINOR_HI) << 3
406        | super::read_field_le::<u8>(WAFER_VERSION_MINOR_LO)
407}
408
409#[derive(Debug, Clone, Copy, strum::FromRepr)]
410#[repr(u32)]
411pub(crate) enum EfuseBlock {
412    Block0,
413    Block1,
414    Block2,
415    Block3,
416    Block4,
417    Block5,
418    Block6,
419    Block7,
420    Block8,
421    Block9,
422    Block10,
423}
424
425impl EfuseBlock {
426    pub(crate) fn address(self) -> *const u32 {
427        let efuse = EFUSE::regs();
428        match self {
429            Self::Block0 => efuse.rd_wr_dis().as_ptr(),
430            Self::Block1 => efuse.rd_mac_spi_sys_0().as_ptr(),
431            Self::Block2 => efuse.rd_sys_data_part1_(0).as_ptr(),
432            Self::Block3 => efuse.rd_usr_data(0).as_ptr(),
433            Self::Block4 => efuse.rd_key0_data(0).as_ptr(),
434            Self::Block5 => efuse.rd_key1_data(0).as_ptr(),
435            Self::Block6 => efuse.rd_key2_data(0).as_ptr(),
436            Self::Block7 => efuse.rd_key3_data(0).as_ptr(),
437            Self::Block8 => efuse.rd_key4_data(0).as_ptr(),
438            Self::Block9 => efuse.rd_key5_data(0).as_ptr(),
439            Self::Block10 => efuse.rd_sys_data_part2_(0).as_ptr(),
440        }
441    }
442}