Skip to content

Commit 18a0f05

Browse files
authored
Merge pull request #65 from jessebraham/efuse
Add a method of reading eFuse values
2 parents 12d989f + 4286006 commit 18a0f05

File tree

10 files changed

+310
-140
lines changed

10 files changed

+310
-140
lines changed

cargo-espflash/src/main.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
use crate::cargo_config::parse_cargo_config;
2-
use crate::error::UnsupportedTargetError;
1+
use std::{
2+
fs,
3+
path::PathBuf,
4+
process::{exit, Command, ExitStatus, Stdio},
5+
string::ToString,
6+
};
7+
38
use cargo_metadata::Message;
49
use clap::{App, Arg, SubCommand};
510
use error::Error;
@@ -8,12 +13,8 @@ use miette::{IntoDiagnostic, Result, WrapErr};
813
use monitor::monitor;
914
use package_metadata::CargoEspFlashMeta;
1015
use serial::{BaudRate, FlowControl, SerialPort};
11-
use std::{
12-
fs,
13-
path::PathBuf,
14-
process::{exit, Command, ExitStatus, Stdio},
15-
string::ToString,
16-
};
16+
17+
use crate::{cargo_config::parse_cargo_config, error::UnsupportedTargetError};
1718

1819
mod cargo_config;
1920
mod error;
@@ -23,6 +24,7 @@ mod package_metadata;
2324

2425
fn main() -> Result<()> {
2526
miette::set_panic_hook();
27+
2628
let mut app = App::new(env!("CARGO_PKG_NAME"))
2729
.bin_name("cargo")
2830
.subcommand(
@@ -139,11 +141,13 @@ fn main() -> Result<()> {
139141
None
140142
};
141143

142-
// Connect the Flasher to the target device. If the '--board-info' flag has been
143-
// provided, display the board info and terminate the application.
144+
// Connect the Flasher to the target device and print the board information
145+
// upon connection. If the '--board-info' flag has been provided, we have
146+
// nothing left to do so exit early.
144147
let mut flasher = Flasher::connect(serial, speed)?;
148+
flasher.board_info()?;
149+
145150
if matches.is_present("board_info") {
146-
board_info(&flasher);
147151
return Ok(());
148152
}
149153

@@ -191,6 +195,7 @@ fn main() -> Result<()> {
191195
} else {
192196
flasher.load_elf_to_flash(&elf_data, bootloader, partition_table)?;
193197
}
198+
println!("\nFlashing has completed!");
194199

195200
if matches.is_present("monitor") {
196201
monitor(flasher.into_serial()).into_diagnostic()?;
@@ -200,11 +205,6 @@ fn main() -> Result<()> {
200205
Ok(())
201206
}
202207

203-
fn board_info(flasher: &Flasher) {
204-
println!("Chip type: {}", flasher.chip());
205-
println!("Flash size: {}", flasher.flash_size());
206-
}
207-
208208
fn build(
209209
release: bool,
210210
example: Option<&str>,

espflash/src/chip/esp32.rs renamed to espflash/src/chip/esp32/esp32.rs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
use crate::chip::Esp32Params;
1+
use std::ops::Range;
22

3-
use crate::image_format::{Esp32BootloaderFormat, ImageFormat, ImageFormatId};
3+
use super::Esp32Params;
44
use crate::{
5-
chip::{Chip, ChipType, SpiRegisters},
5+
chip::{Chip, ChipType, ReadEFuse, SpiRegisters},
6+
connection::Connection,
67
elf::FirmwareImage,
8+
image_format::{Esp32BootloaderFormat, ImageFormat, ImageFormatId},
79
Error, PartitionTable,
810
};
911

10-
use std::ops::Range;
11-
1212
pub struct Esp32;
1313

1414
const IROM_MAP_START: u32 = 0x400d0000;
@@ -27,12 +27,14 @@ pub const PARAMS: Esp32Params = Esp32Params {
2727
app_addr: 0x10000,
2828
app_size: 0x3f0000,
2929
chip_id: 0,
30-
default_bootloader: include_bytes!("../../bootloader/esp32-bootloader.bin"),
30+
default_bootloader: include_bytes!("../../../bootloader/esp32-bootloader.bin"),
3131
};
3232

3333
impl ChipType for Esp32 {
3434
const CHIP_DETECT_MAGIC_VALUE: u32 = 0x00f01d83;
3535

36+
const UART_CLKDIV_REG: u32 = 0x3ff40014;
37+
3638
const SPI_REGISTERS: SpiRegisters = SpiRegisters {
3739
base: 0x3ff42000,
3840
usr_offset: 0x1c,
@@ -77,6 +79,32 @@ impl ChipType for Esp32 {
7779
}
7880
}
7981

82+
impl ReadEFuse for Esp32 {
83+
const EFUSE_REG_BASE: u32 = 0x3ff5a000;
84+
}
85+
86+
impl Esp32 {
87+
pub fn chip_revision(&self, connection: &mut Connection) -> Result<u32, Error> {
88+
let word3 = self.read_efuse(connection, 3)?;
89+
let word5 = self.read_efuse(connection, 5)?;
90+
91+
let apb_ctrl_date = connection.read_reg(0x3FF6607C)?;
92+
93+
let rev_bit0 = (word3 >> 15) & 0x1 != 0;
94+
let rev_bit1 = (word5 >> 20) & 0x1 != 0;
95+
let rev_bit2 = (apb_ctrl_date >> 31) & 0x1 != 0;
96+
97+
let revision = match (rev_bit0, rev_bit1, rev_bit2) {
98+
(true, true, true) => 3,
99+
(true, true, false) => 2,
100+
(true, false, _) => 1,
101+
(false, _, _) => 0,
102+
};
103+
104+
Ok(revision)
105+
}
106+
}
107+
80108
#[test]
81109
fn test_esp32_rom() {
82110
use std::fs::read;

espflash/src/chip/esp32c3.rs renamed to espflash/src/chip/esp32/esp32c3.rs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
use crate::chip::Esp32Params;
2-
use crate::image_format::{Esp32BootloaderFormat, ImageFormat, ImageFormatId};
1+
use std::ops::Range;
2+
3+
use super::Esp32Params;
34
use crate::{
4-
chip::{ChipType, SpiRegisters},
5+
chip::{ChipType, ReadEFuse, SpiRegisters},
6+
connection::Connection,
57
elf::FirmwareImage,
8+
image_format::{Esp32BootloaderFormat, ImageFormat, ImageFormatId},
69
Chip, Error, PartitionTable,
710
};
811

9-
use std::ops::Range;
10-
1112
pub struct Esp32c3;
1213

1314
const IROM_MAP_START: u32 = 0x42000000;
@@ -26,13 +27,15 @@ pub const PARAMS: Esp32Params = Esp32Params {
2627
app_addr: 0x10000,
2728
app_size: 0x3f0000,
2829
chip_id: 5,
29-
default_bootloader: include_bytes!("../../bootloader/esp32c3-bootloader.bin"),
30+
default_bootloader: include_bytes!("../../../bootloader/esp32c3-bootloader.bin"),
3031
};
3132

3233
impl ChipType for Esp32c3 {
3334
const CHIP_DETECT_MAGIC_VALUE: u32 = 0x6921506f;
3435
const CHIP_DETECT_MAGIC_VALUE2: u32 = 0x1b31506f;
3536

37+
const UART_CLKDIV_REG: u32 = 0x3ff40014;
38+
3639
const SPI_REGISTERS: SpiRegisters = SpiRegisters {
3740
base: 0x60002000,
3841
usr_offset: 0x18,
@@ -53,6 +56,11 @@ impl ChipType for Esp32c3 {
5356
const SUPPORTED_TARGETS: &'static [&'static str] =
5457
&["riscv32imc-uknown-none-elf", "riscv32imc-esp-espidf"];
5558

59+
fn crystal_freq(&self, _connection: &mut Connection) -> Result<u32, Error> {
60+
// The ESP32-C3's XTAL has a fixed frequency of 40MHz.
61+
Ok(40)
62+
}
63+
5664
fn get_flash_segments<'a>(
5765
image: &'a FirmwareImage,
5866
bootloader: Option<Vec<u8>>,
@@ -77,3 +85,20 @@ impl ChipType for Esp32c3 {
7785
target.starts_with("riscv32imc-")
7886
}
7987
}
88+
89+
impl ReadEFuse for Esp32c3 {
90+
const EFUSE_REG_BASE: u32 = 0x60008830;
91+
}
92+
93+
impl Esp32c3 {
94+
pub fn chip_revision(&self, connection: &mut Connection) -> Result<u32, Error> {
95+
let block1_addr = Self::EFUSE_REG_BASE + 0x14;
96+
let num_word = 3;
97+
let pos = 18;
98+
99+
let value = connection.read_reg(block1_addr + (num_word * 0x4))?;
100+
let value = (value & (0x7 << pos)) >> pos;
101+
102+
Ok(value)
103+
}
104+
}

espflash/src/chip/esp32s2.rs renamed to espflash/src/chip/esp32/esp32s2.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
use crate::chip::Esp32Params;
2-
use crate::image_format::{Esp32BootloaderFormat, ImageFormat, ImageFormatId};
1+
use std::ops::Range;
2+
3+
use super::Esp32Params;
34
use crate::{
4-
chip::{ChipType, SpiRegisters},
5+
chip::{ChipType, ReadEFuse, SpiRegisters},
6+
connection::Connection,
57
elf::FirmwareImage,
8+
image_format::{Esp32BootloaderFormat, ImageFormat, ImageFormatId},
69
Chip, Error, PartitionTable,
710
};
811

9-
use std::ops::Range;
10-
1112
pub struct Esp32s2;
1213

1314
const IROM_MAP_START: u32 = 0x40080000;
@@ -26,12 +27,14 @@ pub const PARAMS: Esp32Params = Esp32Params {
2627
app_addr: 0x10000,
2728
app_size: 0x100000,
2829
chip_id: 2,
29-
default_bootloader: include_bytes!("../../bootloader/esp32s2-bootloader.bin"),
30+
default_bootloader: include_bytes!("../../../bootloader/esp32s2-bootloader.bin"),
3031
};
3132

3233
impl ChipType for Esp32s2 {
3334
const CHIP_DETECT_MAGIC_VALUE: u32 = 0x000007c6;
3435

36+
const UART_CLKDIV_REG: u32 = 0x3f400014;
37+
3538
const SPI_REGISTERS: SpiRegisters = SpiRegisters {
3639
base: 0x3f402000,
3740
usr_offset: 0x18,
@@ -51,6 +54,11 @@ impl ChipType for Esp32s2 {
5154
const SUPPORTED_TARGETS: &'static [&'static str] =
5255
&["xtensa-esp32s2-none-elf", "xtensa-esp32s2-espidf"];
5356

57+
fn crystal_freq(&self, _connection: &mut Connection) -> Result<u32, Error> {
58+
// The ESP32-S2's XTAL has a fixed frequency of 40MHz.
59+
Ok(40)
60+
}
61+
5462
fn get_flash_segments<'a>(
5563
image: &'a FirmwareImage,
5664
bootloader: Option<Vec<u8>>,
@@ -75,3 +83,7 @@ impl ChipType for Esp32s2 {
7583
target.starts_with("xtensa-esp32s2-")
7684
}
7785
}
86+
87+
impl ReadEFuse for Esp32s2 {
88+
const EFUSE_REG_BASE: u32 = 0x3F41A030;
89+
}

espflash/src/chip/esp32/mod.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
use crate::PartitionTable;
2+
3+
#[allow(clippy::module_inception)]
4+
mod esp32;
5+
mod esp32c3;
6+
mod esp32s2;
7+
8+
pub use esp32::Esp32;
9+
pub use esp32c3::Esp32c3;
10+
pub use esp32s2::Esp32s2;
11+
12+
#[derive(Clone, Copy, Debug)]
13+
pub struct Esp32Params {
14+
pub boot_addr: u32,
15+
pub partition_addr: u32,
16+
pub nvs_addr: u32,
17+
pub nvs_size: u32,
18+
pub phy_init_data_addr: u32,
19+
pub phy_init_data_size: u32,
20+
pub app_addr: u32,
21+
pub app_size: u32,
22+
pub chip_id: u16,
23+
pub default_bootloader: &'static [u8],
24+
}
25+
26+
impl Esp32Params {
27+
pub fn default_partition_table(&self) -> PartitionTable {
28+
PartitionTable::basic(
29+
self.nvs_addr,
30+
self.nvs_size,
31+
self.phy_init_data_addr,
32+
self.phy_init_data_size,
33+
self.app_addr,
34+
self.app_size,
35+
)
36+
}
37+
}

espflash/src/chip/esp8266.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
1-
use super::ChipType;
2-
use crate::{chip::SpiRegisters, elf::FirmwareImage, Chip, Error, PartitionTable};
3-
4-
use crate::error::UnsupportedImageFormatError;
5-
use crate::image_format::{Esp8266Format, ImageFormat, ImageFormatId};
6-
71
use std::ops::Range;
82

9-
pub const IROM_MAP_START: u32 = 0x40200000;
3+
use super::ChipType;
4+
use crate::{
5+
chip::{ReadEFuse, SpiRegisters},
6+
elf::FirmwareImage,
7+
error::UnsupportedImageFormatError,
8+
image_format::{Esp8266Format, ImageFormat, ImageFormatId},
9+
Chip, Error, PartitionTable,
10+
};
11+
12+
const IROM_MAP_START: u32 = 0x40200000;
1013
const IROM_MAP_END: u32 = 0x40300000;
1114

1215
pub struct Esp8266;
1316

1417
impl ChipType for Esp8266 {
1518
const CHIP_DETECT_MAGIC_VALUE: u32 = 0xfff0c101;
1619

20+
const UART_CLKDIV_REG: u32 = 0x60000014;
21+
const XTAL_CLK_DIVIDER: u32 = 2;
22+
1723
const SPI_REGISTERS: SpiRegisters = SpiRegisters {
1824
base: 0x60000200,
1925
usr_offset: 0x1c,
@@ -48,11 +54,16 @@ impl ChipType for Esp8266 {
4854
}
4955
}
5056

57+
impl ReadEFuse for Esp8266 {
58+
const EFUSE_REG_BASE: u32 = 0x3ff00050;
59+
}
60+
5161
#[test]
5262
fn test_esp8266_rom() {
53-
use pretty_assertions::assert_eq;
5463
use std::fs::read;
5564

65+
use pretty_assertions::assert_eq;
66+
5667
let input_bytes = read("./tests/data/esp8266").unwrap();
5768
let expected_bin = read("./tests/data/esp8266.bin").unwrap();
5869

0 commit comments

Comments
 (0)