Merge pull request #69 from jessebraham/feature/more-board-info

Display chip features and MAC address in board info output
This commit is contained in:
Robin Appelman
2021-10-05 16:14:35 +00:00
committed by GitHub
6 changed files with 231 additions and 6 deletions

View File

@@ -2,7 +2,7 @@ use std::ops::Range;
use super::Esp32Params;
use crate::{
chip::{Chip, ChipType, ReadEFuse, SpiRegisters},
chip::{bytes_to_mac_addr, Chip, ChipType, ReadEFuse, SpiRegisters},
connection::Connection,
elf::FirmwareImage,
image_format::{Esp32BootloaderFormat, ImageFormat, ImageFormatId},
@@ -54,6 +54,64 @@ impl ChipType for Esp32 {
const SUPPORTED_TARGETS: &'static [&'static str] =
&["xtensa-esp32-none-elf", "xtensa-esp32-espidf"];
fn chip_features(&self, connection: &mut Connection) -> Result<Vec<&str>, Error> {
let word3 = self.read_efuse(connection, 3)?;
let word4 = self.read_efuse(connection, 4)?;
let word6 = self.read_efuse(connection, 6)?;
let mut features = vec!["WiFi"];
let chip_ver_dis_bt = word3 & 0x2;
if chip_ver_dis_bt == 0 {
features.push("BT");
}
let chip_ver_dis_app_cpu = word3 & 0x1;
if chip_ver_dis_app_cpu == 0 {
features.push("Dual Core");
} else {
features.push("Single Core");
}
let chip_cpu_freq_rated = word3 & (1 << 13);
if chip_cpu_freq_rated != 0 {
let chip_cpu_freq_low = word3 & (1 << 12);
if chip_cpu_freq_low != 0 {
features.push("160MHz");
} else {
features.push("240MHz");
}
}
let pkg_version = self.package_version(connection)?;
if [2, 4, 5, 6].contains(&pkg_version) {
features.push("Embedded Flash");
}
if pkg_version == 6 {
features.push("Embedded PSRAM");
}
let adc_vref = (word4 >> 8) & 0x1;
if adc_vref != 0 {
features.push("VRef calibration in efuse");
}
let blk3_part_res = (word3 >> 14) & 0x1;
if blk3_part_res != 0 {
features.push("BLK3 partially reserved");
}
let coding_scheme = word6 & 0x3;
features.push(match coding_scheme {
0 => "Coding Scheme None",
1 => "Coding Scheme 3/4",
2 => "Coding Scheme Repeat (UNSUPPORTED)",
_ => "Coding Scheme Invalid",
});
Ok(features)
}
fn get_flash_segments<'a>(
image: &'a FirmwareImage,
bootloader: Option<Vec<u8>>,
@@ -74,6 +132,17 @@ impl ChipType for Esp32 {
}
}
fn mac_address(&self, connection: &mut Connection) -> Result<String, Error> {
let word1 = self.read_efuse(connection, 1)?;
let word2 = self.read_efuse(connection, 2)?;
let words = ((word2 as u64) << 32) | word1 as u64;
let bytes = words.to_be_bytes();
let bytes = &bytes[2..8];
Ok(bytes_to_mac_addr(bytes))
}
fn supports_target(target: &str) -> bool {
target.starts_with("xtensa-esp32-")
}
@@ -103,6 +172,15 @@ impl Esp32 {
Ok(revision)
}
fn package_version(&self, connection: &mut Connection) -> Result<u32, Error> {
let word3 = self.read_efuse(connection, 3)?;
let pkg_version = (word3 >> 9) & 0x7;
let pkg_version = pkg_version + (((word3 >> 2) & 0x1) << 3);
Ok(pkg_version)
}
}
#[test]

View File

@@ -2,7 +2,7 @@ use std::ops::Range;
use super::Esp32Params;
use crate::{
chip::{ChipType, ReadEFuse, SpiRegisters},
chip::{bytes_to_mac_addr, ChipType, ReadEFuse, SpiRegisters},
connection::Connection,
elf::FirmwareImage,
image_format::{Esp32BootloaderFormat, ImageFormat, ImageFormatId},
@@ -56,6 +56,10 @@ impl ChipType for Esp32c3 {
const SUPPORTED_TARGETS: &'static [&'static str] =
&["riscv32imc-uknown-none-elf", "riscv32imc-esp-espidf"];
fn chip_features(&self, _connection: &mut Connection) -> Result<Vec<&str>, Error> {
Ok(vec!["WiFi"])
}
fn crystal_freq(&self, _connection: &mut Connection) -> Result<u32, Error> {
// The ESP32-C3's XTAL has a fixed frequency of 40MHz.
Ok(40)
@@ -81,6 +85,17 @@ impl ChipType for Esp32c3 {
}
}
fn mac_address(&self, connection: &mut Connection) -> Result<String, Error> {
let word5 = self.read_efuse(connection, 5)?;
let word6 = self.read_efuse(connection, 6)?;
let bytes = ((word6 as u64) << 32) | word5 as u64;
let bytes = bytes.to_be_bytes();
let bytes = &bytes[2..];
Ok(bytes_to_mac_addr(bytes))
}
fn supports_target(target: &str) -> bool {
target.starts_with("riscv32imc-")
}

View File

@@ -2,7 +2,7 @@ use std::ops::Range;
use super::Esp32Params;
use crate::{
chip::{ChipType, ReadEFuse, SpiRegisters},
chip::{bytes_to_mac_addr, ChipType, ReadEFuse, SpiRegisters},
connection::Connection,
elf::FirmwareImage,
image_format::{Esp32BootloaderFormat, ImageFormat, ImageFormatId},
@@ -54,6 +54,36 @@ impl ChipType for Esp32s2 {
const SUPPORTED_TARGETS: &'static [&'static str] =
&["xtensa-esp32s2-none-elf", "xtensa-esp32s2-espidf"];
fn chip_features(&self, connection: &mut Connection) -> Result<Vec<&str>, Error> {
let mut features = vec!["WiFi"];
let flash_version = match self.get_flash_version(connection)? {
0 => "No Embedded Flash",
1 => "Embedded Flash 2MB",
2 => "Embedded Flash 4MB",
_ => "Unknown Embedded Flash",
};
features.push(flash_version);
let psram_version = match self.get_psram_version(connection)? {
0 => "No Embedded PSRAM",
1 => "Embedded PSRAM 2MB",
2 => "Embedded PSRAM 4MB",
_ => "Unknown Embedded PSRAM",
};
features.push(psram_version);
let block2_version = match self.get_block2_version(connection)? {
0 => "No calibration in BLK2 of efuse",
1 => "ADC and temperature sensor calibration in BLK2 of efuse V1",
2 => "ADC and temperature sensor calibration in BLK2 of efuse V2",
_ => "Unknown Calibration in BLK2",
};
features.push(block2_version);
Ok(features)
}
fn crystal_freq(&self, _connection: &mut Connection) -> Result<u32, Error> {
// The ESP32-S2's XTAL has a fixed frequency of 40MHz.
Ok(40)
@@ -79,6 +109,17 @@ impl ChipType for Esp32s2 {
}
}
fn mac_address(&self, connection: &mut Connection) -> Result<String, Error> {
let word5 = self.read_efuse(connection, 5)?;
let word6 = self.read_efuse(connection, 6)?;
let bytes = ((word6 as u64) << 32) | word5 as u64;
let bytes = bytes.to_be_bytes();
let bytes = &bytes[2..];
Ok(bytes_to_mac_addr(bytes))
}
fn supports_target(target: &str) -> bool {
target.starts_with("xtensa-esp32s2-")
}
@@ -87,3 +128,26 @@ impl ChipType for Esp32s2 {
impl ReadEFuse for Esp32s2 {
const EFUSE_REG_BASE: u32 = 0x3F41A030;
}
impl Esp32s2 {
fn get_flash_version(&self, connection: &mut Connection) -> Result<u32, Error> {
let blk1_word3 = self.read_efuse(connection, 8)?;
let flash_version = (blk1_word3 >> 21) & 0xf;
Ok(flash_version)
}
fn get_psram_version(&self, connection: &mut Connection) -> Result<u32, Error> {
let blk1_word3 = self.read_efuse(connection, 8)?;
let psram_version = (blk1_word3 >> 28) & 0xf;
Ok(psram_version)
}
fn get_block2_version(&self, connection: &mut Connection) -> Result<u32, Error> {
let blk2_word4 = self.read_efuse(connection, 15)?;
let block2_version = (blk2_word4 >> 4) & 0x7;
Ok(block2_version)
}
}

View File

@@ -1,8 +1,9 @@
use std::ops::Range;
use super::ChipType;
use super::{bytes_to_mac_addr, ChipType};
use crate::{
chip::{ReadEFuse, SpiRegisters},
connection::Connection,
elf::FirmwareImage,
error::UnsupportedImageFormatError,
image_format::{Esp8266Format, ImageFormat, ImageFormatId},
@@ -37,6 +38,10 @@ impl ChipType for Esp8266 {
const SUPPORTED_TARGETS: &'static [&'static str] = &["xtensa-esp8266-none-elf"];
fn chip_features(&self, _connection: &mut Connection) -> Result<Vec<&str>, Error> {
Ok(vec!["WiFi"])
}
fn get_flash_segments<'a>(
image: &'a FirmwareImage,
_bootloader: Option<Vec<u8>>,
@@ -49,6 +54,32 @@ impl ChipType for Esp8266 {
}
}
fn mac_address(&self, connection: &mut Connection) -> Result<String, Error> {
let word0 = self.read_efuse(connection, 0)?;
let word1 = self.read_efuse(connection, 1)?;
let word3 = self.read_efuse(connection, 3)?;
// First determine the OUI portion of the MAC address
let mut bytes = if word3 != 0 {
vec![
((word3 >> 16) & 0xff) as u8,
((word3 >> 8) & 0xff) as u8,
(word3 & 0xff) as u8,
]
} else if ((word1 >> 16) & 0xff) == 0 {
vec![0x18, 0xfe, 0x34]
} else {
vec![0xac, 0xd0, 0x74]
};
// Add the remaining NIC portion of the MAC address
bytes.push(((word1 >> 8) & 0xff) as u8);
bytes.push((word1 & 0xff) as u8);
bytes.push(((word0 >> 24) & 0xff) as u8);
Ok(bytes_to_mac_addr(&bytes))
}
fn supports_target(target: &str) -> bool {
target.starts_with("xtensa-esp8266-")
}

View File

@@ -34,6 +34,9 @@ pub trait ChipType {
const SUPPORTED_TARGETS: &'static [&'static str];
/// List the available features of the connected chip.
fn chip_features(&self, connection: &mut Connection) -> Result<Vec<&str>, Error>;
/// Determine the frequency of the crytal on the connected chip.
fn crystal_freq(&self, connection: &mut Connection) -> Result<u32, Error> {
let uart_div = connection.read_reg(Self::UART_CLKDIV_REG)? & Self::UART_CLKDIV_MASK;
@@ -52,6 +55,9 @@ pub trait ChipType {
image_format: ImageFormatId,
) -> Result<Box<dyn ImageFormat<'a> + 'a>, Error>;
/// Read the MAC address of the connected chip.
fn mac_address(&self, connection: &mut Connection) -> Result<String, Error>;
fn supports_target(target: &str) -> bool;
}
@@ -238,4 +244,30 @@ impl Chip {
Ok(rev)
}
pub fn chip_features(&self, connection: &mut Connection) -> Result<Vec<&str>, Error> {
match self {
Chip::Esp32 => Esp32.chip_features(connection),
Chip::Esp32c3 => Esp32c3.chip_features(connection),
Chip::Esp32s2 => Esp32s2.chip_features(connection),
Chip::Esp8266 => Esp8266.chip_features(connection),
}
}
pub fn mac_address(&self, connection: &mut Connection) -> Result<String, Error> {
match self {
Chip::Esp32 => Esp32.mac_address(connection),
Chip::Esp32c3 => Esp32c3.mac_address(connection),
Chip::Esp32s2 => Esp32s2.mac_address(connection),
Chip::Esp8266 => Esp8266.mac_address(connection),
}
}
}
pub(crate) fn bytes_to_mac_addr(bytes: &[u8]) -> String {
bytes
.iter()
.map(|b| format!("{:02x}", b))
.collect::<Vec<_>>()
.join(":")
}

View File

@@ -479,10 +479,13 @@ impl Flasher {
/// Read and print any information we can about the connected board
pub fn board_info(&mut self) -> Result<(), Error> {
let chip = self.chip();
let maybe_revision = chip.chip_revision(self.connection())?;
let freq = chip.crystal_freq(self.connection())?;
let size = self.flash_size();
let maybe_revision = chip.chip_revision(self.connection())?;
let features = chip.chip_features(self.connection())?;
let freq = chip.crystal_freq(self.connection())?;
let mac = chip.mac_address(self.connection())?;
print!("Chip type: {}", chip);
match maybe_revision {
Some(revision) => println!(" (revision {})", revision),
@@ -490,6 +493,8 @@ impl Flasher {
}
println!("Crystal frequency: {}MHz", freq);
println!("Flash size: {}", size);
println!("Features: {}", features.join(", "));
println!("MAC address: {}", mac);
Ok(())
}