mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-27 12:20:56 +00:00
Reorganize efuse code (#3868)
This commit is contained in:
parent
b2c31a1dac
commit
82100314c5
@ -5,7 +5,7 @@
|
||||
|
||||
#![allow(clippy::empty_docs)]
|
||||
|
||||
use super::EfuseField;
|
||||
use crate::efuse::EfuseField;
|
||||
|
||||
/// Efuse write disable mask
|
||||
pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 16);
|
@ -1,59 +1,7 @@
|
||||
#![cfg_attr(docsrs, procmacros::doc_replace)]
|
||||
//! # Reading of eFuses (ESP32)
|
||||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
//! The `efuse` module provides functionality for reading eFuse data
|
||||
//! from the `ESP32` chip, allowing access to various chip-specific information
|
||||
//! such as:
|
||||
//!
|
||||
//! * MAC address
|
||||
//! * Chip type, revision
|
||||
//! * Core count
|
||||
//! * Max CPU frequency
|
||||
//!
|
||||
//! and more. It is useful for retrieving chip-specific configuration and
|
||||
//! identification data during runtime.
|
||||
//!
|
||||
//! The `Efuse` struct represents the eFuse peripheral and is responsible for
|
||||
//! reading various eFuse fields and values.
|
||||
//!
|
||||
//! ## Examples
|
||||
//!
|
||||
//! ### Read data from the eFuse storage.
|
||||
//!
|
||||
//! ```rust, no_run
|
||||
//! # {before_snippet}
|
||||
//! # use esp_hal::efuse::Efuse;
|
||||
//!
|
||||
//! let mac_address = Efuse::read_base_mac_address();
|
||||
//!
|
||||
//! println!(
|
||||
//! "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
|
||||
//! mac_address[0],
|
||||
//! mac_address[1],
|
||||
//! mac_address[2],
|
||||
//! mac_address[3],
|
||||
//! mac_address[4],
|
||||
//! mac_address[5]
|
||||
//! );
|
||||
//!
|
||||
//! println!("MAC address {:02x?}", Efuse::mac_address());
|
||||
//! println!("Flash Encryption {:?}", Efuse::flash_encryption());
|
||||
//! println!("Core Count {}", Efuse::core_count());
|
||||
//! println!("Bluetooth enabled {}", Efuse::is_bluetooth_enabled());
|
||||
//! println!("Chip type {:?}", Efuse::chip_type());
|
||||
//! println!("Max CPU clock {:?}", Efuse::max_cpu_frequency());
|
||||
//! # {after_snippet}
|
||||
//! ```
|
||||
|
||||
pub use self::fields::*;
|
||||
use crate::{peripherals::EFUSE, soc::efuse_field::EfuseField, time::Rate};
|
||||
use crate::{peripherals::EFUSE, time::Rate};
|
||||
|
||||
mod fields;
|
||||
|
||||
/// A struct representing the eFuse functionality of the chip.
|
||||
pub struct Efuse;
|
||||
pub use fields::*;
|
||||
|
||||
/// Representing different types of ESP32 chips.
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
@ -74,7 +22,7 @@ pub enum ChipType {
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl Efuse {
|
||||
impl super::Efuse {
|
||||
/// Returns the number of CPUs available on the chip.
|
||||
///
|
||||
/// While ESP32 chips usually come with two mostly equivalent CPUs (protocol
|
@ -5,7 +5,7 @@
|
||||
|
||||
#![allow(clippy::empty_docs)]
|
||||
|
||||
use super::EfuseField;
|
||||
use crate::efuse::EfuseField;
|
||||
|
||||
/// Disable programming of individual eFuses
|
||||
pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 8);
|
@ -1,54 +1,9 @@
|
||||
#![cfg_attr(docsrs, procmacros::doc_replace)]
|
||||
//! # Reading of eFuses (ESP32-C2)
|
||||
//!
|
||||
//! ## Overview
|
||||
//! The `efuse` module provides functionality for reading eFuse data
|
||||
//! from the `ESP32-C2` chip, allowing access to various chip-specific
|
||||
//! information such as:
|
||||
//!
|
||||
//! * MAC address
|
||||
//! * ADC calibration information
|
||||
//!
|
||||
//! and more. It is useful for retrieving chip-specific configuration and
|
||||
//! identification data during runtime.
|
||||
//!
|
||||
//! The `Efuse` struct represents the eFuse peripheral and is responsible for
|
||||
//! reading various eFuse fields and values.
|
||||
//!
|
||||
//! ## Examples
|
||||
//!
|
||||
//! ### Read data from the eFuse storage.
|
||||
//!
|
||||
//! ```rust, no_run
|
||||
//! # {before_snippet}
|
||||
//! # use esp_hal::efuse::Efuse;
|
||||
//!
|
||||
//! let mac_address = Efuse::read_base_mac_address();
|
||||
//!
|
||||
//! println!(
|
||||
//! "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
|
||||
//! mac_address[0],
|
||||
//! mac_address[1],
|
||||
//! mac_address[2],
|
||||
//! mac_address[3],
|
||||
//! mac_address[4],
|
||||
//! mac_address[5]
|
||||
//! );
|
||||
//!
|
||||
//! println!("MAC address {:02x?}", Efuse::mac_address());
|
||||
//! println!("Flash Encryption {:?}", Efuse::flash_encryption());
|
||||
//! # {after_snippet}
|
||||
//! ```
|
||||
|
||||
pub use self::fields::*;
|
||||
use crate::{analog::adc::Attenuation, peripherals::EFUSE, soc::efuse_field::EfuseField};
|
||||
use crate::{analog::adc::Attenuation, peripherals::EFUSE};
|
||||
|
||||
mod fields;
|
||||
pub use fields::*;
|
||||
|
||||
/// A struct representing the eFuse functionality of the chip.
|
||||
pub struct Efuse;
|
||||
|
||||
impl Efuse {
|
||||
impl super::Efuse {
|
||||
/// Get status of SPI boot encryption.
|
||||
pub fn flash_encryption() -> bool {
|
||||
!Self::read_field_le::<u8>(SPI_BOOT_CRYPT_CNT)
|
@ -5,7 +5,7 @@
|
||||
|
||||
#![allow(clippy::empty_docs)]
|
||||
|
||||
use super::EfuseField;
|
||||
use crate::efuse::EfuseField;
|
||||
|
||||
/// Disable programming of individual eFuses
|
||||
pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 32);
|
@ -1,55 +1,9 @@
|
||||
#![cfg_attr(docsrs, procmacros::doc_replace)]
|
||||
//! # Reading of eFuses (ESP32-C3)
|
||||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
//! The `efuse` module provides functionality for reading eFuse data
|
||||
//! from the `ESP32-C3` chip, allowing access to various chip-specific
|
||||
//! information such as:
|
||||
//!
|
||||
//! * MAC address
|
||||
//! * ADC calibration data
|
||||
//!
|
||||
//! and more. It is useful for retrieving chip-specific configuration and
|
||||
//! identification data during runtime.
|
||||
//!
|
||||
//! The `Efuse` struct represents the eFuse peripheral and is responsible for
|
||||
//! reading various eFuse fields and values.
|
||||
//!
|
||||
//! ## Examples
|
||||
//!
|
||||
//! ### Read data from the eFuse storage.
|
||||
//!
|
||||
//! ```rust, no_run
|
||||
//! # {before_snippet}
|
||||
//! # use esp_hal::efuse::Efuse;
|
||||
//!
|
||||
//! let mac_address = Efuse::read_base_mac_address();
|
||||
//!
|
||||
//! println!(
|
||||
//! "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
|
||||
//! mac_address[0],
|
||||
//! mac_address[1],
|
||||
//! mac_address[2],
|
||||
//! mac_address[3],
|
||||
//! mac_address[4],
|
||||
//! mac_address[5]
|
||||
//! );
|
||||
//!
|
||||
//! println!("MAC address {:02x?}", Efuse::mac_address());
|
||||
//! println!("Flash Encryption {:?}", Efuse::flash_encryption());
|
||||
//! # {after_snippet}
|
||||
//! ```
|
||||
|
||||
pub use self::fields::*;
|
||||
use crate::{analog::adc::Attenuation, peripherals::EFUSE, soc::efuse_field::EfuseField};
|
||||
use crate::{analog::adc::Attenuation, peripherals::EFUSE};
|
||||
|
||||
mod fields;
|
||||
pub use fields::*;
|
||||
|
||||
/// A struct representing the eFuse functionality of the chip.
|
||||
pub struct Efuse;
|
||||
|
||||
impl Efuse {
|
||||
impl super::Efuse {
|
||||
/// Get status of SPI boot encryption.
|
||||
pub fn flash_encryption() -> bool {
|
||||
!Self::read_field_le::<u8>(SPI_BOOT_CRYPT_CNT)
|
@ -5,7 +5,7 @@
|
||||
|
||||
#![allow(clippy::empty_docs)]
|
||||
|
||||
use super::EfuseField;
|
||||
use crate::efuse::EfuseField;
|
||||
|
||||
/// Disable programming of individual eFuses
|
||||
pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 32);
|
@ -1,55 +1,9 @@
|
||||
#![cfg_attr(docsrs, procmacros::doc_replace)]
|
||||
//! # Reading of eFuses (ESP32-C6)
|
||||
//!
|
||||
//! ## Overview
|
||||
//! The `efuse` module provides functionality for reading eFuse data
|
||||
//! from the `ESP32-C6` chip, allowing access to various chip-specific
|
||||
//! information such as:
|
||||
//!
|
||||
//! * MAC address
|
||||
//! * ADC calibration data
|
||||
//! * Chip version
|
||||
//!
|
||||
//! and more. It is useful for retrieving chip-specific configuration and
|
||||
//! identification data during runtime.
|
||||
//!
|
||||
//! The `Efuse` struct represents the eFuse peripheral and is responsible for
|
||||
//! reading various eFuse fields and values.
|
||||
//!
|
||||
//! ## Examples
|
||||
//!
|
||||
//! ### Read data from the eFuse storage.
|
||||
//!
|
||||
//! ```rust, no_run
|
||||
//! # {before_snippet}
|
||||
//! # use esp_hal::efuse::Efuse;
|
||||
//!
|
||||
//! let mac_address = Efuse::read_base_mac_address();
|
||||
//!
|
||||
//! println!(
|
||||
//! "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
|
||||
//! mac_address[0],
|
||||
//! mac_address[1],
|
||||
//! mac_address[2],
|
||||
//! mac_address[3],
|
||||
//! mac_address[4],
|
||||
//! mac_address[5]
|
||||
//! );
|
||||
//!
|
||||
//! println!("MAC address {:02x?}", Efuse::mac_address());
|
||||
//! println!("Flash Encryption {:?}", Efuse::flash_encryption());
|
||||
//! # {after_snippet}
|
||||
//! ```
|
||||
|
||||
pub use self::fields::*;
|
||||
use crate::{analog::adc::Attenuation, peripherals::EFUSE, soc::efuse_field::EfuseField};
|
||||
use crate::{analog::adc::Attenuation, peripherals::EFUSE};
|
||||
|
||||
mod fields;
|
||||
pub use fields::*;
|
||||
|
||||
/// A struct representing the eFuse functionality of the chip.
|
||||
pub struct Efuse;
|
||||
|
||||
impl Efuse {
|
||||
impl super::Efuse {
|
||||
/// Get status of SPI boot encryption.
|
||||
pub fn flash_encryption() -> bool {
|
||||
!Self::read_field_le::<u8>(SPI_BOOT_CRYPT_CNT)
|
@ -5,7 +5,7 @@
|
||||
|
||||
#![allow(clippy::empty_docs)]
|
||||
|
||||
use super::EfuseField;
|
||||
use crate::efuse::EfuseField;
|
||||
|
||||
/// Disable programming of individual eFuses
|
||||
pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 32);
|
@ -1,55 +1,9 @@
|
||||
#![cfg_attr(docsrs, procmacros::doc_replace)]
|
||||
//! # Reading of eFuses (ESP32-H2)
|
||||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
//! The `efuse` module provides functionality for reading eFuse data
|
||||
//! from the `ESP32-H2` chip, allowing access to various chip-specific
|
||||
//! information such as:
|
||||
//!
|
||||
//! * MAC address
|
||||
//! * ADC calibration data
|
||||
//!
|
||||
//! and more. It is useful for retrieving chip-specific configuration and
|
||||
//! identification data during runtime.
|
||||
//!
|
||||
//! The `Efuse` struct represents the eFuse peripheral and is responsible for
|
||||
//! reading various eFuse fields and values.
|
||||
//!
|
||||
//! ## Examples
|
||||
//!
|
||||
//! ### Read data from the eFuse storage.
|
||||
//!
|
||||
//! ```rust, no_run
|
||||
//! # {before_snippet}
|
||||
//! # use esp_hal::efuse::Efuse;
|
||||
//!
|
||||
//! let mac_address = Efuse::read_base_mac_address();
|
||||
//!
|
||||
//! println!(
|
||||
//! "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
|
||||
//! mac_address[0],
|
||||
//! mac_address[1],
|
||||
//! mac_address[2],
|
||||
//! mac_address[3],
|
||||
//! mac_address[4],
|
||||
//! mac_address[5]
|
||||
//! );
|
||||
//!
|
||||
//! println!("MAC address {:02x?}", Efuse::mac_address());
|
||||
//! println!("Flash Encryption {:?}", Efuse::flash_encryption());
|
||||
//! # {after_snippet}
|
||||
//! ```
|
||||
|
||||
pub use self::fields::*;
|
||||
use crate::{analog::adc::Attenuation, peripherals::EFUSE, soc::efuse_field::EfuseField};
|
||||
use crate::{analog::adc::Attenuation, peripherals::EFUSE};
|
||||
|
||||
mod fields;
|
||||
pub use fields::*;
|
||||
|
||||
/// A struct representing the eFuse functionality of the chip.
|
||||
pub struct Efuse;
|
||||
|
||||
impl Efuse {
|
||||
impl super::Efuse {
|
||||
/// Get status of SPI boot encryption.
|
||||
pub fn flash_encryption() -> bool {
|
||||
!Self::read_field_le::<u8>(SPI_BOOT_CRYPT_CNT)
|
@ -5,7 +5,7 @@
|
||||
|
||||
#![allow(clippy::empty_docs)]
|
||||
|
||||
use super::EfuseField;
|
||||
use crate::efuse::EfuseField;
|
||||
|
||||
/// Disable programming of individual eFuses
|
||||
pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 32);
|
@ -1,57 +1,9 @@
|
||||
#![cfg_attr(docsrs, procmacros::doc_replace)]
|
||||
//! # Reading of eFuses (ESP32-S2)
|
||||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
//! The `efuse` module provides functionality for reading eFuse data
|
||||
//! from the `ESP32-S2` chip, allowing access to various chip-specific
|
||||
//! information such as:
|
||||
//!
|
||||
//! * MAC address
|
||||
//! * core count
|
||||
//! * CPU frequency
|
||||
//! * chip type
|
||||
//!
|
||||
//! and more. It is useful for retrieving chip-specific configuration and
|
||||
//! identification data during runtime.
|
||||
//!
|
||||
//! The `Efuse` struct represents the eFuse peripheral and is responsible for
|
||||
//! reading various eFuse fields and values.
|
||||
//!
|
||||
//! ## Examples
|
||||
//!
|
||||
//! ### Read data from the eFuse storage.
|
||||
//!
|
||||
//! ```rust, no_run
|
||||
//! # {before_snippet}
|
||||
//! # use esp_hal::efuse::Efuse;
|
||||
//!
|
||||
//! let mac_address = Efuse::read_base_mac_address();
|
||||
//!
|
||||
//! println!(
|
||||
//! "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
|
||||
//! mac_address[0],
|
||||
//! mac_address[1],
|
||||
//! mac_address[2],
|
||||
//! mac_address[3],
|
||||
//! mac_address[4],
|
||||
//! mac_address[5]
|
||||
//! );
|
||||
//!
|
||||
//! println!("MAC address {:02x?}", Efuse::mac_address());
|
||||
//! println!("Flash Encryption {:?}", Efuse::flash_encryption());
|
||||
//! # {after_snippet}
|
||||
//! ```
|
||||
|
||||
pub use self::fields::*;
|
||||
use crate::{peripherals::EFUSE, soc::efuse_field::EfuseField};
|
||||
use crate::peripherals::EFUSE;
|
||||
|
||||
mod fields;
|
||||
pub use fields::*;
|
||||
|
||||
/// A struct representing the eFuse functionality of the chip.
|
||||
pub struct Efuse;
|
||||
|
||||
impl Efuse {
|
||||
impl super::Efuse {
|
||||
/// Get status of SPI boot encryption.
|
||||
pub fn flash_encryption() -> bool {
|
||||
!Self::read_field_le::<u8>(SPI_BOOT_CRYPT_CNT)
|
@ -5,7 +5,7 @@
|
||||
|
||||
#![allow(clippy::empty_docs)]
|
||||
|
||||
use super::EfuseField;
|
||||
use crate::efuse::EfuseField;
|
||||
|
||||
/// Disable programming of individual eFuses
|
||||
pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 32);
|
@ -1,55 +1,9 @@
|
||||
#![cfg_attr(docsrs, procmacros::doc_replace)]
|
||||
//! # Reading of eFuses (ESP32-S3)
|
||||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
//! The `efuse` module provides functionality for reading eFuse data
|
||||
//! from the `ESP32-S3` chip, allowing access to various chip-specific
|
||||
//! information such as:
|
||||
//!
|
||||
//! * MAC address
|
||||
//! * Chip revision
|
||||
//!
|
||||
//! and more. It is useful for retrieving chip-specific configuration and
|
||||
//! identification data during runtime.
|
||||
//!
|
||||
//! The `Efuse` struct represents the eFuse peripheral and is responsible for
|
||||
//! reading various eFuse fields and values.
|
||||
//!
|
||||
//! ## Examples
|
||||
//!
|
||||
//! ### Read data from the eFuse storage.
|
||||
//!
|
||||
//! ```rust, no_run
|
||||
//! # {before_snippet}
|
||||
//! # use esp_hal::efuse::Efuse;
|
||||
//!
|
||||
//! let mac_address = Efuse::read_base_mac_address();
|
||||
//!
|
||||
//! println!(
|
||||
//! "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
|
||||
//! mac_address[0],
|
||||
//! mac_address[1],
|
||||
//! mac_address[2],
|
||||
//! mac_address[3],
|
||||
//! mac_address[4],
|
||||
//! mac_address[5]
|
||||
//! );
|
||||
//!
|
||||
//! println!("MAC address {:02x?}", Efuse::mac_address());
|
||||
//! println!("Flash Encryption {:?}", Efuse::flash_encryption());
|
||||
//! # {after_snippet}
|
||||
//! ```
|
||||
|
||||
pub use self::fields::*;
|
||||
use crate::{analog::adc::Attenuation, peripherals::EFUSE, soc::efuse_field::EfuseField};
|
||||
use crate::{analog::adc::Attenuation, peripherals::EFUSE};
|
||||
|
||||
mod fields;
|
||||
pub use fields::*;
|
||||
|
||||
/// A struct representing the eFuse functionality of the chip.
|
||||
pub struct Efuse;
|
||||
|
||||
impl Efuse {
|
||||
impl super::Efuse {
|
||||
/// Get status of SPI boot encryption.
|
||||
pub fn flash_encryption() -> bool {
|
||||
!Self::read_field_le::<u8>(SPI_BOOT_CRYPT_CNT)
|
253
esp-hal/src/efuse/mod.rs
Normal file
253
esp-hal/src/efuse/mod.rs
Normal file
@ -0,0 +1,253 @@
|
||||
#![cfg_attr(docsrs, procmacros::doc_replace)]
|
||||
//! # eFuse (one-time programmable configuration)
|
||||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
//! The `efuse` module provides functionality for reading eFuse data
|
||||
//! from the chip, allowing access to various chip-specific
|
||||
//! information such as:
|
||||
//!
|
||||
//! * MAC address
|
||||
//! * Chip revision
|
||||
//!
|
||||
//! and more. It is useful for retrieving chip-specific configuration and
|
||||
//! identification data during runtime.
|
||||
//!
|
||||
//! The `Efuse` struct represents the eFuse peripheral and is responsible for
|
||||
//! reading various eFuse fields and values.
|
||||
//!
|
||||
//! ## Examples
|
||||
//!
|
||||
//! ### Read data from the eFuse storage.
|
||||
//!
|
||||
//! ```rust, no_run
|
||||
//! # {before_snippet}
|
||||
//! use esp_hal::efuse::{Efuse, SECURE_VERSION};
|
||||
//!
|
||||
//! let mac_address = Efuse::read_base_mac_address();
|
||||
//!
|
||||
//! println!(
|
||||
//! "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}",
|
||||
//! mac_address[0],
|
||||
//! mac_address[1],
|
||||
//! mac_address[2],
|
||||
//! mac_address[3],
|
||||
//! mac_address[4],
|
||||
//! mac_address[5]
|
||||
//! );
|
||||
//!
|
||||
//! println!("MAC address {:02x?}", Efuse::mac_address());
|
||||
//! println!("Flash Encryption {:?}", Efuse::flash_encryption());
|
||||
//!
|
||||
//! // Besides the helper methods, various eFuse field constants can also be read with a lower-level API:
|
||||
//!
|
||||
//! println!(
|
||||
//! "Secure version {:?}",
|
||||
//! Efuse::read_field_le::<u16>(SECURE_VERSION)
|
||||
//! );
|
||||
//! # {after_snippet}
|
||||
//! ```
|
||||
|
||||
use core::{cmp, mem, slice, sync::atomic::Ordering};
|
||||
|
||||
use bytemuck::AnyBitPattern;
|
||||
use portable_atomic::AtomicU8;
|
||||
|
||||
#[cfg_attr(esp32, path = "esp32/mod.rs")]
|
||||
#[cfg_attr(esp32c2, path = "esp32c2/mod.rs")]
|
||||
#[cfg_attr(esp32c3, path = "esp32c3/mod.rs")]
|
||||
#[cfg_attr(esp32c6, path = "esp32c6/mod.rs")]
|
||||
#[cfg_attr(esp32h2, path = "esp32h2/mod.rs")]
|
||||
#[cfg_attr(esp32s2, path = "esp32s2/mod.rs")]
|
||||
#[cfg_attr(esp32s3, path = "esp32s3/mod.rs")]
|
||||
pub(crate) mod implem;
|
||||
|
||||
pub use implem::*;
|
||||
|
||||
/// The bit field for get access to efuse data
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[instability::unstable]
|
||||
pub struct EfuseField {
|
||||
/// The block
|
||||
pub(crate) block: EfuseBlock,
|
||||
/// Word number - this is just informational
|
||||
pub(crate) _word: u32,
|
||||
/// Starting bit in the efuse block
|
||||
pub(crate) bit_start: u32,
|
||||
/// Number of bits
|
||||
pub(crate) bit_count: u32,
|
||||
}
|
||||
|
||||
impl EfuseField {
|
||||
pub(crate) const fn new(block: u32, word: u32, bit_start: u32, bit_count: u32) -> Self {
|
||||
Self {
|
||||
block: EfuseBlock::from_repr(block).unwrap(),
|
||||
_word: word,
|
||||
bit_start,
|
||||
bit_count,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct representing the eFuse functionality of the chip.
|
||||
#[instability::unstable]
|
||||
pub struct Efuse;
|
||||
|
||||
impl Efuse {
|
||||
/// Reads chip's MAC address from the eFuse storage.
|
||||
#[instability::unstable]
|
||||
pub fn read_base_mac_address() -> [u8; 6] {
|
||||
let mut mac_addr = [0u8; 6];
|
||||
|
||||
let mac0 = Self::read_field_le::<[u8; 4]>(crate::efuse::MAC0);
|
||||
let mac1 = Self::read_field_le::<[u8; 2]>(crate::efuse::MAC1);
|
||||
|
||||
// MAC address is stored in big endian, so load the bytes in reverse:
|
||||
mac_addr[0] = mac1[1];
|
||||
mac_addr[1] = mac1[0];
|
||||
mac_addr[2] = mac0[3];
|
||||
mac_addr[3] = mac0[2];
|
||||
mac_addr[4] = mac0[1];
|
||||
mac_addr[5] = mac0[0];
|
||||
|
||||
mac_addr
|
||||
}
|
||||
|
||||
/// Read field value in a little-endian order
|
||||
#[inline(always)]
|
||||
#[instability::unstable]
|
||||
pub fn read_field_le<T: AnyBitPattern>(field: EfuseField) -> T {
|
||||
let EfuseField {
|
||||
block,
|
||||
bit_start,
|
||||
bit_count,
|
||||
..
|
||||
} = field;
|
||||
|
||||
// Represent output value as a bytes slice:
|
||||
let mut output = mem::MaybeUninit::<T>::uninit();
|
||||
let mut bytes = unsafe {
|
||||
slice::from_raw_parts_mut(output.as_mut_ptr() as *mut u8, mem::size_of::<T>())
|
||||
};
|
||||
|
||||
let bit_off = bit_start as usize;
|
||||
let bit_end = cmp::min(bit_count as usize, bytes.len() * 8) + bit_off;
|
||||
|
||||
let mut last_word_off = bit_off / 32;
|
||||
let mut last_word = unsafe { block.address().add(last_word_off).read_volatile() };
|
||||
|
||||
let word_bit_off = bit_off % 32;
|
||||
let word_bit_ext = 32 - word_bit_off;
|
||||
|
||||
let mut word_off = last_word_off;
|
||||
for bit_off in (bit_off..bit_end).step_by(32) {
|
||||
if word_off != last_word_off {
|
||||
// Read a new word:
|
||||
last_word_off = word_off;
|
||||
last_word = unsafe { block.address().add(last_word_off).read_volatile() };
|
||||
}
|
||||
|
||||
let mut word = last_word >> word_bit_off;
|
||||
word_off += 1;
|
||||
|
||||
let word_bit_len = cmp::min(bit_end - bit_off, 32);
|
||||
if word_bit_len > word_bit_ext {
|
||||
// Read the next word:
|
||||
last_word_off = word_off;
|
||||
last_word = unsafe { block.address().add(last_word_off).read_volatile() };
|
||||
// Append bits from a beginning of the next word:
|
||||
word |= last_word.wrapping_shl((32 - word_bit_off) as u32);
|
||||
};
|
||||
|
||||
if word_bit_len < 32 {
|
||||
// Mask only needed bits of a word:
|
||||
word &= u32::MAX >> (32 - word_bit_len);
|
||||
}
|
||||
|
||||
// Represent word as a byte slice:
|
||||
let byte_len = word_bit_len.div_ceil(8);
|
||||
let word_bytes =
|
||||
unsafe { slice::from_raw_parts(&word as *const u32 as *const u8, byte_len) };
|
||||
|
||||
// Copy word bytes to output value bytes:
|
||||
bytes[..byte_len].copy_from_slice(word_bytes);
|
||||
|
||||
// Move read window forward:
|
||||
bytes = &mut bytes[byte_len..];
|
||||
}
|
||||
|
||||
// Fill untouched bytes with zeros:
|
||||
bytes.fill(0);
|
||||
|
||||
unsafe { output.assume_init() }
|
||||
}
|
||||
|
||||
/// Read bit value.
|
||||
///
|
||||
/// This function panics if the field's bit length is not equal to 1.
|
||||
#[inline(always)]
|
||||
#[instability::unstable]
|
||||
pub fn read_bit(field: EfuseField) -> bool {
|
||||
assert_eq!(field.bit_count, 1);
|
||||
Self::read_field_le::<u8>(field) != 0
|
||||
}
|
||||
|
||||
/// Set the base mac address
|
||||
///
|
||||
/// The new value will be returned by `read_mac_address` instead of the one
|
||||
/// hard-coded in eFuse. This does not persist across device resets.
|
||||
///
|
||||
/// Can only be called once. Returns `Err(SetMacError::AlreadySet)`
|
||||
/// otherwise.
|
||||
#[instability::unstable]
|
||||
pub fn set_mac_address(mac: [u8; 6]) -> Result<(), SetMacError> {
|
||||
if MAC_OVERRIDE_STATE
|
||||
.compare_exchange(0, 1, Ordering::Relaxed, Ordering::Relaxed)
|
||||
.is_err()
|
||||
{
|
||||
return Err(SetMacError::AlreadySet);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
MAC_OVERRIDE = mac;
|
||||
}
|
||||
|
||||
MAC_OVERRIDE_STATE.store(2, Ordering::Relaxed);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get base mac address
|
||||
///
|
||||
/// By default this reads the base mac address from eFuse, but it can be
|
||||
/// overridden by `set_mac_address`.
|
||||
#[instability::unstable]
|
||||
pub fn mac_address() -> [u8; 6] {
|
||||
if MAC_OVERRIDE_STATE.load(Ordering::Relaxed) == 2 {
|
||||
unsafe { MAC_OVERRIDE }
|
||||
} else {
|
||||
Self::read_base_mac_address()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Indicates the state of setting the mac address
|
||||
// 0 -- unset
|
||||
// 1 -- in the process of being set
|
||||
// 2 -- set
|
||||
//
|
||||
// Values other than 0 indicate that we cannot attempt setting the mac address
|
||||
// again, and values other than 2 indicate that we should read the mac address
|
||||
// from eFuse.
|
||||
#[cfg_attr(not(feature = "unstable"), allow(unused))]
|
||||
static MAC_OVERRIDE_STATE: AtomicU8 = AtomicU8::new(0);
|
||||
#[cfg_attr(not(feature = "unstable"), allow(unused))]
|
||||
static mut MAC_OVERRIDE: [u8; 6] = [0; 6];
|
||||
|
||||
/// Error indicating issues with setting the MAC address.
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
#[instability::unstable]
|
||||
pub enum SetMacError {
|
||||
/// The MAC address has already been set and cannot be changed.
|
||||
AlreadySet,
|
||||
}
|
@ -225,10 +225,6 @@ pub(crate) use peripherals::pac;
|
||||
#[cfg_attr(not(feature = "unstable"), doc(hidden))]
|
||||
pub use xtensa_lx_rt::{self, xtensa_lx};
|
||||
|
||||
#[cfg(soc_has_efuse)]
|
||||
#[instability::unstable]
|
||||
#[cfg_attr(not(feature = "unstable"), allow(unused))]
|
||||
pub use self::soc::efuse;
|
||||
#[cfg(lp_core)]
|
||||
#[instability::unstable]
|
||||
#[cfg_attr(not(feature = "unstable"), allow(unused))]
|
||||
@ -333,6 +329,7 @@ unstable_module! {
|
||||
pub mod otg_fs;
|
||||
#[cfg(psram)] // DMA needs some things from here
|
||||
pub mod psram;
|
||||
pub mod efuse;
|
||||
}
|
||||
|
||||
unstable_driver! {
|
||||
|
@ -18,9 +18,10 @@ use crate::{
|
||||
esp32c6_rtc_update_to_xtal_raw,
|
||||
},
|
||||
},
|
||||
efuse::Efuse,
|
||||
peripherals::TIMG0,
|
||||
rtc_cntl::RtcClock,
|
||||
soc::{efuse::Efuse, regi2c},
|
||||
soc::regi2c,
|
||||
time::Rate,
|
||||
};
|
||||
|
||||
|
@ -1,128 +0,0 @@
|
||||
use core::{cmp, mem, slice};
|
||||
|
||||
use bytemuck::AnyBitPattern;
|
||||
|
||||
use crate::soc::efuse::{Efuse, EfuseBlock};
|
||||
|
||||
/// The bit field for get access to efuse data
|
||||
#[allow(unused)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct EfuseField {
|
||||
/// The block
|
||||
pub(crate) block: EfuseBlock,
|
||||
/// Word number - this is just informational
|
||||
pub(crate) word: u32,
|
||||
/// Starting bit in the efuse block
|
||||
pub(crate) bit_start: u32,
|
||||
/// Number of bits
|
||||
pub(crate) bit_count: u32,
|
||||
}
|
||||
|
||||
impl EfuseField {
|
||||
pub(crate) const fn new(block: u32, word: u32, bit_start: u32, bit_count: u32) -> Self {
|
||||
Self {
|
||||
block: EfuseBlock::from_repr(block).unwrap(),
|
||||
word,
|
||||
bit_start,
|
||||
bit_count,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Efuse {
|
||||
/// Reads chip's MAC address from the eFuse storage.
|
||||
pub fn read_base_mac_address() -> [u8; 6] {
|
||||
let mut mac_addr = [0u8; 6];
|
||||
|
||||
let mac0 = Self::read_field_le::<[u8; 4]>(crate::soc::efuse::MAC0);
|
||||
let mac1 = Self::read_field_le::<[u8; 2]>(crate::soc::efuse::MAC1);
|
||||
|
||||
// MAC address is stored in big endian, so load the bytes in reverse:
|
||||
mac_addr[0] = mac1[1];
|
||||
mac_addr[1] = mac1[0];
|
||||
mac_addr[2] = mac0[3];
|
||||
mac_addr[3] = mac0[2];
|
||||
mac_addr[4] = mac0[1];
|
||||
mac_addr[5] = mac0[0];
|
||||
|
||||
mac_addr
|
||||
}
|
||||
|
||||
/// Read field value in a little-endian order
|
||||
#[inline(always)]
|
||||
pub fn read_field_le<T: AnyBitPattern>(field: EfuseField) -> T {
|
||||
let EfuseField {
|
||||
block,
|
||||
bit_start,
|
||||
bit_count,
|
||||
..
|
||||
} = field;
|
||||
|
||||
// Represent output value as a bytes slice:
|
||||
let mut output = mem::MaybeUninit::<T>::uninit();
|
||||
let mut bytes = unsafe {
|
||||
slice::from_raw_parts_mut(output.as_mut_ptr() as *mut u8, mem::size_of::<T>())
|
||||
};
|
||||
|
||||
let bit_off = bit_start as usize;
|
||||
let bit_end = cmp::min(bit_count as usize, bytes.len() * 8) + bit_off;
|
||||
|
||||
let mut last_word_off = bit_off / 32;
|
||||
let mut last_word = unsafe { block.address().add(last_word_off).read_volatile() };
|
||||
|
||||
let word_bit_off = bit_off % 32;
|
||||
let word_bit_ext = 32 - word_bit_off;
|
||||
|
||||
let mut word_off = last_word_off;
|
||||
for bit_off in (bit_off..bit_end).step_by(32) {
|
||||
if word_off != last_word_off {
|
||||
// Read a new word:
|
||||
last_word_off = word_off;
|
||||
last_word = unsafe { block.address().add(last_word_off).read_volatile() };
|
||||
}
|
||||
|
||||
let mut word = last_word >> word_bit_off;
|
||||
word_off += 1;
|
||||
|
||||
let word_bit_len = cmp::min(bit_end - bit_off, 32);
|
||||
if word_bit_len > word_bit_ext {
|
||||
// Read the next word:
|
||||
last_word_off = word_off;
|
||||
last_word = unsafe { block.address().add(last_word_off).read_volatile() };
|
||||
// Append bits from a beginning of the next word:
|
||||
word |= last_word.wrapping_shl((32 - word_bit_off) as u32);
|
||||
};
|
||||
|
||||
if word_bit_len < 32 {
|
||||
// Mask only needed bits of a word:
|
||||
word &= u32::MAX >> (32 - word_bit_len);
|
||||
}
|
||||
|
||||
// Represent word as a byte slice:
|
||||
let byte_len = word_bit_len.div_ceil(8);
|
||||
let word_bytes =
|
||||
unsafe { slice::from_raw_parts(&word as *const u32 as *const u8, byte_len) };
|
||||
|
||||
// Copy word bytes to output value bytes:
|
||||
bytes[..byte_len].copy_from_slice(word_bytes);
|
||||
|
||||
// Move read window forward:
|
||||
bytes = &mut bytes[byte_len..];
|
||||
}
|
||||
|
||||
// Fill untouched bytes with zeros:
|
||||
bytes.fill(0);
|
||||
|
||||
unsafe { output.assume_init() }
|
||||
}
|
||||
|
||||
/// Read bit value.
|
||||
///
|
||||
/// This function panics if the field's bit length is not equal to 1.
|
||||
#[inline(always)]
|
||||
#[cfg_attr(not(feature = "unstable"), allow(unused))]
|
||||
pub fn read_bit(field: EfuseField) -> bool {
|
||||
assert_eq!(field.bit_count, 1);
|
||||
Self::read_field_le::<u8>(field) != 0
|
||||
}
|
||||
}
|
@ -6,7 +6,6 @@
|
||||
//! for interacting with various system-related peripherals on `ESP32` chip.
|
||||
|
||||
crate::unstable_module! {
|
||||
pub mod efuse;
|
||||
pub mod trng;
|
||||
}
|
||||
pub mod cpu_control;
|
||||
|
@ -6,7 +6,6 @@
|
||||
//! for interacting with various system-related peripherals on `ESP32-C2` chip.
|
||||
|
||||
crate::unstable_module! {
|
||||
pub mod efuse;
|
||||
pub mod trng;
|
||||
}
|
||||
pub mod gpio;
|
||||
|
@ -10,7 +10,6 @@
|
||||
//! * I2S_DEFAULT_CLK_SRC: 2 - I2S clock source
|
||||
|
||||
crate::unstable_module! {
|
||||
pub mod efuse;
|
||||
pub mod trng;
|
||||
}
|
||||
pub mod gpio;
|
||||
|
@ -11,7 +11,6 @@
|
||||
//! * I2S_SCLK: 160_000_000 - I2S clock frequency
|
||||
|
||||
crate::unstable_module! {
|
||||
pub mod efuse;
|
||||
pub mod lp_core;
|
||||
pub mod trng;
|
||||
}
|
||||
|
@ -11,7 +11,6 @@
|
||||
//! * I2S_SCLK: 96_000_000 - I2S clock frequency
|
||||
|
||||
crate::unstable_module! {
|
||||
pub mod efuse;
|
||||
pub mod trng;
|
||||
}
|
||||
pub mod gpio;
|
||||
|
@ -10,7 +10,6 @@
|
||||
//! * I2S_DEFAULT_CLK_SRC: 2 - I2S clock source
|
||||
|
||||
crate::unstable_module! {
|
||||
pub mod efuse;
|
||||
pub mod trng;
|
||||
pub mod ulp_core;
|
||||
}
|
||||
|
@ -10,7 +10,6 @@
|
||||
//! * I2S_DEFAULT_CLK_SRC: 2 - I2S clock source
|
||||
|
||||
crate::unstable_module! {
|
||||
pub mod efuse;
|
||||
pub mod trng;
|
||||
pub mod ulp_core;
|
||||
}
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
use core::ops::Range;
|
||||
|
||||
use portable_atomic::{AtomicU8, Ordering};
|
||||
|
||||
pub use self::implementation::*;
|
||||
|
||||
#[cfg_attr(esp32, path = "esp32/mod.rs")]
|
||||
@ -15,68 +13,6 @@ pub use self::implementation::*;
|
||||
#[cfg_attr(esp32s3, path = "esp32s3/mod.rs")]
|
||||
mod implementation;
|
||||
|
||||
mod efuse_field;
|
||||
|
||||
// Indicates the state of setting the mac address
|
||||
// 0 -- unset
|
||||
// 1 -- in the process of being set
|
||||
// 2 -- set
|
||||
//
|
||||
// Values other than 0 indicate that we cannot attempt setting the mac address
|
||||
// again, and values other than 2 indicate that we should read the mac address
|
||||
// from eFuse.
|
||||
#[cfg_attr(not(feature = "unstable"), allow(unused))]
|
||||
static MAC_OVERRIDE_STATE: AtomicU8 = AtomicU8::new(0);
|
||||
#[cfg_attr(not(feature = "unstable"), allow(unused))]
|
||||
static mut MAC_OVERRIDE: [u8; 6] = [0; 6];
|
||||
|
||||
/// Error indicating issues with setting the MAC address.
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
#[cfg_attr(not(feature = "unstable"), allow(unused))]
|
||||
pub enum SetMacError {
|
||||
/// The MAC address has already been set and cannot be changed.
|
||||
AlreadySet,
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "unstable"), allow(unused))]
|
||||
impl self::efuse::Efuse {
|
||||
/// Set the base mac address
|
||||
///
|
||||
/// The new value will be returned by `read_mac_address` instead of the one
|
||||
/// hard-coded in eFuse. This does not persist across device resets.
|
||||
///
|
||||
/// Can only be called once. Returns `Err(SetMacError::AlreadySet)`
|
||||
/// otherwise.
|
||||
pub fn set_mac_address(mac: [u8; 6]) -> Result<(), SetMacError> {
|
||||
if MAC_OVERRIDE_STATE
|
||||
.compare_exchange(0, 1, Ordering::Relaxed, Ordering::Relaxed)
|
||||
.is_err()
|
||||
{
|
||||
return Err(SetMacError::AlreadySet);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
MAC_OVERRIDE = mac;
|
||||
}
|
||||
|
||||
MAC_OVERRIDE_STATE.store(2, Ordering::Relaxed);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get base mac address
|
||||
///
|
||||
/// By default this reads the base mac address from eFuse, but it can be
|
||||
/// overridden by `set_mac_address`.
|
||||
pub fn mac_address() -> [u8; 6] {
|
||||
if MAC_OVERRIDE_STATE.load(Ordering::Relaxed) == 2 {
|
||||
unsafe { MAC_OVERRIDE }
|
||||
} else {
|
||||
Self::read_base_mac_address()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) fn is_valid_ram_address(address: usize) -> bool {
|
||||
addr_in_range(address, memory_range!("DRAM"))
|
||||
|
@ -358,7 +358,7 @@ where
|
||||
|
||||
#[cfg(any(esp32c3, esp32s3))]
|
||||
{
|
||||
use crate::soc::efuse::*;
|
||||
use crate::efuse::{Efuse, USB_EXCHG_PINS};
|
||||
|
||||
// On the esp32c3, and esp32s3 the USB_EXCHG_PINS efuse is bugged and
|
||||
// doesn't swap the pullups too, this works around that.
|
||||
|
Loading…
x
Reference in New Issue
Block a user