use probe_rs_target::{
Chip,
chip_detection::{ChipDetectionMethod, EspressifDetection},
};
use crate::{
Error, MemoryInterface,
architecture::{
riscv::communication_interface::RiscvCommunicationInterface,
xtensa::communication_interface::XtensaCommunicationInterface,
},
config::{DebugSequence, Registry},
vendor::{
Vendor,
espressif::sequences::{
esp32::ESP32, esp32c2::ESP32C2, esp32c3::ESP32C3, esp32c5::ESP32C5, esp32c6::ESP32C6,
esp32c61::ESP32C61, esp32h2::ESP32H2, esp32p4::ESP32P4, esp32s2::ESP32S2,
esp32s3::ESP32S3,
},
},
};
pub mod sequences;
const MAGIC_VALUE_ADDRESS: u64 = 0x4000_1000;
fn get_target_by_magic(info: &EspressifDetection, read_magic: u32) -> Option<String> {
for (magic, target) in info.variants.iter() {
if *magic == read_magic {
return Some(target.clone());
}
}
None
}
fn try_detect_espressif_chip(
registry: &Registry,
mut read_magic: impl FnMut(u64) -> Option<u32>,
idcode: u32,
) -> Option<String> {
for family in registry.families() {
for info in family
.chip_detection
.iter()
.filter_map(ChipDetectionMethod::as_espressif)
{
if info.idcode != idcode {
continue;
}
if let Some(target) = get_target_by_magic(info, 0) {
return Some(target);
} else {
let Some(read_magic) = read_magic(MAGIC_VALUE_ADDRESS) else {
continue;
};
tracing::debug!("Read magic value: {read_magic:#010x}");
if let Some(target) = get_target_by_magic(info, read_magic) {
return Some(target);
}
}
}
}
None
}
#[derive(docsplay::Display)]
pub struct Espressif;
impl Vendor for Espressif {
fn try_create_debug_sequence(&self, chip: &Chip) -> Option<DebugSequence> {
let sequence = if chip.name.eq_ignore_ascii_case("esp32s2") {
DebugSequence::Xtensa(ESP32S2::create())
} else if chip.name.eq_ignore_ascii_case("esp32s3") {
DebugSequence::Xtensa(ESP32S3::create())
} else if chip.name.eq_ignore_ascii_case("esp32c2") {
DebugSequence::Riscv(ESP32C2::create())
} else if chip.name.eq_ignore_ascii_case("esp32c3") {
DebugSequence::Riscv(ESP32C3::create())
} else if chip.name.eq_ignore_ascii_case("esp32c5") {
DebugSequence::Riscv(ESP32C5::create())
} else if chip.name.eq_ignore_ascii_case("esp32c61") {
DebugSequence::Riscv(ESP32C61::create())
} else if chip.name.eq_ignore_ascii_case("esp32c6") {
DebugSequence::Riscv(ESP32C6::create())
} else if chip.name.eq_ignore_ascii_case("esp32h2") {
DebugSequence::Riscv(ESP32H2::create())
} else if chip.name.eq_ignore_ascii_case("esp32p4") {
DebugSequence::Riscv(ESP32P4::create())
} else if chip.name.starts_with("esp32") {
DebugSequence::Xtensa(ESP32::create())
} else {
return None;
};
Some(sequence)
}
fn try_detect_riscv_chip(
&self,
registry: &Registry,
probe: &mut RiscvCommunicationInterface,
idcode: u32,
) -> Result<Option<String>, Error> {
Ok(try_detect_espressif_chip(
registry,
|address| {
probe
.halted_access(|probe| Ok(probe.read_word_32(address).ok()))
.unwrap()
},
idcode,
))
}
fn try_detect_xtensa_chip(
&self,
registry: &Registry,
probe: &mut XtensaCommunicationInterface,
idcode: u32,
) -> Result<Option<String>, Error> {
Ok(try_detect_espressif_chip(
registry,
|address| probe.read_word_32(address).ok(),
idcode,
))
}
}