use std::sync::Arc;
use crate::{
MemoryMappedRegister,
architecture::arm::{
ArmError,
armv6m::{Aircr, Demcr},
dp::{Ctrl, DpAddress, DpRegister},
memory::ArmMemoryInterface,
sequences::{ArmDebugSequence, cortex_m_wait_for_reset},
},
};
const SIO_CPUID_OFFSET: u64 = 0xd000_0000;
const RESCUE_DP: DpAddress = DpAddress::Multidrop(0xf100_2927);
const CORE_1_DP: DpAddress = DpAddress::Multidrop(0x1100_2927);
#[derive(Debug)]
pub struct Rp2040 {}
impl Rp2040 {
pub fn create() -> Arc<Self> {
Arc::new(Rp2040 {})
}
}
impl ArmDebugSequence for Rp2040 {
fn reset_system(
&self,
core: &mut dyn ArmMemoryInterface,
core_type: crate::CoreType,
debug_base: Option<u64>,
) -> Result<(), ArmError> {
tracing::trace!("Starting reset of RP2040");
let core_id = core.read_word_32(SIO_CPUID_OFFSET)?;
if core_id != 0 {
tracing::error!("Skipping reset of core {core_id}");
return Ok(());
}
let should_catch_reset =
Demcr(core.read_word_32(Demcr::get_mmio_address())?).vc_corereset();
let ap = core.fully_qualified_address();
let arm_interface = core.get_arm_debug_interface()?;
let existing_core_0 = arm_interface.read_raw_dp_register(ap.dp(), Ctrl::ADDRESS)?;
let existing_core_1 = arm_interface.read_raw_dp_register(CORE_1_DP, Ctrl::ADDRESS)?;
arm_interface.write_raw_dp_register(RESCUE_DP, Ctrl::ADDRESS, 0)?;
tracing::trace!(
"Existing values core0: {existing_core_0:08x} core1: {existing_core_1:08x}"
);
let _val = arm_interface.read_raw_dp_register(RESCUE_DP, Ctrl::ADDRESS)?;
let dap_probe = arm_interface.try_dap_probe_mut().unwrap();
self.debug_port_setup(dap_probe, ap.dp())?;
self.debug_core_start(arm_interface, &ap, core_type, debug_base, None)?;
tracing::trace!("Restoring ctrl values");
arm_interface.write_raw_dp_register(ap.dp(), Ctrl::ADDRESS, existing_core_0)?;
arm_interface.write_raw_dp_register(CORE_1_DP, Ctrl::ADDRESS, existing_core_1)?;
if should_catch_reset {
tracing::trace!("Re-setting reset catch");
self.reset_catch_set(core, core_type, debug_base)?
}
let mut aircr = Aircr(0);
aircr.vectkey();
aircr.set_sysresetreq(true);
core.write_word_32(Aircr::get_mmio_address(), aircr.into())?;
cortex_m_wait_for_reset(core)?;
tracing::trace!("Finished RP2040 reset sequence");
Ok(())
}
}