Skip to content

Commit 7025dd4

Browse files
committed
Create and implement a trait for reading eFuse values
1 parent b754206 commit 7025dd4

File tree

7 files changed

+116
-66
lines changed

7 files changed

+116
-66
lines changed

espflash/src/chip/esp32/esp32.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::ops::Range;
22

33
use super::Esp32Params;
44
use crate::{
5-
chip::{Chip, ChipType, SpiRegisters},
5+
chip::{Chip, ChipType, ReadEFuse, SpiRegisters},
66
elf::FirmwareImage,
77
image_format::{Esp32BootloaderFormat, ImageFormat, ImageFormatId},
88
Error, PartitionTable,
@@ -76,6 +76,10 @@ impl ChipType for Esp32 {
7676
}
7777
}
7878

79+
impl ReadEFuse for Esp32 {
80+
const EFUSE_REG_BASE: u32 = 0x3ff5a000;
81+
}
82+
7983
#[test]
8084
fn test_esp32_rom() {
8185
use std::fs::read;

espflash/src/chip/esp32/esp32c3.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::ops::Range;
22

33
use super::Esp32Params;
44
use crate::{
5-
chip::{ChipType, SpiRegisters},
5+
chip::{ChipType, ReadEFuse, SpiRegisters},
66
elf::FirmwareImage,
77
image_format::{Esp32BootloaderFormat, ImageFormat, ImageFormatId},
88
Chip, Error, PartitionTable,
@@ -77,3 +77,7 @@ impl ChipType for Esp32c3 {
7777
target.starts_with("riscv32imc-")
7878
}
7979
}
80+
81+
impl ReadEFuse for Esp32c3 {
82+
const EFUSE_REG_BASE: u32 = 0x60008830;
83+
}

espflash/src/chip/esp32/esp32s2.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::ops::Range;
22

33
use super::Esp32Params;
44
use crate::{
5-
chip::{ChipType, SpiRegisters},
5+
chip::{ChipType, ReadEFuse, SpiRegisters},
66
elf::FirmwareImage,
77
image_format::{Esp32BootloaderFormat, ImageFormat, ImageFormatId},
88
Chip, Error, PartitionTable,
@@ -75,3 +75,7 @@ impl ChipType for Esp32s2 {
7575
target.starts_with("xtensa-esp32s2-")
7676
}
7777
}
78+
79+
impl ReadEFuse for Esp32s2 {
80+
const EFUSE_REG_BASE: u32 = 0x3F41A030;
81+
}

espflash/src/chip/esp8266.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::ops::Range;
22

33
use super::ChipType;
44
use crate::{
5-
chip::SpiRegisters,
5+
chip::{ReadEFuse, SpiRegisters},
66
elf::FirmwareImage,
77
error::UnsupportedImageFormatError,
88
image_format::{Esp8266Format, ImageFormat, ImageFormatId},
@@ -51,11 +51,16 @@ impl ChipType for Esp8266 {
5151
}
5252
}
5353

54+
impl ReadEFuse for Esp8266 {
55+
const EFUSE_REG_BASE: u32 = 0x3ff00050;
56+
}
57+
5458
#[test]
5559
fn test_esp8266_rom() {
56-
use pretty_assertions::assert_eq;
5760
use std::fs::read;
5861

62+
use pretty_assertions::assert_eq;
63+
5964
let input_bytes = read("./tests/data/esp8266").unwrap();
6065
let expected_bin = read("./tests/data/esp8266.bin").unwrap();
6166

espflash/src/chip/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::ops::Range;
33
use strum_macros::Display;
44

55
use crate::{
6+
connection::Connection,
67
elf::FirmwareImage,
78
error::ChipDetectError,
89
flash_target::{Esp32Target, Esp8266Target, FlashTarget, RamTarget},
@@ -40,6 +41,16 @@ pub trait ChipType {
4041
fn supports_target(target: &str) -> bool;
4142
}
4243

44+
pub trait ReadEFuse {
45+
const EFUSE_REG_BASE: u32;
46+
47+
/// Given an active connection, read the nth word of the eFuse region.
48+
fn read_efuse(&self, connection: &mut Connection, n: u32) -> Result<u32, Error> {
49+
let reg = Self::EFUSE_REG_BASE + (n * 0x4);
50+
connection.read_reg(reg)
51+
}
52+
}
53+
4354
pub struct SpiRegisters {
4455
base: u32,
4556
usr_offset: u32,
@@ -194,4 +205,13 @@ impl Chip {
194205
Chip::Esp8266 => Esp8266::SUPPORTED_TARGETS,
195206
}
196207
}
208+
209+
pub fn read_efuse(&self, connection: &mut Connection, n: u32) -> Result<u32, Error> {
210+
match self {
211+
Chip::Esp32 => Esp32.read_efuse(connection, n),
212+
Chip::Esp32c3 => Esp32c3.read_efuse(connection, n),
213+
Chip::Esp32s2 => Esp32s2.read_efuse(connection, n),
214+
Chip::Esp8266 => Esp8266.read_efuse(connection, n),
215+
}
216+
}
197217
}

espflash/src/connection.rs

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
use std::io::Write;
2-
use std::thread::sleep;
3-
use std::time::Duration;
4-
5-
use crate::encoder::SlipEncoder;
6-
use crate::error::{ConnectionError, Error, ResultExt, RomError, RomErrorKind};
7-
use crate::flasher::Command;
8-
use binread::io::Cursor;
9-
use binread::{BinRead, BinReaderExt};
1+
use std::{io::Write, thread::sleep, time::Duration};
2+
3+
use binread::{io::Cursor, BinRead, BinReaderExt};
4+
use bytemuck::{bytes_of, Pod, Zeroable};
105
use serial::{BaudRate, SerialPort, SerialPortSettings, SystemPort};
116
use slip_codec::Decoder;
127

8+
use crate::{
9+
encoder::SlipEncoder,
10+
error::{ConnectionError, Error, ResultExt, RomError, RomErrorKind},
11+
flasher::Command,
12+
};
13+
1314
pub struct Connection {
1415
serial: SystemPort,
1516
decoder: Decoder,
@@ -25,6 +26,15 @@ pub struct CommandResponse {
2526
pub error: u8,
2627
}
2728

29+
#[derive(Zeroable, Pod, Copy, Clone, Debug)]
30+
#[repr(C)]
31+
struct WriteRegParams {
32+
addr: u32,
33+
value: u32,
34+
mask: u32,
35+
delay_us: u32,
36+
}
37+
2838
impl Connection {
2939
pub fn new(serial: SystemPort) -> Self {
3040
Connection {
@@ -143,6 +153,26 @@ impl Connection {
143153
Err(Error::Connection(ConnectionError::ConnectionFailed))
144154
}
145155

156+
pub fn read_reg(&mut self, reg: u32) -> Result<u32, Error> {
157+
self.with_timeout(Command::ReadReg.timeout(), |connection| {
158+
connection.command(Command::ReadReg, &reg.to_le_bytes()[..], 0)
159+
})
160+
}
161+
162+
pub fn write_reg(&mut self, addr: u32, value: u32, mask: Option<u32>) -> Result<(), Error> {
163+
let params = WriteRegParams {
164+
addr,
165+
value,
166+
mask: mask.unwrap_or(0xFFFFFFFF),
167+
delay_us: 0,
168+
};
169+
self.with_timeout(Command::WriteReg.timeout(), |connection| {
170+
connection.command(Command::WriteReg, bytes_of(&params), 0)
171+
})?;
172+
173+
Ok(())
174+
}
175+
146176
fn read(&mut self) -> Result<Vec<u8>, Error> {
147177
let mut output = Vec::with_capacity(1024);
148178
self.decoder.decode(&mut self.serial, &mut output)?;

espflash/src/flasher.rs

Lines changed: 35 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1+
use std::{borrow::Cow, thread::sleep};
2+
13
use bytemuck::{__core::time::Duration, bytes_of, Pod, Zeroable};
24
use serial::{BaudRate, SystemPort};
35
use strum_macros::Display;
46

5-
use std::thread::sleep;
6-
7-
use crate::elf::RomSegment;
8-
use crate::error::{ConnectionError, ElfError, FlashDetectError, ResultExt, RomError};
97
use crate::{
10-
chip::Chip, connection::Connection, elf::FirmwareImage, encoder::SlipEncoder,
11-
error::RomErrorKind, Error, PartitionTable,
8+
chip::Chip,
9+
connection::Connection,
10+
elf::{FirmwareImage, RomSegment},
11+
encoder::SlipEncoder,
12+
error::{ConnectionError, ElfError, FlashDetectError, ResultExt, RomError, RomErrorKind},
13+
Error, PartitionTable,
1214
};
13-
use std::borrow::Cow;
1415

1516
pub(crate) type Encoder<'a> = SlipEncoder<'a, SystemPort>;
1617

@@ -187,15 +188,6 @@ struct BeginParams {
187188
encrypted: u32,
188189
}
189190

190-
#[derive(Zeroable, Pod, Copy, Clone, Debug)]
191-
#[repr(C)]
192-
struct WriteRegParams {
193-
addr: u32,
194-
value: u32,
195-
mask: u32,
196-
delay_us: u32,
197-
}
198-
199191
#[derive(Zeroable, Pod, Copy, Clone)]
200192
#[repr(C)]
201193
struct EntryParams {
@@ -255,7 +247,7 @@ impl Flasher {
255247
}
256248

257249
fn chip_detect(&mut self) -> Result<(), Error> {
258-
let magic = self.read_reg(CHIP_DETECT_MAGIC_REG_ADDR)?;
250+
let magic = self.connection.read_reg(CHIP_DETECT_MAGIC_REG_ADDR)?;
259251
let chip = Chip::from_magic(magic)?;
260252

261253
self.chip = chip;
@@ -375,8 +367,8 @@ impl Flasher {
375367

376368
let spi_registers = self.chip.spi_registers();
377369

378-
let old_spi_usr = self.read_reg(spi_registers.usr())?;
379-
let old_spi_usr2 = self.read_reg(spi_registers.usr2())?;
370+
let old_spi_usr = self.connection.read_reg(spi_registers.usr())?;
371+
let old_spi_usr2 = self.connection.read_reg(spi_registers.usr2())?;
380372

381373
let mut flags = 1 << 31;
382374
if !data.is_empty() {
@@ -386,17 +378,21 @@ impl Flasher {
386378
flags |= 1 << 28;
387379
}
388380

389-
self.write_reg(spi_registers.usr(), flags, None)?;
390-
self.write_reg(spi_registers.usr2(), 7 << 28 | command as u32, None)?;
381+
self.connection
382+
.write_reg(spi_registers.usr(), flags, None)?;
383+
self.connection
384+
.write_reg(spi_registers.usr2(), 7 << 28 | command as u32, None)?;
391385

392386
if let (Some(mosi_data_length), Some(miso_data_length)) =
393387
(spi_registers.mosi_length(), spi_registers.miso_length())
394388
{
395389
if !data.is_empty() {
396-
self.write_reg(mosi_data_length, data.len() as u32 * 8 - 1, None)?;
390+
self.connection
391+
.write_reg(mosi_data_length, data.len() as u32 * 8 - 1, None)?;
397392
}
398393
if read_bits > 0 {
399-
self.write_reg(miso_data_length, read_bits - 1, None)?;
394+
self.connection
395+
.write_reg(miso_data_length, read_bits - 1, None)?;
400396
}
401397
} else {
402398
let mosi_mask = if data.is_empty() {
@@ -405,26 +401,32 @@ impl Flasher {
405401
data.len() as u32 * 8 - 1
406402
};
407403
let miso_mask = if read_bits == 0 { 0 } else { read_bits - 1 };
408-
self.write_reg(spi_registers.usr1(), miso_mask << 8 | mosi_mask << 17, None)?;
404+
self.connection.write_reg(
405+
spi_registers.usr1(),
406+
miso_mask << 8 | mosi_mask << 17,
407+
None,
408+
)?;
409409
}
410410

411411
if data.is_empty() {
412-
self.write_reg(spi_registers.w0(), 0, None)?;
412+
self.connection.write_reg(spi_registers.w0(), 0, None)?;
413413
} else {
414414
for (i, bytes) in data.chunks(4).enumerate() {
415415
let mut data_bytes = [0; 4];
416416
data_bytes[0..bytes.len()].copy_from_slice(bytes);
417417
let data = u32::from_le_bytes(data_bytes);
418-
self.write_reg(spi_registers.w0() + i as u32, data, None)?;
418+
self.connection
419+
.write_reg(spi_registers.w0() + i as u32, data, None)?;
419420
}
420421
}
421422

422-
self.write_reg(spi_registers.cmd(), 1 << 18, None)?;
423+
self.connection
424+
.write_reg(spi_registers.cmd(), 1 << 18, None)?;
423425

424426
let mut i = 0;
425427
loop {
426428
sleep(Duration::from_millis(1));
427-
if self.read_reg(spi_registers.usr())? & (1 << 18) == 0 {
429+
if self.connection.read_reg(spi_registers.usr())? & (1 << 18) == 0 {
428430
break;
429431
}
430432
i += 1;
@@ -433,32 +435,13 @@ impl Flasher {
433435
}
434436
}
435437

436-
let result = self.read_reg(spi_registers.w0())?;
437-
self.write_reg(spi_registers.usr(), old_spi_usr, None)?;
438-
self.write_reg(spi_registers.usr2(), old_spi_usr2, None)?;
439-
440-
Ok(result)
441-
}
442-
443-
fn read_reg(&mut self, reg: u32) -> Result<u32, Error> {
438+
let result = self.connection.read_reg(spi_registers.w0())?;
444439
self.connection
445-
.with_timeout(Command::ReadReg.timeout(), |connection| {
446-
connection.command(Command::ReadReg, &reg.to_le_bytes()[..], 0)
447-
})
448-
}
449-
450-
fn write_reg(&mut self, addr: u32, value: u32, mask: Option<u32>) -> Result<(), Error> {
451-
let params = WriteRegParams {
452-
addr,
453-
value,
454-
mask: mask.unwrap_or(0xFFFFFFFF),
455-
delay_us: 0,
456-
};
440+
.write_reg(spi_registers.usr(), old_spi_usr, None)?;
457441
self.connection
458-
.with_timeout(Command::WriteReg.timeout(), |connection| {
459-
connection.command(Command::WriteReg, bytes_of(&params), 0)
460-
})?;
461-
Ok(())
442+
.write_reg(spi_registers.usr2(), old_spi_usr2, None)?;
443+
444+
Ok(result)
462445
}
463446

464447
/// The chip type that the flasher is connected to

0 commit comments

Comments
 (0)