use std::{sync::Arc, thread, time::Duration};
use probe_rs_target::CoreType;
use crate::{
MemoryMappedRegister,
architecture::arm::{
ArmDebugInterface, ArmError, FullyQualifiedApAddress,
armv7m::Demcr,
memory::ArmMemoryInterface,
sequences::{ArmDebugSequence, cortex_m_core_start},
},
};
#[derive(Debug)]
pub struct Va416xx;
impl Va416xx {
pub fn create() -> Arc<Self> {
Arc::new(Self)
}
}
impl ArmDebugSequence for Va416xx {
fn debug_core_start(
&self,
interface: &mut dyn ArmDebugInterface,
core_ap: &FullyQualifiedApAddress,
_core_type: CoreType,
_debug_base: Option<u64>,
_cti_base: Option<u64>,
) -> Result<(), ArmError> {
let mut core = interface.memory_interface(core_ap)?;
cortex_m_core_start(&mut *core)?;
core.write_32(0x4001_0010, &[0x000_0001])?;
core.write_32(0x400210C0, &[0x1ACCE551])?;
core.write_32(0x40021008, &[0])?;
Ok(())
}
fn reset_system(
&self,
interface: &mut dyn ArmMemoryInterface,
core_type: CoreType,
debug_base: Option<u64>,
) -> Result<(), ArmError> {
use crate::architecture::arm::core::armv7m::{Aircr, Dhcsr};
let demcr = Demcr(interface.read_word_32(Demcr::get_mmio_address())?);
let mut aircr = Aircr(0);
aircr.vectkey();
aircr.set_sysresetreq(true);
interface
.write_word_32(Aircr::get_mmio_address(), aircr.into())
.ok();
interface.flush().ok();
let ap = interface.fully_qualified_address();
let arm_interface = interface.get_arm_debug_interface()?;
const NUM_RETRIES: u32 = 10;
for i in 0..NUM_RETRIES {
match arm_interface.reinitialize() {
Ok(_) => break,
Err(e) => {
if i == NUM_RETRIES - 1 {
return Err(e);
}
thread::sleep(Duration::from_millis(50));
}
}
}
assert!(debug_base.is_none());
self.debug_core_start(arm_interface, &ap, core_type, None, None)?;
if demcr.vc_corereset() {
let mut value = Dhcsr(0);
value.set_c_halt(true);
value.set_c_debugen(true);
value.enable_write();
const NUM_HALT_RETRIES: u32 = 10;
for i in 0..NUM_HALT_RETRIES {
interface.write_word_32(Dhcsr::get_mmio_address(), value.into())?;
let dhcsr = Dhcsr(interface.read_word_32(Dhcsr::get_mmio_address())?);
if dhcsr.s_halt() {
break;
}
if i >= NUM_HALT_RETRIES - 1 {
return Err(ArmError::Timeout);
}
thread::sleep(Duration::from_millis(50));
}
}
Ok(())
}
}