use std::{
sync::{
Arc,
atomic::{AtomicBool, Ordering},
},
thread,
time::{Duration, Instant},
};
use probe_rs_target::Chip;
use crate::{
architecture::arm::{
ArmDebugInterface, ArmError, FullyQualifiedApAddress, Pins,
armv7m::{Demcr, FpCtrl, FpRev2CompX, MpuCtrl},
communication_interface::DapProbe,
core::{
armv7m::{Aircr, Dhcsr},
registers::cortex_m::PC,
},
dp::DpAddress,
memory::ArmMemoryInterface,
sequences::{self, ArmDebugSequence, ArmDebugSequenceError},
},
core::MemoryMappedRegister,
};
#[derive(Debug)]
pub struct MIMXRT10xx {
simulate_reset_catch: AtomicBool,
}
impl MIMXRT10xx {
pub fn create() -> Arc<dyn ArmDebugSequence> {
Arc::new(Self {
simulate_reset_catch: AtomicBool::new(false),
})
}
fn halt(&self, probe: &mut dyn ArmMemoryInterface, halt: bool) -> Result<(), ArmError> {
let mut dhcsr = Dhcsr(probe.read_word_32(Dhcsr::get_mmio_address())?);
dhcsr.set_c_halt(halt);
dhcsr.set_c_debugen(true);
dhcsr.enable_write();
probe.write_word_32(Dhcsr::get_mmio_address(), dhcsr.into())?;
probe.flush()?;
self.wait_for_halt(probe, halt)?;
Ok(())
}
fn use_boot_fuses_for_flexram(
&self,
probe: &mut dyn ArmMemoryInterface,
) -> Result<(), ArmError> {
const IOMUXC_GPR_GPR16: u64 = 0x400A_C040;
const FLEXRAM_BANK_CFG_SEL_MASK: u32 = 1 << 2;
let mut gpr16 = probe.read_word_32(IOMUXC_GPR_GPR16)?;
gpr16 &= !FLEXRAM_BANK_CFG_SEL_MASK;
probe.write_word_32(IOMUXC_GPR_GPR16, gpr16)?;
probe.flush()?;
Ok(())
}
fn wait_for_halt(
&self,
probe: &mut dyn ArmMemoryInterface,
halt: bool,
) -> Result<(), ArmError> {
let start = Instant::now();
let action = if halt { "halt" } else { "unhalt" };
while Dhcsr(probe.read_word_32(Dhcsr::get_mmio_address())?).s_halt() != halt {
if start.elapsed() > Duration::from_millis(100) {
tracing::debug!("Exceeded timeout while waiting for core to {action}");
return Err(ArmError::Timeout);
}
thread::sleep(Duration::from_millis(1));
}
Ok(())
}
}
impl ArmDebugSequence for MIMXRT10xx {
fn reset_catch_set(
&self,
_: &mut dyn ArmMemoryInterface,
_: probe_rs_target::CoreType,
_: Option<u64>,
) -> Result<(), ArmError> {
self.simulate_reset_catch.store(true, Ordering::Relaxed);
Ok(())
}
fn reset_catch_clear(
&self,
_: &mut dyn ArmMemoryInterface,
_: probe_rs_target::CoreType,
_: Option<u64>,
) -> Result<(), ArmError> {
self.simulate_reset_catch.store(false, Ordering::Relaxed);
Ok(())
}
fn reset_system(
&self,
interface: &mut dyn ArmMemoryInterface,
_: crate::CoreType,
_: Option<u64>,
) -> Result<(), ArmError> {
tracing::debug!("Halting MCU before changing FlexRAM layout");
self.halt(interface, true)?;
tracing::debug!("Setting FlexRAM layout");
self.use_boot_fuses_for_flexram(interface)?;
tracing::debug!("Enabling DWT to set a watchpoint");
let mut demcr = Demcr(interface.read_word_32(Demcr::get_mmio_address())?);
let trcena = demcr.trcena();
demcr.set_trcena(true);
interface.write_word_32(Demcr::get_mmio_address(), demcr.0)?;
tracing::debug!("Installing watchpoint to catch boot ROM SRC_SBMR1 read");
const DWT_COMP0: u64 = 0xE000_1020;
const DWT_MASK0: u64 = 0xE000_1024;
const DWT_FUNCTION0: u64 = 0xE000_1028;
const DWT_FUNCTION_DATAVSIZE_WORD: u32 = 0b10 << 10;
const DWT_FUNCTION_DEBUG_DATA_RW: u32 = 0b0111;
const SRC_SBMR1: u32 = 0x400F_8004;
interface.write_word_32(DWT_COMP0, SRC_SBMR1)?;
interface.write_word_32(DWT_MASK0, 0)?;
interface.write_word_32(
DWT_FUNCTION0,
DWT_FUNCTION_DATAVSIZE_WORD | DWT_FUNCTION_DEBUG_DATA_RW,
)?;
interface.flush()?;
tracing::debug!("Performing the standard Cortex-M system reset");
sequences::cortex_m_reset_system(interface)?;
tracing::debug!("Waiting for watchpoint to hit");
self.wait_for_halt(interface, true)?;
let mpu_ctrl = MpuCtrl(interface.read_word_32(MpuCtrl::get_mmio_address())?);
tracing::debug!("MPU_CTRL at boot ROM catch: {mpu_ctrl:?}");
if mpu_ctrl.enable() {
interface.write_word_32(MpuCtrl::get_mmio_address(), MpuCtrl(0).into())?;
interface.flush()?;
}
tracing::debug!("Cleaning up watchpoints");
interface.write_word_32(DWT_COMP0, 0)?;
interface.write_word_32(DWT_FUNCTION0, 0)?;
let mut demcr = Demcr(interface.read_word_32(Demcr::get_mmio_address())?);
demcr.set_trcena(trcena);
interface.write_word_32(Demcr::get_mmio_address(), demcr.0)?;
interface.flush()?;
if !self.simulate_reset_catch.load(Ordering::Relaxed) {
self.halt(interface, false)?;
}
Ok(())
}
}
#[deprecated(note = "Prefer MIMXRT11xx, which supports 1170 and 1160 targets")]
pub type MIMXRT117x = MIMXRT11xx;
#[derive(Debug)]
pub struct MIMXRT11xx {
simulate_reset_catch: AtomicBool,
}
impl MIMXRT11xx {
const SRC: u64 = 0x40C0_4000;
const SRC_SRMR: u64 = Self::SRC + 4;
fn new() -> Self {
Self {
simulate_reset_catch: AtomicBool::new(false),
}
}
pub fn create() -> Arc<dyn ArmDebugSequence> {
Arc::new(Self::new())
}
fn clear_src_srmr_mask(&self, probe: &mut dyn ArmMemoryInterface) -> Result<(), ArmError> {
let mut srmr = probe.read_word_32(Self::SRC_SRMR)?;
tracing::debug!("SRC_SRMR: {srmr:#010X}. Clearing the M7REQ_RESET_MODE mask...");
srmr &= !(0b11 << 12);
probe.write_word_32(Self::SRC_SRMR, srmr)?;
probe.flush()?;
Ok(())
}
fn halt(&self, probe: &mut dyn ArmMemoryInterface, halt: bool) -> Result<(), ArmError> {
let mut dhcsr = Dhcsr(probe.read_word_32(Dhcsr::get_mmio_address())?);
dhcsr.set_c_halt(halt);
dhcsr.set_c_debugen(true);
dhcsr.enable_write();
probe.write_word_32(Dhcsr::get_mmio_address(), dhcsr.into())?;
probe.flush()?;
let start = Instant::now();
let action = if halt { "halt" } else { "unhalt" };
while Dhcsr(probe.read_word_32(Dhcsr::get_mmio_address())?).s_halt() != halt {
if start.elapsed() > Duration::from_millis(100) {
tracing::debug!("Exceeded timeout while waiting for the core to {action}");
return Err(ArmError::Timeout);
}
thread::sleep(Duration::from_millis(1));
}
Ok(())
}
fn wait_for_enable(
&self,
probe: &mut dyn ArmMemoryInterface,
timeout: Duration,
) -> Result<(), ArmError> {
let start = Instant::now();
let mut errors = 0usize;
let mut disables = 0usize;
loop {
match probe.generic_status() {
Ok(csw) if csw.DeviceEn() => {
tracing::debug!(
"Device enabled after {}ms with {errors} errors and {disables} invalid statuses",
start.elapsed().as_millis()
);
return Ok(());
}
Ok(_) => disables += 1,
Err(_) => errors += 1,
}
if start.elapsed() > timeout {
tracing::debug!(
"Exceeded {}ms timeout while waiting for enable with {errors} errors and {disables} invalid statuses",
timeout.as_millis()
);
return Err(ArmError::Timeout);
}
thread::sleep(Duration::from_millis(1));
}
}
fn read_core_reg(
&self,
probe: &mut dyn ArmMemoryInterface,
reg: crate::core::registers::CoreRegister,
) -> Result<u32, ArmError> {
crate::architecture::arm::core::cortex_m::read_core_reg(probe, reg.into())
}
fn write_core_reg(
&self,
probe: &mut dyn ArmMemoryInterface,
reg: crate::core::registers::CoreRegister,
value: u32,
) -> Result<(), ArmError> {
crate::architecture::arm::core::cortex_m::write_core_reg(probe, reg.into(), value)?;
probe.flush()?;
Ok(())
}
const BOOT_ROM_SPIN_ADDRESS_REV_A: u32 = 0x00223104;
const BOOT_ROM_SPIN_ADDRESS_REV_B: u32 = 0x002231FC;
fn find_flexspi_image_reset_handler(
&self,
probe: &mut dyn ArmMemoryInterface,
) -> Result<Option<u32>, ArmError> {
const FLEXSPI1: u64 = 0x30000000;
const IVT: u64 = FLEXSPI1 + 0x1000;
tracing::debug!("Assuming that your CM7's program is in FlexSPI1 at {FLEXSPI1:#010X}");
let ivt_header = probe.read_word_32(IVT)?;
tracing::debug!("IVT Header: {ivt_header:#010X}");
if ivt_header & 0xFF != 0xD1 {
tracing::debug!("IVT tag is incorrect! Expected 0xD1 in {ivt_header:#010X}");
return Ok(None);
}
if (ivt_header >> 8) & 0xFFFF != 0x2000 {
tracing::debug!("IVT length is incorrect! {ivt_header:#010X}");
return Ok(None);
}
let ivt_version = ivt_header >> 24;
if !(0x40..=0x45).contains(&ivt_version) {
tracing::debug!("IVT version is invalid! {ivt_header:#010X}");
return Ok(None);
}
let reset_handler = if ivt_version == 0x40 {
let vector_table = probe.read_word_32(IVT + 4)?;
tracing::debug!("Vector table address: {vector_table:#010X}");
probe.read_word_32(u64::from(vector_table) + 4u64)?
} else {
probe.read_word_32(IVT + 4)?
};
tracing::debug!("Reset handler: {reset_handler:#010X}");
if reset_handler & 1 == 0 {
tracing::debug!(
"Is your reset handler actually a function address? Where's its thumb bit?"
);
return Ok(None);
}
Ok(Some(reset_handler))
}
fn use_boot_fuses_for_flexram(
&self,
probe: &mut dyn ArmMemoryInterface,
) -> Result<(), ArmError> {
const IOMUXC_GPR_GPR16: u64 = 0x400E_4040;
const FLEXRAM_BANK_CFG_SEL_MASK: u32 = 1 << 2;
let mut gpr16 = probe.read_word_32(IOMUXC_GPR_GPR16)?;
gpr16 &= !FLEXRAM_BANK_CFG_SEL_MASK;
probe.write_word_32(IOMUXC_GPR_GPR16, gpr16)?;
probe.flush()?;
Ok(())
}
}
impl ArmDebugSequence for MIMXRT11xx {
fn reset_catch_set(
&self,
_: &mut dyn ArmMemoryInterface,
_: probe_rs_target::CoreType,
_: Option<u64>,
) -> Result<(), ArmError> {
self.simulate_reset_catch.store(true, Ordering::Relaxed);
Ok(())
}
fn reset_catch_clear(
&self,
_: &mut dyn ArmMemoryInterface,
_: probe_rs_target::CoreType,
_: Option<u64>,
) -> Result<(), ArmError> {
self.simulate_reset_catch.store(false, Ordering::Relaxed);
Ok(())
}
fn reset_system(
&self,
probe: &mut dyn ArmMemoryInterface,
core_type: probe_rs_target::CoreType,
debug_base: Option<u64>,
) -> Result<(), ArmError> {
self.halt(probe, true)?;
self.use_boot_fuses_for_flexram(probe)?;
let debug_cache = DebugCache::from_target(probe)?;
self.clear_src_srmr_mask(probe)?;
let mut aircr = Aircr(0);
aircr.vectkey();
aircr.set_sysresetreq(true);
probe
.write_word_32(Aircr::get_mmio_address(), aircr.into())
.ok();
probe.flush().ok();
let ap = probe.fully_qualified_address();
let interface = probe.get_arm_debug_interface()?;
interface.reinitialize()?;
assert!(debug_base.is_none());
self.debug_core_start(interface, &ap, core_type, None, None)?;
self.wait_for_enable(probe, Duration::from_millis(300))?;
self.halt(probe, true)?;
let pc = self
.read_core_reg(probe, PC)
.map_err(|err| ArmDebugSequenceError::SequenceSpecific(err.into()))?;
if pc != Self::BOOT_ROM_SPIN_ADDRESS_REV_A && pc != Self::BOOT_ROM_SPIN_ADDRESS_REV_B {
let err = format!(
"The Cortex M7 PC should be at either {:#010X} or {:#010X}, but it's at {pc:#010X}",
Self::BOOT_ROM_SPIN_ADDRESS_REV_A,
Self::BOOT_ROM_SPIN_ADDRESS_REV_B,
);
return Err(ArmDebugSequenceError::SequenceSpecific(err.into()).into());
}
tracing::debug!("Boot ROM spinning at {pc:#010X}");
if let Some(pc) = self.find_flexspi_image_reset_handler(probe)? {
self.write_core_reg(probe, PC, pc)?
} else {
tracing::warn!(
"Could not find a valid reset handler in FlexSPI! Keeping the CM7 in the boot ROM."
);
}
debug_cache.restore(probe)?;
if !self.simulate_reset_catch.load(Ordering::Relaxed) {
self.halt(probe, false)?;
}
Ok(())
}
}
struct DebugCache {
fp_ctrl: FpCtrl,
fp_comps: Vec<FpRev2CompX>,
}
impl DebugCache {
fn from_target(probe: &mut dyn ArmMemoryInterface) -> Result<Self, ArmError> {
let fp_ctrl = FpCtrl(probe.read_word_32(FpCtrl::get_mmio_address())?);
Ok(Self {
fp_ctrl,
fp_comps: (0..fp_ctrl.num_code())
.map(|base_address| -> Result<FpRev2CompX, ArmError> {
let address = FpRev2CompX::get_mmio_address_from_base(base_address as u64 * 4)?;
let fp_comp = probe.read_word_32(address)?;
Ok(FpRev2CompX(fp_comp))
})
.collect::<Result<Vec<_>, _>>()?,
})
}
fn restore(mut self, probe: &mut dyn ArmMemoryInterface) -> Result<(), ArmError> {
self.fp_ctrl.set_key(true);
probe.write_word_32(FpCtrl::get_mmio_address(), self.fp_ctrl.into())?;
for (base, fp_comp) in self.fp_comps.into_iter().enumerate() {
probe.write_word_32(
FpRev2CompX::get_mmio_address_from_base(base as u64 * 4)?,
fp_comp.into(),
)?;
}
Ok(())
}
}
#[derive(Debug)]
pub struct S32K3xx {
has_clock_partition2: bool,
sram_size: u32,
dtcm_size: u32,
connect_under_reset: AtomicBool,
}
impl S32K3xx {
const SDA_AP: u8 = 7;
const SDA_AP_DBGENCTRL: u64 = 0x80;
const SDA_AP_DBGENCTRL_ENABLE_M7: u32 = 0x3000_00F0;
const SDA_AP_RSTCTRL: u64 = 0x90;
const SDA_AP_RSTCTRL_RELEASE_CM7_0: u32 = 1 << 25;
const SDA_AP_RSTCTRL_RELEASE_CM7_1: u32 = 1 << 26;
const MDM_AP: u8 = 6;
const MDM_AP_CTL: u64 = 0x04;
const MDM_AP_CTL_RSTREL: u32 = 0x0040_0000;
const MDM_AP_CTL_RSTREL_DBGREQ: u32 = 0x0040_0B00;
const MDM_AP_CTL_RSTREL_DBGREQ_FUNCRST: u32 = 0x0040_0B20;
const MDM_AP_CTL_CORE_ACCESS: u32 = 0x0043_0000;
const MC_ME: u64 = 0x402D_C000;
const DMAMUX0_CHCFG0: u64 = 0x4028_0003;
const EDMA_TCD0: u64 = 0x4021_0000;
const SRAM_BASE: u64 = 0x2040_0000;
const DTCM_BASE: u64 = 0x2000_0000;
const DTCM_BACKDOOR: u32 = 0x2100_0000;
pub fn create(chip: &Chip) -> Arc<dyn ArmDebugSequence> {
let has_clock_partition2 = !["S32K310", "S32K311", "S32K312"]
.iter()
.any(|smaller| chip.name.starts_with(smaller));
let mut dtcm_size = 0;
let mut sram_ranges = Vec::new();
for region in &chip.memory_map {
let range = region.address_range();
if range.start == Self::DTCM_BASE {
dtcm_size = (range.end - range.start) as u32;
} else if range.start >= Self::SRAM_BASE {
sram_ranges.push(range);
}
}
sram_ranges.sort_by_key(|range| range.start);
let mut sram_end = Self::SRAM_BASE;
for range in sram_ranges {
if range.start <= sram_end {
sram_end = sram_end.max(range.end);
}
}
Arc::new(Self {
has_clock_partition2,
sram_size: (sram_end - Self::SRAM_BASE) as u32,
dtcm_size,
connect_under_reset: AtomicBool::new(false),
})
}
fn sda_ap(dp: DpAddress) -> FullyQualifiedApAddress {
FullyQualifiedApAddress::v1_with_dp(dp, Self::SDA_AP)
}
fn mdm_ap(dp: DpAddress) -> FullyQualifiedApAddress {
FullyQualifiedApAddress::v1_with_dp(dp, Self::MDM_AP)
}
fn enable_m7_debug(
&self,
interface: &mut dyn ArmDebugInterface,
dp: DpAddress,
) -> Result<(), ArmError> {
interface.write_raw_ap_register(
&Self::sda_ap(dp),
Self::SDA_AP_DBGENCTRL,
Self::SDA_AP_DBGENCTRL_ENABLE_M7,
)?;
interface.flush()
}
fn debug_enablement(
&self,
interface: &mut dyn ArmDebugInterface,
memory_ap: &FullyQualifiedApAddress,
) -> Result<(), ArmError> {
self.enable_m7_debug(interface, memory_ap.dp())?;
let mut memory = interface.memory_interface(memory_ap)?;
self.enable_peripheral_clocks(&mut *memory)?;
self.ram_initialize(&mut *memory)
}
fn enable_peripheral_clocks(
&self,
memory: &mut dyn ArmMemoryInterface,
) -> Result<(), ArmError> {
tracing::debug!("Enabling peripheral clocks");
let mut enable_partition = |partition: u64, cofb_clken: &[u32]| -> Result<(), ArmError> {
let prtn = Self::MC_ME + 0x100 + partition * 0x200;
for (block, &clken) in cofb_clken.iter().enumerate() {
if clken != 0 {
memory.write_word_32(prtn + 0x30 + block as u64 * 4, clken)?;
}
}
memory.write_word_32(prtn, 1)?;
memory.write_word_32(prtn + 4, 1)?;
memory.write_word_32(Self::MC_ME, 0x5AF0)?;
memory.write_word_32(Self::MC_ME, 0xA50F)?;
Ok(())
};
enable_partition(0, &[0, 0x0000_F7DF])?;
enable_partition(1, &[0xB1E0_FFF8, 0x812A_A407, 0xBBF3_FE7E, 0x0000_0141])?;
if self.has_clock_partition2 {
enable_partition(2, &[0x29FF_FFF0, 0xC489_87F9])?;
}
memory.flush()
}
fn ram_initialize(&self, memory: &mut dyn ArmMemoryInterface) -> Result<(), ArmError> {
if self.sram_size != 0 {
tracing::debug!("Initializing {} bytes of SRAM via DMA", self.sram_size);
self.dma_fill(memory, Self::SRAM_BASE as u32, self.sram_size)?;
}
if self.dtcm_size != 0 {
tracing::debug!("Initializing {} bytes of DTCM via DMA", self.dtcm_size);
self.dma_fill(memory, Self::DTCM_BACKDOOR, self.dtcm_size)?;
}
Ok(())
}
fn dma_fill(
&self,
memory: &mut dyn ArmMemoryInterface,
dest: u32,
len: u32,
) -> Result<(), ArmError> {
const TCD: u64 = S32K3xx::EDMA_TCD0;
const CH0_CSR_DONE: u32 = 1 << 30;
memory.write_word_8(Self::DMAMUX0_CHCFG0, 0x80)?;
memory.write_word_32(TCD, CH0_CSR_DONE)?;
memory.write_word_32(TCD + 0x20, 0x0040_0000)?;
memory.write_word_32(TCD + 0x24, 0x0303_0000)?;
memory.write_word_32(TCD + 0x28, len)?;
memory.write_word_32(TCD + 0x2C, 0)?;
memory.write_word_32(TCD + 0x30, dest)?;
memory.write_word_32(TCD + 0x34, 0x0001_0008)?;
memory.write_word_32(TCD + 0x38, len.wrapping_neg())?;
memory.write_word_32(TCD + 0x3C, 1)?;
memory.flush()?;
let start = Instant::now();
while memory.read_word_32(TCD)? & CH0_CSR_DONE == 0 {
if start.elapsed() > Duration::from_secs(1) {
tracing::warn!("Timed out waiting for the RAM initialization DMA transfer");
return Err(ArmError::Timeout);
}
thread::sleep(Duration::from_millis(1));
}
Ok(())
}
fn release_reset_pin(&self, probe: &mut dyn ArmDebugInterface) -> Result<(), ArmError> {
let mut n_reset = Pins(0);
n_reset.set_nreset(true);
let n_reset = n_reset.0 as u32;
let can_read_pins = probe.swj_pins(n_reset, n_reset, 0)? != 0xffff_ffff;
if can_read_pins {
let start = Instant::now();
loop {
if Pins(probe.swj_pins(n_reset, n_reset, 0)? as u8).nreset() {
return Ok(());
}
if start.elapsed() >= Duration::from_secs(1) {
return Err(ArmError::Timeout);
}
thread::sleep(Duration::from_millis(100));
}
} else {
thread::sleep(Duration::from_millis(100));
Ok(())
}
}
}
impl ArmDebugSequence for S32K3xx {
fn reset_hardware_assert(&self, interface: &mut dyn DapProbe) -> Result<(), ArmError> {
self.connect_under_reset.store(true, Ordering::Relaxed);
let mut n_reset = Pins(0);
n_reset.set_nreset(true);
let _ = interface.swj_pins(0, n_reset.0 as u32, 0)?;
Ok(())
}
fn debug_device_unlock(
&self,
interface: &mut dyn ArmDebugInterface,
default_ap: &FullyQualifiedApAddress,
_permissions: &crate::Permissions,
) -> Result<(), ArmError> {
let dp = default_ap.dp();
if self.connect_under_reset.load(Ordering::Relaxed) {
self.enable_m7_debug(interface, dp)?;
interface.write_raw_ap_register(
&Self::mdm_ap(dp),
Self::MDM_AP_CTL,
Self::MDM_AP_CTL_CORE_ACCESS,
)?;
interface.write_raw_ap_register(&Self::sda_ap(dp), Self::SDA_AP_RSTCTRL, 0)?;
interface.flush()?;
self.release_reset_pin(interface)
} else {
self.enable_m7_debug(interface, default_ap.dp())
}
}
fn reset_hardware_deassert(
&self,
probe: &mut dyn ArmDebugInterface,
default_ap: &FullyQualifiedApAddress,
) -> Result<(), ArmError> {
let release = if default_ap.ap_v1()? == 5 {
Self::SDA_AP_RSTCTRL_RELEASE_CM7_1
} else {
Self::SDA_AP_RSTCTRL_RELEASE_CM7_0
};
let result = probe
.write_raw_ap_register(
&Self::sda_ap(default_ap.dp()),
Self::SDA_AP_RSTCTRL,
release,
)
.and_then(|_| probe.flush());
if let Err(error) = result {
tracing::warn!("Ignoring error while releasing the core from reset: {error}");
}
if let Err(error) = self.debug_enablement(probe, default_ap) {
tracing::warn!("Ignoring error during debug enablement: {error}");
}
self.connect_under_reset.store(false, Ordering::Relaxed);
Ok(())
}
fn reset_system(
&self,
interface: &mut dyn ArmMemoryInterface,
_core_type: probe_rs_target::CoreType,
_debug_base: Option<u64>,
) -> Result<(), ArmError> {
let demcr = Demcr(interface.read_word_32(Demcr::get_mmio_address())?);
tracing::debug!("Initiating functional reset");
let dp = interface.fully_qualified_address().dp();
let mdm_ap = Self::mdm_ap(dp);
let probe = interface.get_arm_debug_interface()?;
probe.write_raw_ap_register(&mdm_ap, Self::MDM_AP_CTL, Self::MDM_AP_CTL_RSTREL_DBGREQ)?;
probe.write_raw_ap_register(
&mdm_ap,
Self::MDM_AP_CTL,
Self::MDM_AP_CTL_RSTREL_DBGREQ_FUNCRST,
)?;
probe.write_raw_ap_register(&mdm_ap, Self::MDM_AP_CTL, Self::MDM_AP_CTL_RSTREL_DBGREQ)?;
probe.write_raw_ap_register(&mdm_ap, Self::MDM_AP_CTL, Self::MDM_AP_CTL_RSTREL)?;
probe.flush()?;
sequences::cortex_m_wait_for_reset(interface)?;
if demcr.vc_corereset() {
self.enable_peripheral_clocks(interface)?;
self.ram_initialize(interface)?;
}
Ok(())
}
}