diff --git a/Cargo.lock b/Cargo.lock index c0b9af85..5a537510 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1377,6 +1377,15 @@ dependencies = [ "web-time", ] +[[package]] +name = "indoc" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", +] + [[package]] name = "io-kit-sys" version = "0.4.1" @@ -1564,6 +1573,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "miette" version = "7.6.0" @@ -1876,6 +1894,67 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "pyo3" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37a6df7eab65fc7bee654a421404947e10a0f7085b6951bf2ea395f4659fb0cf" +dependencies = [ + "indoc", + "libc", + "memoffset", + "once_cell", + "portable-atomic", + "pyo3-build-config", + "pyo3-ffi", + "pyo3-macros", + "unindent", +] + +[[package]] +name = "pyo3-build-config" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f77d387774f6f6eec64a004eac0ed525aab7fa1966d94b42f743797b3e395afb" +dependencies = [ + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dd13844a4242793e02df3e2ec093f540d948299a6a77ea9ce7afd8623f542be" +dependencies = [ + "libc", + "pyo3-build-config", +] + +[[package]] +name = "pyo3-macros" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf8f9f1108270b90d3676b8679586385430e5c0bb78bb5f043f95499c821a71" +dependencies = [ + "proc-macro2", + "pyo3-macros-backend", + "quote", + "syn", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a3b2274450ba5288bc9b8c1b69ff569d1d61189d4bff38f8d22e03d17f932b" +dependencies = [ + "heck", + "proc-macro2", + "pyo3-build-config", + "quote", + "syn", +] + [[package]] name = "quinn" version = "0.11.9" @@ -2480,6 +2559,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "target-lexicon" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df7f62577c25e07834649fc3b39fafdc597c0a3527dc1c60129201ccfcbaa50c" + [[package]] name = "tempfile" version = "3.23.0" @@ -2794,6 +2879,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" +[[package]] +name = "unindent" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" + [[package]] name = "unit-prefix" version = "0.5.1" @@ -3313,6 +3404,7 @@ dependencies = [ "clap", "env_logger", "log", + "pyo3", "serde", "serde_yaml", ] diff --git a/espflash/src/error.rs b/espflash/src/error.rs index 2d56c617..7aabeae5 100644 --- a/espflash/src/error.rs +++ b/espflash/src/error.rs @@ -357,6 +357,10 @@ pub enum Error { /// Key is not in the expected section #[error("Misplaced key, check your configuration file. Key: {0}")] MisplacedKey(String), + + /// Specified eFuse block does not exist + #[error("specified eFuse block does not exist: {0}")] + InvalidEfuseBlock(u8), } #[cfg(feature = "serialport")] diff --git a/espflash/src/target/efuse/esp32.rs b/espflash/src/target/efuse/esp32.rs index 08810206..fde536da 100644 --- a/espflash/src/target/efuse/esp32.rs +++ b/espflash/src/target/efuse/esp32.rs @@ -2,15 +2,32 @@ //! //! This file was automatically generated, please do not edit it manually! //! -//! Generated: 2025-06-25 11:06 +//! Generated: 2025-11-19 16:57 //! Version: 369d2d860d34e777c0f7d545a7dfc3c4 #![allow(unused)] -use super::EfuseField; +use super::{EfuseBlock, EfuseField}; -/// Total size in bytes of each block -pub(crate) const BLOCK_SIZES: &[u32] = &[28, 32, 32, 32]; +/// All eFuse blocks available on this device. +pub(crate) const BLOCKS: &[EfuseBlock] = &[ + EfuseBlock { + length: 7u8, + read_address: 1073061888u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1073061944u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1073061976u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1073062008u32, + }, +]; /// Efuse write disable mask pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 16); diff --git a/espflash/src/target/efuse/esp32c2.rs b/espflash/src/target/efuse/esp32c2.rs index 12a19be5..27bb3d69 100644 --- a/espflash/src/target/efuse/esp32c2.rs +++ b/espflash/src/target/efuse/esp32c2.rs @@ -2,15 +2,32 @@ //! //! This file was automatically generated, please do not edit it manually! //! -//! Generated: 2025-06-26 09:47 +//! Generated: 2025-11-19 16:57 //! Version: 897499b0349a608b895d467abbcf006b #![allow(unused)] -use super::EfuseField; +use super::{EfuseBlock, EfuseField}; -/// Total size in bytes of each block -pub(crate) const BLOCK_SIZES: &[u32] = &[8, 11, 32, 32]; +/// All eFuse blocks available on this device. +pub(crate) const BLOCKS: &[EfuseBlock] = &[ + EfuseBlock { + length: 2u8, + read_address: 1610647596u32, + }, + EfuseBlock { + length: 3u8, + read_address: 1610647604u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610647616u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610647648u32, + }, +]; /// Disable programming of individual eFuses pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 8); diff --git a/espflash/src/target/efuse/esp32c3.rs b/espflash/src/target/efuse/esp32c3.rs index 3e570423..ffb75147 100644 --- a/espflash/src/target/efuse/esp32c3.rs +++ b/espflash/src/target/efuse/esp32c3.rs @@ -2,15 +2,60 @@ //! //! This file was automatically generated, please do not edit it manually! //! -//! Generated: 2025-06-26 09:47 +//! Generated: 2025-11-19 16:57 //! Version: 4622cf9245401eca0eb1df8122449a6d #![allow(unused)] -use super::EfuseField; +use super::{EfuseBlock, EfuseField}; -/// Total size in bytes of each block -pub(crate) const BLOCK_SIZES: &[u32] = &[23, 24, 32, 32, 32, 32, 32, 32, 32, 32, 32]; +/// All eFuse blocks available on this device. +pub(crate) const BLOCKS: &[EfuseBlock] = &[ + EfuseBlock { + length: 6u8, + read_address: 1610647596u32, + }, + EfuseBlock { + length: 6u8, + read_address: 1610647620u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610647644u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610647676u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610647708u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610647740u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610647772u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610647804u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610647836u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610647868u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610647900u32, + }, +]; /// Disable programming of individual eFuses pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 32); diff --git a/espflash/src/target/efuse/esp32c5.rs b/espflash/src/target/efuse/esp32c5.rs index af632a3b..c6b42e0a 100644 --- a/espflash/src/target/efuse/esp32c5.rs +++ b/espflash/src/target/efuse/esp32c5.rs @@ -2,15 +2,60 @@ //! //! This file was automatically generated, please do not edit it manually! //! -//! Generated: 2025-06-26 09:47 +//! Generated: 2025-11-19 16:57 //! Version: 31c7fe3f5f4e0a55b178a57126c0aca7 #![allow(unused)] -use super::EfuseField; +use super::{EfuseBlock, EfuseField}; -/// Total size in bytes of each block -pub(crate) const BLOCK_SIZES: &[u32] = &[24, 24, 32, 32, 32, 32, 32, 32, 32, 32, 32]; +/// All eFuse blocks available on this device. +pub(crate) const BLOCKS: &[EfuseBlock] = &[ + EfuseBlock { + length: 6u8, + read_address: 1611352108u32, + }, + EfuseBlock { + length: 6u8, + read_address: 1611352132u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611352156u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611352188u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611352220u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611352252u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611352284u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611352316u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611352348u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611352380u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611352412u32, + }, +]; /// Disable programming of individual eFuses pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 32); diff --git a/espflash/src/target/efuse/esp32c6.rs b/espflash/src/target/efuse/esp32c6.rs index 4adf01b1..fa8f83f3 100644 --- a/espflash/src/target/efuse/esp32c6.rs +++ b/espflash/src/target/efuse/esp32c6.rs @@ -2,15 +2,60 @@ //! //! This file was automatically generated, please do not edit it manually! //! -//! Generated: 2025-06-25 11:06 +//! Generated: 2025-11-19 16:57 //! Version: df46b69f0ed3913114ba53d3a0b2b843 #![allow(unused)] -use super::EfuseField; +use super::{EfuseBlock, EfuseField}; -/// Total size in bytes of each block -pub(crate) const BLOCK_SIZES: &[u32] = &[24, 24, 32, 32, 32, 32, 32, 32, 32, 32, 32]; +/// All eFuse blocks available on this device. +pub(crate) const BLOCKS: &[EfuseBlock] = &[ + EfuseBlock { + length: 6u8, + read_address: 1611335724u32, + }, + EfuseBlock { + length: 6u8, + read_address: 1611335748u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611335772u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611335804u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611335836u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611335868u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611335900u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611335932u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611335964u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611335996u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611336028u32, + }, +]; /// Disable programming of individual eFuses pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 32); diff --git a/espflash/src/target/efuse/esp32h2.rs b/espflash/src/target/efuse/esp32h2.rs index f1c86cb6..949617d8 100644 --- a/espflash/src/target/efuse/esp32h2.rs +++ b/espflash/src/target/efuse/esp32h2.rs @@ -2,15 +2,60 @@ //! //! This file was automatically generated, please do not edit it manually! //! -//! Generated: 2025-06-25 11:06 +//! Generated: 2025-11-19 16:57 //! Version: 44563d2af4ebdba4db6c0a34a50c94f9 #![allow(unused)] -use super::EfuseField; +use super::{EfuseBlock, EfuseField}; -/// Total size in bytes of each block -pub(crate) const BLOCK_SIZES: &[u32] = &[24, 24, 32, 32, 32, 32, 32, 32, 32, 32, 32]; +/// All eFuse blocks available on this device. +pub(crate) const BLOCKS: &[EfuseBlock] = &[ + EfuseBlock { + length: 6u8, + read_address: 1611335724u32, + }, + EfuseBlock { + length: 6u8, + read_address: 1611335748u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611335772u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611335804u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611335836u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611335868u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611335900u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611335932u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611335964u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611335996u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1611336028u32, + }, +]; /// Disable programming of individual eFuses pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 32); diff --git a/espflash/src/target/efuse/esp32p4.rs b/espflash/src/target/efuse/esp32p4.rs index 7f40d640..2fd687e6 100644 --- a/espflash/src/target/efuse/esp32p4.rs +++ b/espflash/src/target/efuse/esp32p4.rs @@ -2,15 +2,60 @@ //! //! This file was automatically generated, please do not edit it manually! //! -//! Generated: 2025-06-25 11:06 +//! Generated: 2025-11-19 16:57 //! Version: f7765f0ac3faf4b54f8c1f064307522c #![allow(unused)] -use super::EfuseField; +use super::{EfuseBlock, EfuseField}; -/// Total size in bytes of each block -pub(crate) const BLOCK_SIZES: &[u32] = &[24, 24, 32, 32, 32, 32, 32, 32, 32, 32, 32]; +/// All eFuse blocks available on this device. +pub(crate) const BLOCKS: &[EfuseBlock] = &[ + EfuseBlock { + length: 6u8, + read_address: 1343410220u32, + }, + EfuseBlock { + length: 6u8, + read_address: 1343410244u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1343410268u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1343410300u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1343410332u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1343410364u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1343410396u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1343410428u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1343410460u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1343410492u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1343410524u32, + }, +]; /// Disable programming of individual eFuses pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 32); diff --git a/espflash/src/target/efuse/esp32s2.rs b/espflash/src/target/efuse/esp32s2.rs index 951d9a99..2ea60218 100644 --- a/espflash/src/target/efuse/esp32s2.rs +++ b/espflash/src/target/efuse/esp32s2.rs @@ -2,15 +2,60 @@ //! //! This file was automatically generated, please do not edit it manually! //! -//! Generated: 2025-06-26 09:47 +//! Generated: 2025-11-19 16:57 //! Version: 888a61f6f500d9c7ee0aa32016b0bee7 #![allow(unused)] -use super::EfuseField; +use super::{EfuseBlock, EfuseField}; -/// Total size in bytes of each block -pub(crate) const BLOCK_SIZES: &[u32] = &[24, 24, 32, 32, 32, 32, 32, 32, 32, 32, 32]; +/// All eFuse blocks available on this device. +pub(crate) const BLOCKS: &[EfuseBlock] = &[ + EfuseBlock { + length: 6u8, + read_address: 1061265452u32, + }, + EfuseBlock { + length: 6u8, + read_address: 1061265476u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1061265500u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1061265532u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1061265564u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1061265596u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1061265628u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1061265660u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1061265692u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1061265724u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1061265756u32, + }, +]; /// Disable programming of individual eFuses pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 32); diff --git a/espflash/src/target/efuse/esp32s3.rs b/espflash/src/target/efuse/esp32s3.rs index 1050a6b3..d39beff5 100644 --- a/espflash/src/target/efuse/esp32s3.rs +++ b/espflash/src/target/efuse/esp32s3.rs @@ -2,15 +2,60 @@ //! //! This file was automatically generated, please do not edit it manually! //! -//! Generated: 2025-06-26 09:47 +//! Generated: 2025-11-19 16:57 //! Version: 7127dd097e72bb90d0b790d460993126 #![allow(unused)] -use super::EfuseField; +use super::{EfuseBlock, EfuseField}; -/// Total size in bytes of each block -pub(crate) const BLOCK_SIZES: &[u32] = &[23, 24, 32, 32, 32, 32, 32, 32, 32, 32, 32]; +/// All eFuse blocks available on this device. +pub(crate) const BLOCKS: &[EfuseBlock] = &[ + EfuseBlock { + length: 6u8, + read_address: 1610641452u32, + }, + EfuseBlock { + length: 6u8, + read_address: 1610641476u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610641500u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610641532u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610641564u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610641596u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610641628u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610641660u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610641692u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610641724u32, + }, + EfuseBlock { + length: 8u8, + read_address: 1610641756u32, + }, +]; /// Disable programming of individual eFuses pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 32); diff --git a/espflash/src/target/efuse/mod.rs b/espflash/src/target/efuse/mod.rs index d71cae7f..f8c67054 100644 --- a/espflash/src/target/efuse/mod.rs +++ b/espflash/src/target/efuse/mod.rs @@ -15,6 +15,16 @@ pub mod esp32p4; pub mod esp32s2; pub mod esp32s3; +#[derive(Clone, Copy)] +pub(crate) struct EfuseBlock { + // Number of registers that this block contains. + // + // Each register is a single 4-byte word. + pub(crate) length: u8, + // Read address for this eFuse block. + pub(crate) read_address: u32, +} + /// An eFuse field which can be read from a target device. #[allow(unused)] #[derive(Debug, Clone, serde::Deserialize)] diff --git a/espflash/src/target/mod.rs b/espflash/src/target/mod.rs index 101f5d90..7013dab6 100644 --- a/espflash/src/target/mod.rs +++ b/espflash/src/target/mod.rs @@ -20,6 +20,7 @@ pub use self::flash_target::{ use crate::{ Error, flasher::{FLASH_WRITE_SIZE, FlashFrequency}, + target::efuse::EfuseBlock, }; #[cfg(feature = "serialport")] use crate::{connection::Connection, flasher::SpiAttachParams, target::efuse::EfuseField}; @@ -397,20 +398,32 @@ impl Chip { } } + /// Returns the eFuse block definition of the specified block. + fn block(&self, block: u8) -> Result { + let blocks = match self { + Chip::Esp32 => efuse::esp32::BLOCKS, + Chip::Esp32c2 => efuse::esp32c2::BLOCKS, + Chip::Esp32c3 => efuse::esp32c3::BLOCKS, + Chip::Esp32c5 => efuse::esp32c5::BLOCKS, + Chip::Esp32c6 => efuse::esp32c6::BLOCKS, + Chip::Esp32h2 => efuse::esp32h2::BLOCKS, + Chip::Esp32p4 => efuse::esp32p4::BLOCKS, + Chip::Esp32s2 => efuse::esp32s2::BLOCKS, + Chip::Esp32s3 => efuse::esp32s3::BLOCKS, + }; + + if block as usize >= blocks.len() { + return Err(Error::InvalidEfuseBlock(block)); + } + + Ok(blocks[block as usize]) + } + /// Returns the size of the specified block for the implementing target. /// device pub fn block_size(&self, block: usize) -> u32 { - match self { - Chip::Esp32 => efuse::esp32::BLOCK_SIZES[block], - Chip::Esp32c2 => efuse::esp32c2::BLOCK_SIZES[block], - Chip::Esp32c3 => efuse::esp32c3::BLOCK_SIZES[block], - Chip::Esp32c5 => efuse::esp32c5::BLOCK_SIZES[block], - Chip::Esp32c6 => efuse::esp32c6::BLOCK_SIZES[block], - Chip::Esp32h2 => efuse::esp32h2::BLOCK_SIZES[block], - Chip::Esp32p4 => efuse::esp32p4::BLOCK_SIZES[block], - Chip::Esp32s2 => efuse::esp32s2::BLOCK_SIZES[block], - Chip::Esp32s3 => efuse::esp32s3::BLOCK_SIZES[block], - } + let block = self.block(block as u8).unwrap(); + block.length as u32 * 4 } /// Given an active connection, read the specified field of the eFuse @@ -440,14 +453,8 @@ impl Chip { block: u32, word: u32, ) -> Result { - let block0_addr = self.efuse_reg() + self.block0_offset(); - - let mut block_offset = 0; - for b in 0..block { - block_offset += self.block_size(b as usize); - } - - let addr = block0_addr + block_offset + (word * 0x4); + let block = self.block(block as u8)?; + let addr = block.read_address + (word * 0x4); connection.read_reg(addr) } diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 0a49aae6..b88ede60 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -9,5 +9,6 @@ chrono = "0.4" clap = { version = "4.5", features = ["derive"] } env_logger = "0.11" log = "0.4" +pyo3 = { version = "0.27.1", features = ["auto-initialize"] } serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.9" diff --git a/xtask/src/efuse_generator.rs b/xtask/src/efuse_generator.rs index 65c75ba8..9e53b881 100644 --- a/xtask/src/efuse_generator.rs +++ b/xtask/src/efuse_generator.rs @@ -1,6 +1,6 @@ use std::{ cmp::Ordering, - collections::{BTreeMap, HashMap}, + collections::HashMap, ffi::OsStr, fs::{self, OpenOptions}, io::{BufWriter, Write}, @@ -9,6 +9,10 @@ use std::{ }; use clap::{Args, Parser}; +use pyo3::{ + prelude::{PyResult, Python}, + types::{PyAnyMethods as _, PyList, PyTuple}, +}; type Result = std::result::Result>; @@ -37,7 +41,7 @@ const HEADER: &str = r#" #![allow(unused)] -use super::EfuseField; +use super::{EfuseBlock, EfuseField}; "#; @@ -95,7 +99,7 @@ pub(crate) fn generate_efuse_fields(workspace: &Path, args: GenerateEfuseFieldsA let mut efuse_fields = parse_efuse_fields(&efuse_yaml_path)?; process_efuse_definitions(&mut efuse_fields)?; - generate_efuse_definitions(&espflash_path, efuse_fields)?; + generate_efuse_definitions(&espflash_path, &args.esptool_path, efuse_fields)?; Command::new("cargo") .args(["+nightly", "fmt"]) @@ -166,7 +170,11 @@ fn process_efuse_definitions(efuse_fields: &mut EfuseFields) -> Result<()> { Ok(()) } -fn generate_efuse_definitions(espflash_path: &Path, efuse_fields: EfuseFields) -> Result<()> { +fn generate_efuse_definitions( + espflash_path: &Path, + esptool_path: &Path, + efuse_fields: EfuseFields, +) -> Result<()> { let targets_efuse_path = espflash_path .join("src") .join("target") @@ -195,43 +203,75 @@ fn generate_efuse_definitions(espflash_path: &Path, efuse_fields: EfuseFields) - .trim_start() )?; - generate_efuse_block_sizes(&mut writer, &yaml.fields)?; + generate_efuse_blocks(&mut writer, esptool_path, &chip)?; generate_efuse_constants(&mut writer, &yaml.fields)?; } Ok(()) } -fn generate_efuse_block_sizes( +pub(crate) fn generate_efuse_blocks( writer: &mut dyn Write, - fields: &HashMap, + esptool_path: &Path, + chip: &str, ) -> Result<()> { - let mut field_attrs = fields.values().collect::>(); - field_attrs.sort(); - - let block_sizes = field_attrs - .chunk_by(|a, b| a.block == b.block) - .enumerate() - .map(|(block, attrs)| { - let last = attrs.last().unwrap(); - let size_bits = last.start + last.len; - assert!(size_bits % 8 == 0); - - (block, size_bits / 8) - }) - .collect::>(); - - writeln!(writer, "/// Total size in bytes of each block")?; - writeln!( + println!("Processing {chip}"); + + write!( writer, - "pub(crate) const BLOCK_SIZES: &[u32] = &[{}];\n", - block_sizes - .values() - .map(|v| v.to_string()) - .collect::>() - .join(", ") + r#"/// All eFuse blocks available on this device. +pub(crate) const BLOCKS: &[EfuseBlock] = &["# )?; + Python::attach(|py| { + let sys = py.import("sys")?; + + let path = sys.getattr("path")?; + path.call_method1("append", (esptool_path,))?; + + let mem_definition = py.import(format!("espefuse.efuse.{chip}.mem_definition"))?; + + let blocks = mem_definition + .getattr("EfuseDefineBlocks")? + .call0()? + .getattr("BLOCKS")?; + let blocks = blocks.cast::()?; + + let mut previous_index = None; + for block in blocks { + let block = block.cast::()?; + + let index: u8 = block.get_item(2)?.extract()?; + let length: u8 = block.get_item(7)?.extract()?; + let read_address: u32 = block.get_item(3)?.extract()?; + + if let Some(previous_index) = previous_index { + assert!( + (previous_index + 1) == index, + "Block indices should be sequential" + ); + } else { + assert!(index == 0, "Block indices should start at 0"); + } + previous_index.replace(index); + + write!( + writer, + r#" + EfuseBlock {{ + length: {length}u8, + read_address: {read_address}u32, + }}, +"#, + )?; + } + + PyResult::Ok(()) + }) + .unwrap(); + + writeln!(writer, r#"];"#)?; + Ok(()) } @@ -242,6 +282,7 @@ fn generate_efuse_constants( let mut sorted = fields.iter().collect::>(); sorted.sort_by(|a, b| (a.1).cmp(b.1)); + writeln!(writer)?; for (name, attrs) in sorted { let EfuseAttrs { block,