From 4de0ba66da63ad9c222c5952384dff5ef7b6c890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20L=C3=B6thberg?= Date: Thu, 13 Nov 2025 13:10:19 +0100 Subject: [PATCH] Replace old BLOCK_SIZES with definitions of the blocks themselves The actual block definitions only exist within Python classes so this commit uses PyO3 to import the esptool.py eFuse block definitions and generates arrays of the length and read address of each eFuse block. We need the actual read address here rather than using the old offset method because not all eFuse blocks are sequential. (On ESP32 the block 0 read registers are followed by the block 0 write registers.) --- Cargo.lock | 92 ++++++++++++++++++++++++ espflash/src/error.rs | 4 ++ espflash/src/target/efuse/esp32.rs | 25 +++++-- espflash/src/target/efuse/esp32c2.rs | 25 +++++-- espflash/src/target/efuse/esp32c3.rs | 53 ++++++++++++-- espflash/src/target/efuse/esp32c5.rs | 53 ++++++++++++-- espflash/src/target/efuse/esp32c6.rs | 53 ++++++++++++-- espflash/src/target/efuse/esp32h2.rs | 53 ++++++++++++-- espflash/src/target/efuse/esp32p4.rs | 53 ++++++++++++-- espflash/src/target/efuse/esp32s2.rs | 53 ++++++++++++-- espflash/src/target/efuse/esp32s3.rs | 53 ++++++++++++-- espflash/src/target/efuse/mod.rs | 10 +++ espflash/src/target/mod.rs | 45 +++++++----- xtask/Cargo.toml | 1 + xtask/src/efuse_generator.rs | 101 +++++++++++++++++++-------- 15 files changed, 589 insertions(+), 85 deletions(-) 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,