Skip to content

Commit cd38d2e

Browse files
committed
efuse: Implement write support
1 parent f367a32 commit cd38d2e

File tree

16 files changed

+2126
-118
lines changed

16 files changed

+2126
-118
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

espflash/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ log = "0.4"
5050
md-5 = "0.10"
5151
miette = "7.6"
5252
object = "0.37"
53+
reed-solomon = "0.2.1"
5354
regex = { version = "1.11", optional = true }
5455
serde = { version = "1.0", features = ["derive"] }
5556
serialport = { version = "4.7", default-features = false, optional = true }

espflash/src/connection/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,19 @@ impl Connection {
683683
Ok(())
684684
}
685685

686+
/// Updates a register by applying the new value to the masked out portion
687+
/// of the old value.
688+
// TODO: Is this the API we want? For many cases it's convenient to let this
689+
// function handle it, but the resulting API feels kind of
690+
// non-obvious.
691+
pub(crate) fn update_reg(&mut self, addr: u32, mask: u32, new_value: u32) -> Result<(), Error> {
692+
let masked_new_value = new_value.checked_shl(mask.trailing_zeros()).unwrap_or(0) & mask;
693+
694+
let masked_old_value = self.read_reg(addr)? & !mask;
695+
696+
self.write_reg(addr, masked_old_value | masked_new_value, None)
697+
}
698+
686699
/// Reads a register command with a timeout.
687700
pub(crate) fn read(&mut self, len: usize) -> Result<Option<Vec<u8>>, Error> {
688701
let mut tmp = Vec::with_capacity(1024);

espflash/src/error.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,18 @@ pub enum Error {
367367
/// Specified eFuse block does not exist
368368
#[error("specified eFuse block does not exist: {0}")]
369369
InvalidEfuseBlock(u32),
370+
371+
/// Unsupported crystall frequency
372+
#[error("Unsupported crystal frequency: {0}")]
373+
UnsupportedXtalFrequency(String),
374+
375+
/// Failed to write eFuse
376+
#[error("Failed to write eFuse: {0}")]
377+
WritingEfuseFailed(String),
378+
379+
/// Timed out while waiting for eFuse controller to return to idle
380+
#[error("Timed out while waiting for eFuse controller to return to idle")]
381+
TimedOutWaitingForEfuseController,
370382
}
371383

372384
#[cfg(feature = "serialport")]

espflash/src/target/efuse/esp32.rs

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//!
33
//! This file was automatically generated, please do not edit it manually!
44
//!
5-
//! Generated: 2025-11-26 21:42
5+
//! Generated: 2025-12-05 18:05
66
//! Version: 369d2d860d34e777c0f7d545a7dfc3c4
77
88
#![allow(unused)]
@@ -12,23 +12,63 @@ use super::{EfuseBlock, EfuseField};
1212
/// All eFuse blocks available on this device.
1313
pub(crate) const BLOCKS: &[EfuseBlock] = &[
1414
EfuseBlock {
15+
index: 0u8,
1516
length: 7u8,
16-
read_address: 1073061888u32,
17+
read_address: 0x3ff5a000u32,
18+
write_address: 0x3ff5a01cu32,
1719
},
1820
EfuseBlock {
21+
index: 1u8,
1922
length: 8u8,
20-
read_address: 1073061944u32,
23+
read_address: 0x3ff5a038u32,
24+
write_address: 0x3ff5a098u32,
2125
},
2226
EfuseBlock {
27+
index: 2u8,
2328
length: 8u8,
24-
read_address: 1073061976u32,
29+
read_address: 0x3ff5a058u32,
30+
write_address: 0x3ff5a0b8u32,
2531
},
2632
EfuseBlock {
33+
index: 3u8,
2734
length: 8u8,
28-
read_address: 1073062008u32,
35+
read_address: 0x3ff5a078u32,
36+
write_address: 0x3ff5a0d8u32,
2937
},
3038
];
3139

40+
/// Defined eFuse registers and commands
41+
pub(crate) mod defines {
42+
use super::super::EfuseBlockErrors;
43+
pub(crate) const BLOCK_ERRORS: &[EfuseBlockErrors] = &[];
44+
pub(crate) const EFUSE_CMD_READ: u32 = 0x1;
45+
pub(crate) const EFUSE_BLK0_RDATA3_REG: u32 = 0x3ff5a00c;
46+
pub(crate) const EFUSE_MEM_SIZE: u32 = 0x120;
47+
pub(crate) const CODING_SCHEME_NONE_RECOVERY: u32 = 0x3;
48+
pub(crate) const EFUSE_CMD_WRITE: u32 = 0x2;
49+
pub(crate) const EFUSE_CLK_SEL0_MASK: u32 = 0xff;
50+
pub(crate) const EFUSE_REG_DEC_STATUS_MASK: u32 = 0xfff;
51+
pub(crate) const CODING_SCHEME_34: u32 = 0x1;
52+
pub(crate) const EFUSE_CLK_REG: u32 = 0x3ff5a0f8;
53+
pub(crate) const EFUSE_CODING_SCHEME_WORD: u32 = 0x6;
54+
pub(crate) const EFUSE_DAC_CLK_DIV_MASK: u32 = 0xff;
55+
pub(crate) const EFUSE_CODING_SCHEME_MASK: u32 = 0x3;
56+
pub(crate) const EFUSE_CLK_SEL1_MASK: u32 = 0xff00;
57+
pub(crate) const CODING_SCHEME_RS: u32 = 0x4;
58+
pub(crate) const EFUSE_RD_CHIP_VER_REV2: u32 = 0x100000;
59+
pub(crate) const EFUSE_REG_CONF: u32 = 0x3ff5a0fc;
60+
pub(crate) const EFUSE_RD_CHIP_VER_REV1: u32 = 0x8000;
61+
pub(crate) const EFUSE_CONF_WRITE: u32 = 0x5a5a;
62+
pub(crate) const EFUSE_CMD_OP_MASK: u32 = 0x3;
63+
pub(crate) const CODING_SCHEME_NONE: u32 = 0x0;
64+
pub(crate) const CODING_SCHEME_REPEAT: u32 = 0x2;
65+
pub(crate) const EFUSE_BLK0_RDATA5_REG: u32 = 0x3ff5a014;
66+
pub(crate) const EFUSE_CONF_READ: u32 = 0x5aa5;
67+
pub(crate) const EFUSE_REG_DEC_STATUS: u32 = 0x3ff5a11c;
68+
pub(crate) const EFUSE_DAC_CONF_REG: u32 = 0x3ff5a118;
69+
pub(crate) const EFUSE_REG_CMD: u32 = 0x3ff5a104;
70+
}
71+
3272
/// Efuse write disable mask
3373
pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 16);
3474
/// Disable reading from BlOCK1-3

espflash/src/target/efuse/esp32c2.rs

Lines changed: 81 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//!
33
//! This file was automatically generated, please do not edit it manually!
44
//!
5-
//! Generated: 2025-11-26 21:42
5+
//! Generated: 2025-12-05 18:05
66
//! Version: 897499b0349a608b895d467abbcf006b
77
88
#![allow(unused)]
@@ -12,23 +12,99 @@ use super::{EfuseBlock, EfuseField};
1212
/// All eFuse blocks available on this device.
1313
pub(crate) const BLOCKS: &[EfuseBlock] = &[
1414
EfuseBlock {
15+
index: 0u8,
1516
length: 2u8,
16-
read_address: 1610647596u32,
17+
read_address: 0x6000882cu32,
18+
write_address: 0x60008800u32,
1719
},
1820
EfuseBlock {
21+
index: 1u8,
1922
length: 3u8,
20-
read_address: 1610647604u32,
23+
read_address: 0x60008834u32,
24+
write_address: 0x60008800u32,
2125
},
2226
EfuseBlock {
27+
index: 2u8,
2328
length: 8u8,
24-
read_address: 1610647616u32,
29+
read_address: 0x60008840u32,
30+
write_address: 0x60008800u32,
2531
},
2632
EfuseBlock {
33+
index: 3u8,
2734
length: 8u8,
28-
read_address: 1610647648u32,
35+
read_address: 0x60008860u32,
36+
write_address: 0x60008800u32,
2937
},
3038
];
3139

40+
/// Defined eFuse registers and commands
41+
pub(crate) mod defines {
42+
use super::super::EfuseBlockErrors;
43+
pub(crate) const BLOCK_ERRORS: &[EfuseBlockErrors] = &[
44+
EfuseBlockErrors {
45+
err_num_reg: 0x60008880u32,
46+
err_num_mask: None,
47+
err_num_offset: None,
48+
fail_bit_reg: 0x60008880u32,
49+
fail_bit_offset: None,
50+
},
51+
EfuseBlockErrors {
52+
err_num_reg: 0x60008884u32,
53+
err_num_mask: Some(0x7u32),
54+
err_num_offset: Some(0x0u32),
55+
fail_bit_reg: 0x60008884u32,
56+
fail_bit_offset: Some(0x3u32),
57+
},
58+
EfuseBlockErrors {
59+
err_num_reg: 0x60008884u32,
60+
err_num_mask: Some(0x7u32),
61+
err_num_offset: Some(0x4u32),
62+
fail_bit_reg: 0x60008884u32,
63+
fail_bit_offset: Some(0x7u32),
64+
},
65+
EfuseBlockErrors {
66+
err_num_reg: 0x60008884u32,
67+
err_num_mask: Some(0x7u32),
68+
err_num_offset: Some(0x8u32),
69+
fail_bit_reg: 0x60008884u32,
70+
fail_bit_offset: Some(0xbu32),
71+
},
72+
];
73+
pub(crate) const EFUSE_DAC_NUM_M: u32 = 0x1fe00;
74+
pub(crate) const EFUSE_PGM_CMD: u32 = 0x2;
75+
pub(crate) const EFUSE_PWR_ON_NUM_M: u32 = 0xffff00;
76+
pub(crate) const EFUSE_DAC_NUM_S: u32 = 0x9;
77+
pub(crate) const EFUSE_RD_RS_ERR_REG: u32 = 0x60008884;
78+
pub(crate) const EFUSE_PGM_DATA0_REG: u32 = 0x60008800;
79+
pub(crate) const EFUSE_READ_CMD: u32 = 0x1;
80+
pub(crate) const EFUSE_PWR_OFF_NUM_M: u32 = 0xffff;
81+
pub(crate) const EFUSE_WR_TIM_CONF0_REG: u32 = 0x60008910;
82+
pub(crate) const EFUSE_WR_TIM_CONF1_REG: u32 = 0x60008914;
83+
pub(crate) const EFUSE_MEM_SIZE: u32 = 0x200;
84+
pub(crate) const CODING_SCHEME_34: u32 = 0x1;
85+
pub(crate) const CODING_SCHEME_NONE: u32 = 0x0;
86+
pub(crate) const EFUSE_PWR_OFF_NUM_S: u32 = 0x0;
87+
pub(crate) const CODING_SCHEME_REPEAT: u32 = 0x2;
88+
pub(crate) const EFUSE_TPGM_INACTIVE_S: u32 = 0x8;
89+
pub(crate) const EFUSE_CLK_REG: u32 = 0x60008888;
90+
pub(crate) const CODING_SCHEME_NONE_RECOVERY: u32 = 0x3;
91+
pub(crate) const EFUSE_PWR_ON_NUM_S: u32 = 0x8;
92+
pub(crate) const EFUSE_PGM_CMD_MASK: u32 = 0x3;
93+
pub(crate) const EFUSE_WRITE_OP_CODE: u32 = 0x5a5a;
94+
pub(crate) const EFUSE_STATUS_REG: u32 = 0x60008890;
95+
pub(crate) const EFUSE_CMD_REG: u32 = 0x60008894;
96+
pub(crate) const EFUSE_CONF_REG: u32 = 0x6000888c;
97+
pub(crate) const EFUSE_TPGM_INACTIVE_M: u32 = 0xff00;
98+
pub(crate) const EFUSE_DAC_CONF_REG: u32 = 0x60008908;
99+
pub(crate) const EFUSE_RD_REPEAT_ERR_REG: u32 = 0x60008880;
100+
pub(crate) const CODING_SCHEME_RS: u32 = 0x4;
101+
pub(crate) const EFUSE_DAC_CLK_DIV_S: u32 = 0x0;
102+
pub(crate) const EFUSE_PGM_CHECK_VALUE0_REG: u32 = 0x60008820;
103+
pub(crate) const EFUSE_WR_TIM_CONF2_REG: u32 = 0x60008918;
104+
pub(crate) const EFUSE_DAC_CLK_DIV_M: u32 = 0xff;
105+
pub(crate) const EFUSE_READ_OP_CODE: u32 = 0x5aa5;
106+
}
107+
32108
/// Disable programming of individual eFuses
33109
pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 8);
34110
///

0 commit comments

Comments
 (0)