diff --git a/.github/workflows/hil.yml b/.github/workflows/hil.yml index deddafc8..91f683dd 100644 --- a/.github/workflows/hil.yml +++ b/.github/workflows/hil.yml @@ -43,7 +43,7 @@ jobs: - name: Install dependencies env: DEBIAN_FRONTEND: noninteractive - run: apt-get update && apt-get -y install curl musl-tools pkg-config + run: apt-get update && apt-get -y install curl musl-tools pkg-config python3-dev python3-intelhex python3-reedsolo python3-rich-click - name: Install toolchain run: | @@ -119,4 +119,4 @@ jobs: echo "$PWD/xtask_app" >> "$GITHUB_PATH" - name: Run all tests - run: xtask run-tests --chip ${{ matrix.board.mcu }} -t 60 --no-build \ No newline at end of file + run: xtask run-tests --chip ${{ matrix.board.mcu }} -t 60 --no-build diff --git a/CHANGELOG.md b/CHANGELOG.md index d9d5f449..80beab9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- Corrected eFuse BLOCK0 definitions for ESP32-C2, ESP32-C3, and ESP32-S3 (#961) +- Corrected eFuse block address calculations. (#971) - Fixed Secure Download Mode detection on ESP32-P4 (#972) - Several fixes in `read_efuse` (#969) 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 c671fc7c..0cdfda1a 100644 --- a/espflash/src/error.rs +++ b/espflash/src/error.rs @@ -363,6 +363,10 @@ pub enum Error { /// The efuse field is larger than 32 bit. #[error("Requested efuse field is larger than 32 bit. Use `read_efuse_le`.")] EfuseFieldTooLarge, + + /// Specified eFuse block does not exist + #[error("specified eFuse block does not exist: {0}")] + InvalidEfuseBlock(u32), } #[cfg(feature = "serialport")] diff --git a/espflash/src/target/efuse/esp32.rs b/espflash/src/target/efuse/esp32.rs index 81d4c1e3..786b2c62 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-11-19 12:31 +//! Generated: 2025-11-26 21:42 //! 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 d4dad029..459cca03 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-11-19 12:31 +//! Generated: 2025-11-26 21:42 //! 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, 12, 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 cfae4715..db463af8 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-11-19 12:31 +//! Generated: 2025-11-26 21:42 //! Version: 4622cf9245401eca0eb1df8122449a6d #![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: 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 af055171..1894046b 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-11-19 12:31 +//! Generated: 2025-11-26 21:42 //! 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 eed1b593..ea6e5be6 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-11-19 12:31 +//! Generated: 2025-11-26 21:42 //! 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 519167dc..854c7ae9 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-11-19 12:31 +//! Generated: 2025-11-26 21:42 //! 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 73fea9b4..5fed110b 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-11-19 12:31 +//! Generated: 2025-11-26 21:42 //! 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 ab61752b..c2809dec 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-11-19 12:31 +//! Generated: 2025-11-26 21:42 //! 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 54e41bea..8e488dfe 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-11-19 12:31 +//! Generated: 2025-11-26 21:42 //! Version: 7127dd097e72bb90d0b790d460993126 #![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: 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..1595073f 100644 --- a/espflash/src/target/efuse/mod.rs +++ b/espflash/src/target/efuse/mod.rs @@ -15,6 +15,17 @@ 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. + #[allow(dead_code)] + 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 c789bd21..928da195 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: u32) -> 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 u32).unwrap(); + block.length as u32 * 4 } /// Given an active connection, read the specified field of the eFuse @@ -458,7 +471,10 @@ impl Chip { let bit_end = std::cmp::min(bit_count, (bytes.len() * 8) as u32) + bit_off; let mut last_word_off = bit_off / 32; - let mut last_word = read_raw(connection, self.block_address(block) + last_word_off * 4)?; + let mut last_word = read_raw( + connection, + self.block(block)?.read_address + last_word_off * 4, + )?; let word_bit_off = bit_off % 32; let word_bit_ext = 32 - word_bit_off; @@ -468,7 +484,10 @@ impl Chip { if word_off != last_word_off { // Read a new word: last_word_off = word_off; - last_word = read_raw(connection, self.block_address(block) + last_word_off * 4)?; + last_word = read_raw( + connection, + self.block(block)?.read_address + last_word_off * 4, + )?; } let mut word = last_word >> word_bit_off; @@ -478,7 +497,10 @@ impl Chip { if word_bit_len > word_bit_ext { // Read the next word: last_word_off = word_off; - last_word = read_raw(connection, self.block_address(block) + last_word_off * 4)?; + last_word = read_raw( + connection, + self.block(block)?.read_address + last_word_off * 4, + )?; // Append bits from a beginning of the next word: word |= last_word.wrapping_shl(32 - word_bit_off); }; @@ -507,18 +529,6 @@ impl Chip { Ok(unsafe { output.assume_init() }) } - #[cfg(feature = "serialport")] - fn block_address(&self, block: u32) -> u32 { - 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); - } - - block0_addr + block_offset - } - /// Read the raw word in the specified eFuse block, without performing any /// bit-shifting or masking of the read value. #[cfg(feature = "serialport")] @@ -528,7 +538,7 @@ impl Chip { block: u32, word: u32, ) -> Result { - let addr = self.block_address(block) + (word * 0x4); + let addr = self.block(block)?.read_address + (word * 0x4); connection.read_reg(addr) } diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 0a49aae6..fceff61b 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 c389be96..adb3c979 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,47 +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); - - // not all bits for all blocks are defined, this is to avoid - // ending up with block sizes like 23 or 11 - // - // while this fixes the problem, it's not ideal to rely on this - (block, ((size_bits / 8).div_ceil(4)) * 4) - }) - .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.as_os_str(),))?; + + 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(()) } @@ -246,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,