use std::{
sync::Arc,
thread,
time::{Duration, Instant},
};
use probe_rs_target::{Chip, CoreType};
use crate::{
architecture::arm::{
ArmDebugInterface, ArmError, DapProbe, FullyQualifiedApAddress, Pins,
core::armv7m::{Aircr, Demcr, Dhcsr, FpCtrl, FpRev1CompX, FpRev2CompX},
memory::ArmMemoryInterface,
sequences::{ArmDebugSequence, cortex_m_wait_for_reset},
},
core::MemoryMappedRegister,
};
#[derive(Debug, Clone)]
pub struct EFM32xG1 {
flash_base_addr: u64,
}
impl EFM32xG1 {
pub fn create(_chip: &Chip) -> Arc<dyn ArmDebugSequence> {
Arc::new(Self { flash_base_addr: 0 })
}
}
impl ArmDebugSequence for EFM32xG1 {
fn reset_catch_set(
&self,
core: &mut dyn ArmMemoryInterface,
_core_type: CoreType,
_debug_base: Option<u64>,
) -> Result<(), ArmError> {
let reset_vector = core.read_word_32(self.flash_base_addr + 0x4)?;
let addr = reset_vector & !0b1;
let can_breakpoint = reset_vector != 0xffff_ffff && addr < 0x2000_0000;
if can_breakpoint {
tracing::info!("Breakpoint on user application reset vector ({reset_vector:#010x})");
let ctrl = FpCtrl::from(core.read_word_32(FpCtrl::get_mmio_address())?);
let comp: u32 = match ctrl.rev() {
0 => FpRev1CompX::breakpoint_configuration(addr)?.into(),
1 => FpRev2CompX::breakpoint_configuration(addr).into(),
other => {
return Err(ArmError::Other(format!(
"FPB revision {other} is not supported for the EFM32 reset catch"
)));
}
};
core.write_word_32(FpRev1CompX::get_mmio_address(), comp)?;
let mut ctrl = FpCtrl::from(0);
ctrl.set_key(true);
ctrl.set_enable(true);
core.write_word_32(FpCtrl::get_mmio_address(), ctrl.into())?;
} else {
tracing::info!(
"Reset vector {reset_vector:#010x} not usable for a breakpoint, enabling vector catch"
);
let mut demcr = Demcr(core.read_word_32(Demcr::get_mmio_address())?);
demcr.set_vc_corereset(true);
core.write_word_32(Demcr::get_mmio_address(), demcr.into())?;
}
let _ = core.read_word_32(Dhcsr::get_mmio_address())?;
Ok(())
}
fn reset_catch_clear(
&self,
core: &mut dyn ArmMemoryInterface,
_core_type: CoreType,
_debug_base: Option<u64>,
) -> Result<(), ArmError> {
core.write_word_32(FpRev1CompX::get_mmio_address(), 0)?;
let mut ctrl = FpCtrl::from(0);
ctrl.set_key(true);
ctrl.set_enable(false);
core.write_word_32(FpCtrl::get_mmio_address(), ctrl.into())?;
let mut demcr = Demcr(core.read_word_32(Demcr::get_mmio_address())?);
demcr.set_vc_corereset(false);
core.write_word_32(Demcr::get_mmio_address(), demcr.into())
}
fn reset_hardware_assert(&self, interface: &mut dyn DapProbe) -> Result<(), ArmError> {
let mut n_reset = Pins(0);
n_reset.set_nreset(true);
let n_reset = n_reset.0 as u32;
interface.swj_pins(0, n_reset, 0)?; thread::sleep(Duration::from_millis(20));
interface.swj_pins(n_reset, n_reset, 0)?; thread::sleep(Duration::from_millis(10));
Ok(())
}
fn reset_hardware_deassert(
&self,
probe: &mut dyn ArmDebugInterface,
default_ap: &FullyQualifiedApAddress,
) -> Result<(), ArmError> {
let mut n_reset = Pins(0);
n_reset.set_nreset(true);
let n_reset = n_reset.0 as u32;
let _ = probe.swj_pins(n_reset, n_reset, 0)?;
let mut memory = probe.memory_interface(default_ap)?;
let mut request_halt = Dhcsr(0);
request_halt.set_c_halt(true);
request_halt.set_c_debugen(true);
request_halt.enable_write();
let start = Instant::now();
loop {
let halted = (|| -> Result<bool, ArmError> {
memory.write_word_32(Dhcsr::get_mmio_address(), request_halt.into())?;
Ok(Dhcsr(memory.read_word_32(Dhcsr::get_mmio_address())?).s_halt())
})();
match halted {
Ok(true) => return Ok(()),
Ok(false) => {}
Err(e) => {
if start.elapsed() >= Duration::from_millis(500) {
return Err(e);
}
}
}
if start.elapsed() >= Duration::from_millis(500) {
return Err(ArmError::Timeout);
}
thread::sleep(Duration::from_millis(1));
}
}
fn reset_system(
&self,
interface: &mut dyn ArmMemoryInterface,
_core_type: CoreType,
_debug_base: Option<u64>,
) -> Result<(), ArmError> {
let mut aircr = Aircr(0);
aircr.vectkey();
aircr.set_sysresetreq(true);
interface.write_word_32(Aircr::get_mmio_address(), aircr.into())?;
cortex_m_wait_for_reset(interface)?;
let dhcsr = Dhcsr(interface.read_word_32(Dhcsr::get_mmio_address())?);
if dhcsr.s_lockup() {
let mut value = Dhcsr(0);
value.set_c_halt(true);
value.set_c_debugen(true);
value.enable_write();
interface.write_word_32(Dhcsr::get_mmio_address(), value.into())?;
let mut demcr = Demcr(interface.read_word_32(Demcr::get_mmio_address())?);
demcr.set_vc_corereset(true);
interface.write_word_32(Demcr::get_mmio_address(), demcr.into())?;
let mut aircr = Aircr(0);
aircr.vectkey();
aircr.set_vectreset(true);
aircr.set_vectclractive(true);
interface.write_word_32(Aircr::get_mmio_address(), aircr.into())?;
cortex_m_wait_for_reset(interface)?;
}
Ok(())
}
}