use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
use std::time::{Duration, Instant};
use crate::architecture::arm::armv7a::{
clear_hw_breakpoint, get_hw_breakpoint, read_word_32, request_halt, run, set_hw_breakpoint,
wait_for_core_halted, write_word_32,
};
use crate::architecture::arm::communication_interface::DapProbe;
use crate::architecture::arm::memory::ArmMemoryInterface;
use crate::architecture::arm::sequences::{ArmDebugSequence, ArmDebugSequenceError};
use crate::architecture::arm::{ArmError, dp::DpAddress};
use crate::probe::WireProtocol;
use super::icepick::Icepick;
const TMS570_TAP_INDEX: u8 = 0;
const HALT_DELAY: Duration = Duration::from_millis(100);
#[derive(Debug)]
pub struct TMS570 {
existing_breakpoint: AtomicU32,
breakpoint_active: AtomicBool,
}
impl TMS570 {
pub fn create(_name: String) -> Arc<Self> {
Arc::new(Self {
existing_breakpoint: AtomicU32::new(0),
breakpoint_active: AtomicBool::new(false),
})
}
}
impl ArmDebugSequence for TMS570 {
fn reset_catch_set(
&self,
memory: &mut dyn ArmMemoryInterface,
_core_type: probe_rs_target::CoreType,
debug_base: Option<u64>,
) -> Result<(), ArmError> {
let base_address = debug_base.ok_or(ArmError::NoArmTarget)?;
request_halt(memory, base_address)?;
wait_for_core_halted(memory, base_address, HALT_DELAY)?;
let existing = get_hw_breakpoint(memory, base_address, 0)?;
if let Some(existing) = existing {
self.existing_breakpoint.store(existing, Ordering::Release);
}
self.breakpoint_active
.store(existing.is_some(), Ordering::Relaxed);
set_hw_breakpoint(memory, base_address, 0, 0)?;
run(memory, base_address)?;
Ok(())
}
fn reset_catch_clear(
&self,
memory: &mut dyn ArmMemoryInterface,
_core_type: probe_rs_target::CoreType,
debug_base: Option<u64>,
) -> Result<(), ArmError> {
let base_address = debug_base.ok_or(ArmError::NoArmTarget)?;
request_halt(memory, base_address)?;
wait_for_core_halted(memory, base_address, HALT_DELAY)?;
if self.breakpoint_active.swap(false, Ordering::Release) {
set_hw_breakpoint(
memory,
base_address,
0,
self.existing_breakpoint.load(Ordering::Relaxed),
)?;
} else {
clear_hw_breakpoint(memory, base_address, 0)?;
}
write_word_32(memory, base_address, 0xffff_ff5c, 0xa)?;
write_word_32(memory, base_address, 0xffff_ff60, 1)?;
let start = Instant::now();
while read_word_32(memory, base_address, 0xffff_ff68)? & (1 << 8) == 0 {
if start.elapsed() >= HALT_DELAY {
return Err(ArmError::Timeout);
}
std::thread::sleep(Duration::from_millis(1));
}
write_word_32(memory, base_address, 0xffff_ff5c, 0x5)?;
Ok(())
}
fn reset_system(
&self,
interface: &mut dyn ArmMemoryInterface,
_core_type: probe_rs_target::CoreType,
_debug_base: Option<u64>,
) -> Result<(), ArmError> {
let arm_debug = interface.get_arm_debug_interface()?;
let probe = arm_debug.try_dap_probe_mut().ok_or(ArmError::NoArmTarget)?;
let mut icepick = Icepick::initialized(probe)?;
icepick.sysreset()?;
icepick.bypass()?;
Ok(())
}
fn debug_port_setup(
&self,
interface: &mut dyn DapProbe,
_dp: DpAddress,
) -> Result<(), ArmError> {
interface.swj_sequence(51, 0x0007_FFFF_FFFF_FFFF)?;
match interface.active_protocol() {
Some(WireProtocol::Jtag) => {
let mut icepick = Icepick::new(interface)?;
icepick.select_tap(TMS570_TAP_INDEX)?;
interface.configure_jtag(true)?;
}
Some(WireProtocol::Swd) => {
return Err(ArmDebugSequenceError::SequenceSpecific(
"The tms570 family doesn't support SWD".into(),
)
.into());
}
_ => {
return Err(ArmDebugSequenceError::SequenceSpecific(
"Cannot detect current protocol".into(),
)
.into());
}
}
Ok(())
}
}