probe_rs/vendor/infineon/
mod.rsuse jep106::JEP106Code;
use probe_rs_target::{chip_detection::ChipDetectionMethod, Chip};
use crate::{
architecture::arm::{
memory::ArmMemoryInterface, ArmChipInfo, ArmError, ArmProbeInterface,
FullyQualifiedApAddress,
},
config::{registry, DebugSequence},
error::Error,
vendor::{infineon::sequences::xmc4000::XMC4000, Vendor},
};
pub mod sequences;
#[derive(docsplay::Display)]
pub struct Infineon;
const INFINEON: JEP106Code = JEP106Code { id: 0x41, cc: 0x00 };
impl Vendor for Infineon {
fn try_create_debug_sequence(&self, chip: &Chip) -> Option<DebugSequence> {
let sequence = if chip.name.starts_with("XMC4") {
DebugSequence::Arm(XMC4000::create())
} else {
return None;
};
Some(sequence)
}
fn try_detect_arm_chip(
&self,
interface: &mut dyn ArmProbeInterface,
chip_info: ArmChipInfo,
) -> Result<Option<String>, Error> {
if chip_info.manufacturer != INFINEON {
return Ok(None);
}
if let Some(target) = try_detect_xmc4xxx(interface, &chip_info)? {
return Ok(Some(target));
}
Ok(None)
}
}
fn try_detect_xmc4xxx(
interface: &mut dyn ArmProbeInterface,
chip_info: &ArmChipInfo,
) -> Result<Option<String>, Error> {
const KNOWN_PARTS: &[u16] = &[0x1dd, 0x1df, 0x1dc, 0x1db];
if !KNOWN_PARTS.contains(&chip_info.part) {
return Ok(None);
}
let access_port = &FullyQualifiedApAddress::v1_with_default_dp(0);
let mut memory_interface = interface.memory_interface(access_port)?;
let Some(scu_idchip) = read_xmc4xxx_scu_idchip(memory_interface.as_mut())? else {
return Ok(None);
};
tracing::debug!("SCU_IDCHIP = {:#010x}", scu_idchip);
let flash_size_kb = probe_xmc4xxx_flash_size(0x0c00_0000, memory_interface.as_mut());
let families = registry::families_ref();
for family in families.iter() {
for info in family
.chip_detection
.iter()
.filter_map(ChipDetectionMethod::as_infineon_scu)
{
if info.part != chip_info.part || info.scu_id != (scu_idchip & 0xFFFF0) >> 4 {
continue;
}
for (flash, variant) in info.variants.iter() {
if *flash == flash_size_kb {
return Ok(Some(variant.clone()));
}
}
}
}
Ok(None)
}
fn read_xmc4xxx_scu_idchip(memory: &mut dyn ArmMemoryInterface) -> Result<Option<u32>, ArmError> {
bitfield::bitfield! {
#[derive(Copy,Clone)]
struct ScuId(u32);
impl Debug;
pub mod_rev, _: 7, 0;
pub mod_type, _: 15, 8;
pub mod_number, _: 31, 16;
}
impl ScuId {
const ADDRESS: u32 = 0x5000_4000;
}
#[derive(Debug, Copy, Clone)]
struct ScuChipId;
impl ScuChipId {
const ADDRESS: u32 = 0x5000_4004;
}
let scu_id = ScuId(memory.read_word_32(ScuId::ADDRESS as u64)?);
if scu_id.mod_type() != 0xC0 {
return Ok(None);
}
memory.read_word_32(ScuChipId::ADDRESS as u64).map(Some)
}
fn probe_xmc4xxx_flash_size(start_addr: u32, memory: &mut dyn ArmMemoryInterface) -> u32 {
let mut last_successful_size = 0;
for size in [
64, 128, 256, 512, 768, 1024, 1536, 2048,
2049,
] {
let addr = start_addr + (size * 1024) - 4;
if memory.read_word_32(addr as u64).is_err() {
break;
}
last_successful_size = size;
}
last_successful_size
}