diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index b029e2506..66ea89961 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Make `DmaDescriptor` methods public (#2237) - Added a way to configure watchdogs in `esp_hal::init` (#2180) - Implement `embedded_hal_async::delay::DelayNs` for `TIMGx` timers (#2084) +- Added `Efuse::read_bit` (#2259) ### Changed @@ -78,6 +79,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - TWAI on ESP32 (#2207) - TWAI should no longer panic when receiving a non-compliant frame (#2255) - OneShotTimer: fixed `delay_nanos` behaviour (#2256) +- Fixed unsoundness around `Efuse` (#2259) ### Removed diff --git a/esp-hal/MIGRATING-0.20.md b/esp-hal/MIGRATING-0.20.md index ea03064eb..37b29e6bd 100644 --- a/esp-hal/MIGRATING-0.20.md +++ b/esp-hal/MIGRATING-0.20.md @@ -255,3 +255,7 @@ Diff of the `psram_quad.rs` example ... ``` + +## eFuse + +Calling `Efuse::read_field_le::()` no longer compiles. Use `Efuse::read_bit()` instead. diff --git a/esp-hal/src/soc/efuse_field.rs b/esp-hal/src/soc/efuse_field.rs index d0de7a46a..cd27a2ed0 100644 --- a/esp-hal/src/soc/efuse_field.rs +++ b/esp-hal/src/soc/efuse_field.rs @@ -1,3 +1,5 @@ +use bytemuck::AnyBitPattern; + use crate::soc::efuse::{Efuse, EfuseBlock}; /// The bit field for get access to efuse data @@ -21,7 +23,7 @@ impl EfuseField { impl Efuse { /// Read field value in a little-endian order #[inline(always)] - pub fn read_field_le(field: EfuseField) -> T { + pub fn read_field_le(field: EfuseField) -> T { let mut output = core::mem::MaybeUninit::::uninit(); // represent output value as a bytes slice let mut bytes = unsafe { @@ -89,7 +91,7 @@ impl Efuse { /// Read field value in a big-endian order #[inline(always)] - pub fn read_field_be(field: EfuseField) -> T { + pub fn read_field_be(field: EfuseField) -> T { // read value in a little-endian order let mut output = Self::read_field_le::(field); // represent output value as a byte slice @@ -103,4 +105,13 @@ impl Efuse { bytes.reverse(); output } + + /// Read bit value. + /// + /// This function panics if the field's bit length is not equal to 1. + #[inline(always)] + pub fn read_bit(field: EfuseField) -> bool { + assert_eq!(field.bit_len, 1); + Self::read_field_le::(field) != 0 + } } diff --git a/esp-hal/src/soc/esp32/efuse/mod.rs b/esp-hal/src/soc/esp32/efuse/mod.rs index ab1e40073..79773ff0d 100644 --- a/esp-hal/src/soc/esp32/efuse/mod.rs +++ b/esp-hal/src/soc/esp32/efuse/mod.rs @@ -85,7 +85,7 @@ impl Efuse { /// CPU and application CPU), the application CPU is unavailable on /// some. pub fn get_core_count() -> u32 { - if Self::read_field_le::(DISABLE_APP_CPU) { + if Self::read_bit(DISABLE_APP_CPU) { 1 } else { 2 @@ -97,8 +97,8 @@ impl Efuse { /// Note that the actual clock may be lower, depending on the current power /// configuration of the chip, clock source, and other settings. pub fn get_max_cpu_frequency() -> HertzU32 { - let has_rating = Self::read_field_le::(CHIP_CPU_FREQ_RATED); - let has_low_rating = Self::read_field_le::(CHIP_CPU_FREQ_LOW); + let has_rating = Self::read_bit(CHIP_CPU_FREQ_RATED); + let has_low_rating = Self::read_bit(CHIP_CPU_FREQ_LOW); if has_rating && has_low_rating { 160.MHz() @@ -109,7 +109,7 @@ impl Efuse { /// Returns the CHIP_VER_DIS_BT eFuse value. pub fn is_bluetooth_enabled() -> bool { - !Self::read_field_le::(DISABLE_BT) + !Self::read_bit(DISABLE_BT) } /// Returns the CHIP_VER_PKG eFuse value. diff --git a/esp-hal/src/usb_serial_jtag.rs b/esp-hal/src/usb_serial_jtag.rs index e2ad90e45..ea604f876 100644 --- a/esp-hal/src/usb_serial_jtag.rs +++ b/esp-hal/src/usb_serial_jtag.rs @@ -291,7 +291,7 @@ where // On the esp32c3, and esp32s3 the USB_EXCHG_PINS efuse is bugged and // doesn't swap the pullups too, this works around that. - if Efuse::read_field_le(USB_EXCHG_PINS) { + if Efuse::read_bit(USB_EXCHG_PINS) { USB_DEVICE::register_block().conf0().modify(|_, w| { w.pad_pull_override() .set_bit()