use probe_rs_target::{Architecture, ChipFamily};
use super::{Core, MemoryRegion, RawFlashAlgorithm, RegistryError, TargetDescriptionSource};
use crate::architecture::arm::sequences::{
atsame5x::AtSAME5x,
infineon::XMC4000,
nrf52::Nrf52,
nrf53::Nrf5340,
nrf91::Nrf9160,
nxp::{MIMXRT10xx, MIMXRT11xx, LPC55S69},
stm32f_series::Stm32fSeries,
stm32h7::Stm32h7,
ArmDebugSequence,
};
use crate::architecture::riscv::sequences::esp32c3::ESP32C3;
use crate::architecture::riscv::sequences::{DefaultRiscvSequence, RiscvDebugSequence};
use crate::flashing::FlashLoader;
use std::sync::Arc;
use crate::architecture::arm::sequences::DefaultArmSequence;
#[derive(Clone)]
pub struct Target {
pub name: String,
pub cores: Vec<Core>,
pub flash_algorithms: Vec<RawFlashAlgorithm>,
pub memory_map: Vec<MemoryRegion>,
pub(crate) source: TargetDescriptionSource,
pub debug_sequence: DebugSequence,
}
impl std::fmt::Debug for Target {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Target {{
identifier: {:?},
flash_algorithms: {:?},
memory_map: {:?},
}}",
self.name, self.flash_algorithms, self.memory_map
)
}
}
pub type TargetParseError = serde_yaml::Error;
impl Target {
pub(crate) fn new(
family: &ChipFamily,
chip_name: impl AsRef<str>,
) -> Result<Target, RegistryError> {
family
.validate()
.map_err(|e| RegistryError::InvalidChipFamilyDefinition(Box::new(family.clone()), e))?;
let chip = family
.variants
.iter()
.find(|chip| chip.name == chip_name.as_ref())
.ok_or_else(|| RegistryError::ChipNotFound(chip_name.as_ref().to_string()))?;
let mut flash_algorithms = Vec::new();
for algo_name in chip.flash_algorithms.iter() {
let algo = family.get_algorithm(algo_name).expect(
"The required flash algorithm was not found. This is a bug. Please report it.",
);
flash_algorithms.push(algo.clone());
}
let mut debug_sequence = match chip.cores[0].core_type.architecture() {
Architecture::Arm => DebugSequence::Arm(DefaultArmSequence::create()),
Architecture::Riscv => DebugSequence::Riscv(DefaultRiscvSequence::create()),
};
if chip.name.starts_with("MIMXRT10") {
tracing::warn!("Using custom sequence for MIMXRT10xx");
debug_sequence = DebugSequence::Arm(MIMXRT10xx::create());
} else if chip.name.starts_with("MIMXRT11") {
tracing::warn!("Using custom sequence for MIMXRT11xx");
debug_sequence = DebugSequence::Arm(MIMXRT11xx::create());
} else if chip.name.starts_with("LPC55S16") || chip.name.starts_with("LPC55S69") {
tracing::warn!("Using custom sequence for LPC55S16/LPC55S69");
debug_sequence = DebugSequence::Arm(LPC55S69::create());
} else if chip.name.starts_with("esp32c3") {
tracing::warn!("Using custom sequence for ESP32c3");
debug_sequence = DebugSequence::Riscv(ESP32C3::create());
} else if chip.name.starts_with("nRF5340") {
tracing::warn!("Using custom sequence for nRF5340");
debug_sequence = DebugSequence::Arm(Nrf5340::create());
} else if chip.name.starts_with("nRF52") {
tracing::warn!("Using custom sequence for nRF52");
debug_sequence = DebugSequence::Arm(Nrf52::create());
} else if chip.name.starts_with("nRF9160") {
tracing::warn!("Using custom sequence for nRF9160");
debug_sequence = DebugSequence::Arm(Nrf9160::create());
} else if chip.name.starts_with("STM32H7") {
tracing::warn!("Using custom sequence for STM32H7");
debug_sequence = DebugSequence::Arm(Stm32h7::create());
} else if chip.name.starts_with("STM32F1")
|| chip.name.starts_with("STM32F2")
|| chip.name.starts_with("STM32F4")
|| chip.name.starts_with("STM32F7")
{
tracing::warn!("Using custom sequence for STM32F1/2/4/7");
debug_sequence = DebugSequence::Arm(Stm32fSeries::create());
} else if chip.name.starts_with("ATSAMD5") || chip.name.starts_with("ATSAME5") {
tracing::warn!("Using custom sequence for {}", chip.name);
debug_sequence = DebugSequence::Arm(AtSAME5x::create());
} else if chip.name.starts_with("XMC4") {
tracing::warn!("Using custom sequence for XMC4000");
debug_sequence = DebugSequence::Arm(XMC4000::create());
}
Ok(Target {
name: chip.name.clone(),
cores: chip.cores.clone(),
flash_algorithms,
source: family.source.clone(),
memory_map: chip.memory_map.clone(),
debug_sequence,
})
}
pub fn architecture(&self) -> Architecture {
let target_arch = self.cores[0].core_type.architecture();
assert!(
self.cores
.iter()
.map(|core| core.core_type.architecture())
.all(|core_arch| core_arch == target_arch),
"Not all cores of the target are of the same architecture. Probe-rs doesn't support this (yet). If you see this, it is a bug. Please file an issue."
);
target_arch
}
pub fn source(&self) -> &TargetDescriptionSource {
&self.source
}
pub fn flash_loader(&self) -> FlashLoader {
FlashLoader::new(self.memory_map.clone(), self.source.clone())
}
pub(crate) fn flash_algorithm_by_name(&self, name: &str) -> Option<&RawFlashAlgorithm> {
self.flash_algorithms.iter().find(|a| a.name == name)
}
pub(crate) fn core_index_by_name(&self, name: &str) -> Option<usize> {
self.cores.iter().position(|c| c.name == name)
}
pub(crate) fn get_memory_region_by_address(&self, address: u64) -> Option<&MemoryRegion> {
self.memory_map.iter().find(|region| match region {
MemoryRegion::Ram(rr) if rr.range.contains(&address) => true,
MemoryRegion::Generic(gr) if gr.range.contains(&address) => true,
MemoryRegion::Nvm(nr) if nr.range.contains(&address) => true,
_ => false,
})
}
}
#[derive(Debug, Clone)]
pub enum TargetSelector {
Unspecified(String),
Specified(Target),
Auto,
}
impl From<&str> for TargetSelector {
fn from(value: &str) -> Self {
TargetSelector::Unspecified(value.into())
}
}
impl From<&String> for TargetSelector {
fn from(value: &String) -> Self {
TargetSelector::Unspecified(value.into())
}
}
impl From<String> for TargetSelector {
fn from(value: String) -> Self {
TargetSelector::Unspecified(value)
}
}
impl From<()> for TargetSelector {
fn from(_value: ()) -> Self {
TargetSelector::Auto
}
}
impl From<Target> for TargetSelector {
fn from(target: Target) -> Self {
TargetSelector::Specified(target)
}
}
#[derive(Clone)]
pub enum DebugSequence {
Arm(Arc<dyn ArmDebugSequence>),
Riscv(Arc<dyn RiscvDebugSequence>),
}