use std::{fmt::Debug, sync::Arc};
use crate::{
architecture::arm::{
ap::{memory_ap::mock::MockMemoryAp, AccessPort, MemoryAp},
communication_interface::{
ArmDebugState, Initialized, SwdSequence, Uninitialized, UninitializedArmProbe,
},
dp::DebugPortError,
memory::adi_v5_memory_interface::{ADIMemoryInterface, ArmProbe},
sequences::ArmDebugSequence,
ApAddress, ArmError, ArmProbeInterface, DapAccess, DpAddress, MemoryApInformation,
PortType, RawDapAccess, SwoAccess,
},
DebugProbe, DebugProbeError, DebugProbeSelector, Error, Probe, WireProtocol,
};
#[allow(clippy::type_complexity)]
pub struct FakeProbe {
protocol: WireProtocol,
speed: u32,
dap_register_read_handler: Option<Box<dyn Fn(PortType, u8) -> Result<u32, ArmError> + Send>>,
dap_register_write_handler:
Option<Box<dyn Fn(PortType, u8, u32) -> Result<(), ArmError> + Send>>,
}
impl Debug for FakeProbe {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FakeProbe")
.field("protocol", &self.protocol)
.field("speed", &self.speed)
.finish()
}
}
impl FakeProbe {
pub fn new() -> Self {
FakeProbe {
protocol: WireProtocol::Swd,
speed: 1000,
dap_register_read_handler: None,
dap_register_write_handler: None,
}
}
pub fn set_dap_register_read_handler(
&mut self,
handler: Box<dyn Fn(PortType, u8) -> Result<u32, ArmError> + Send>,
) {
self.dap_register_read_handler = Some(handler);
}
pub fn set_dap_register_write_handler(
&mut self,
handler: Box<dyn Fn(PortType, u8, u32) -> Result<(), ArmError> + Send>,
) {
self.dap_register_write_handler = Some(handler);
}
pub fn into_probe(self) -> Probe {
Probe::from_specific_probe(Box::new(self))
}
}
impl Default for FakeProbe {
fn default() -> Self {
FakeProbe::new()
}
}
impl DebugProbe for FakeProbe {
fn new_from_selector(
_selector: impl Into<DebugProbeSelector>,
) -> Result<Box<Self>, DebugProbeError>
where
Self: Sized,
{
Ok(Box::new(FakeProbe::new()))
}
fn get_name(&self) -> &str {
"Mock probe for testing"
}
fn speed_khz(&self) -> u32 {
self.speed
}
fn set_speed(&mut self, speed_khz: u32) -> Result<u32, DebugProbeError> {
self.speed = speed_khz;
Ok(speed_khz)
}
fn attach(&mut self) -> Result<(), DebugProbeError> {
Ok(())
}
fn select_protocol(&mut self, protocol: WireProtocol) -> Result<(), DebugProbeError> {
self.protocol = protocol;
Ok(())
}
fn active_protocol(&self) -> Option<WireProtocol> {
Some(self.protocol)
}
fn detach(&mut self) -> Result<(), crate::Error> {
Ok(())
}
fn target_reset(&mut self) -> Result<(), DebugProbeError> {
Err(DebugProbeError::CommandNotSupportedByProbe("target_reset"))
}
fn target_reset_assert(&mut self) -> Result<(), DebugProbeError> {
unimplemented!()
}
fn target_reset_deassert(&mut self) -> Result<(), DebugProbeError> {
unimplemented!()
}
fn into_probe(self: Box<Self>) -> Box<dyn DebugProbe> {
self
}
fn try_get_arm_interface<'probe>(
self: Box<Self>,
) -> Result<Box<dyn UninitializedArmProbe + 'probe>, (Box<dyn DebugProbe>, DebugProbeError)>
{
Ok(Box::new(FakeArmInterface::new(self)))
}
fn has_arm_interface(&self) -> bool {
true
}
}
impl RawDapAccess for FakeProbe {
fn select_dp(&mut self, _dp: DpAddress) -> Result<(), ArmError> {
Err(DebugPortError::Unsupported(
"Fake debug probe does not support DP selection.".to_string(),
)
.into())
}
fn raw_read_register(&mut self, port: PortType, addr: u8) -> Result<u32, ArmError> {
let handler = self.dap_register_read_handler.as_ref().unwrap();
handler(port, addr)
}
fn raw_write_register(&mut self, port: PortType, addr: u8, value: u32) -> Result<(), ArmError> {
let handler = self.dap_register_write_handler.as_ref().unwrap();
handler(port, addr, value)
}
fn swj_sequence(&mut self, _bit_len: u8, _bits: u64) -> Result<(), DebugProbeError> {
todo!()
}
fn swj_pins(
&mut self,
_pin_out: u32,
_pin_select: u32,
_pin_wait: u32,
) -> Result<u32, DebugProbeError> {
todo!()
}
fn into_probe(self: Box<Self>) -> Box<dyn DebugProbe> {
self
}
}
#[derive(Debug)]
struct FakeArmInterface<S: ArmDebugState> {
probe: Box<FakeProbe>,
memory_ap: MockMemoryAp,
_state: S,
}
impl FakeArmInterface<Uninitialized> {
pub(crate) fn new(probe: Box<FakeProbe>) -> Self {
let state = Uninitialized {
use_overrun_detect: false,
};
let memory_ap = MockMemoryAp::with_pattern();
Self {
probe,
_state: state,
memory_ap,
}
}
fn into_initialized(
self,
sequence: Arc<dyn ArmDebugSequence>,
) -> Result<FakeArmInterface<Initialized>, (Box<Self>, DebugProbeError)> {
Ok(FakeArmInterface::<Initialized>::from_uninitialized(
self, sequence,
))
}
}
impl FakeArmInterface<Initialized> {
fn from_uninitialized(
interface: FakeArmInterface<Uninitialized>,
sequence: Arc<dyn ArmDebugSequence>,
) -> Self {
let memory_ap = MockMemoryAp::with_pattern();
FakeArmInterface::<Initialized> {
probe: interface.probe,
_state: Initialized::new(sequence, false),
memory_ap,
}
}
}
impl<S: ArmDebugState> SwdSequence for FakeArmInterface<S> {
fn swj_sequence(&mut self, bit_len: u8, bits: u64) -> Result<(), DebugProbeError> {
self.probe.swj_sequence(bit_len, bits)?;
Ok(())
}
fn swj_pins(
&mut self,
pin_out: u32,
pin_select: u32,
pin_wait: u32,
) -> Result<u32, DebugProbeError> {
let value = self.probe.swj_pins(pin_out, pin_select, pin_wait)?;
Ok(value)
}
}
impl UninitializedArmProbe for FakeArmInterface<Uninitialized> {
fn initialize(
self: Box<Self>,
sequence: Arc<dyn ArmDebugSequence>,
) -> Result<Box<dyn ArmProbeInterface>, (Box<dyn UninitializedArmProbe>, Error)> {
let interface = self
.into_initialized(sequence)
.map_err(|(s, err)| (s as Box<_>, Error::Probe(err)))?;
Ok(Box::new(interface))
}
fn close(self: Box<Self>) -> Probe {
Probe::from_attached_probe(self.probe)
}
}
impl ArmProbeInterface for FakeArmInterface<Initialized> {
fn memory_interface(
&mut self,
access_port: MemoryAp,
) -> Result<Box<dyn ArmProbe + '_>, ArmError> {
let ap_information = MemoryApInformation {
address: access_port.ap_address(),
supports_only_32bit_data_size: false,
debug_base_address: 0xf000_0000,
supports_hnonsec: false,
has_large_data_extension: false,
has_large_address_extension: false,
device_enabled: true,
};
let memory = ADIMemoryInterface::new(&mut self.memory_ap, ap_information)
.map_err(|e| ArmError::from_access_port(e, access_port))?;
Ok(Box::new(memory) as _)
}
fn ap_information(
&mut self,
_access_port: crate::architecture::arm::ap::GenericAp,
) -> Result<&crate::architecture::arm::ApInformation, ArmError> {
todo!()
}
fn num_access_ports(&mut self, _dp: DpAddress) -> Result<usize, ArmError> {
Ok(1)
}
fn read_chip_info_from_rom_table(
&mut self,
_dp: DpAddress,
) -> Result<Option<crate::architecture::arm::ArmChipInfo>, ArmError> {
Ok(None)
}
fn close(self: Box<Self>) -> Probe {
Probe::from_attached_probe(self.probe)
}
}
impl SwoAccess for FakeArmInterface<Initialized> {
fn enable_swo(
&mut self,
_config: &crate::architecture::arm::SwoConfig,
) -> Result<(), ArmError> {
unimplemented!()
}
fn disable_swo(&mut self) -> Result<(), ArmError> {
unimplemented!()
}
fn read_swo_timeout(&mut self, _timeout: std::time::Duration) -> Result<Vec<u8>, ArmError> {
unimplemented!()
}
}
impl DapAccess for FakeArmInterface<Initialized> {
fn read_raw_dp_register(&mut self, _dp: DpAddress, _address: u8) -> Result<u32, ArmError> {
todo!()
}
fn write_raw_dp_register(
&mut self,
_dp: DpAddress,
_address: u8,
_value: u32,
) -> Result<(), ArmError> {
todo!()
}
fn read_raw_ap_register(&mut self, _ap: ApAddress, _address: u8) -> Result<u32, ArmError> {
todo!()
}
fn read_raw_ap_register_repeated(
&mut self,
_ap: ApAddress,
_address: u8,
_values: &mut [u32],
) -> Result<(), ArmError> {
todo!()
}
fn write_raw_ap_register(
&mut self,
_ap: ApAddress,
_address: u8,
_value: u32,
) -> Result<(), ArmError> {
todo!()
}
fn write_raw_ap_register_repeated(
&mut self,
_ap: ApAddress,
_address: u8,
_values: &[u32],
) -> Result<(), ArmError> {
todo!()
}
}
#[cfg(test)]
mod test {
use super::FakeProbe;
use crate::Permissions;
#[test]
fn create_session_with_fake_probe() {
let fake_probe = FakeProbe::new();
let probe = fake_probe.into_probe();
probe
.attach("nrf51822_xxAC", Permissions::default())
.unwrap();
}
}