mod protocol;
use crate::{
architecture::{
riscv::{
communication_interface::{RiscvError, RiscvInterfaceBuilder},
dtm::jtag_dtm::JtagDtmBuilder,
},
xtensa::communication_interface::{
XtensaCommunicationInterface, XtensaDebugInterfaceState, XtensaError,
},
},
probe::{
AutoImplementJtagAccess, DebugProbe, DebugProbeError, DebugProbeInfo, DebugProbeSelector,
JtagAccess, JtagDriverState, ProbeFactory, RawJtagIo, WireProtocol,
},
};
use bitvec::prelude::*;
use self::protocol::ProtocolHandler;
#[derive(Debug)]
pub struct EspUsbJtagFactory;
impl std::fmt::Display for EspUsbJtagFactory {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("EspJtag")
}
}
impl ProbeFactory for EspUsbJtagFactory {
fn open(&self, selector: &DebugProbeSelector) -> Result<Box<dyn DebugProbe>, DebugProbeError> {
let protocol = ProtocolHandler::new_from_selector(selector)?;
Ok(Box::new(EspUsbJtag {
protocol,
jtag_state: JtagDriverState::default(),
}))
}
fn list_probes(&self) -> Vec<DebugProbeInfo> {
protocol::list_espjtag_devices()
}
}
#[derive(Debug)]
pub struct EspUsbJtag {
protocol: ProtocolHandler,
jtag_state: JtagDriverState,
}
impl RawJtagIo for EspUsbJtag {
fn shift_bit(
&mut self,
tms: bool,
tdi: bool,
capture_tdo: bool,
) -> Result<(), DebugProbeError> {
self.jtag_state.state.update(tms);
self.protocol.shift_bit(tms, tdi, capture_tdo)?;
Ok(())
}
fn read_captured_bits(&mut self) -> Result<BitVec, DebugProbeError> {
self.protocol.read_captured_bits()
}
fn state_mut(&mut self) -> &mut JtagDriverState {
&mut self.jtag_state
}
fn state(&self) -> &JtagDriverState {
&self.jtag_state
}
}
impl AutoImplementJtagAccess for EspUsbJtag {}
impl DebugProbe for EspUsbJtag {
fn select_protocol(&mut self, protocol: WireProtocol) -> Result<(), DebugProbeError> {
if matches!(protocol, WireProtocol::Jtag) {
Ok(())
} else {
Err(DebugProbeError::UnsupportedProtocol(protocol))
}
}
fn active_protocol(&self) -> Option<WireProtocol> {
Some(WireProtocol::Jtag)
}
fn get_name(&self) -> &'static str {
"Esp USB JTAG"
}
fn speed_khz(&self) -> u32 {
self.protocol.base_speed_khz / self.protocol.div_min as u32
}
fn set_speed(&mut self, speed_khz: u32) -> Result<u32, DebugProbeError> {
Ok(speed_khz)
}
fn attach(&mut self) -> Result<(), DebugProbeError> {
tracing::debug!("Attaching to ESP USB JTAG");
self.select_target(0)
}
fn detach(&mut self) -> Result<(), crate::Error> {
Ok(())
}
fn target_reset(&mut self) -> Result<(), DebugProbeError> {
Err(DebugProbeError::NotImplemented {
function_name: "target_reset",
})
}
fn target_reset_assert(&mut self) -> Result<(), DebugProbeError> {
tracing::info!("reset_assert!");
self.protocol.set_reset(true)?;
Ok(())
}
fn target_reset_deassert(&mut self) -> Result<(), DebugProbeError> {
tracing::info!("reset_deassert!");
self.protocol.set_reset(false)?;
Ok(())
}
fn try_as_jtag_probe(&mut self) -> Option<&mut dyn JtagAccess> {
Some(self)
}
fn try_get_riscv_interface_builder<'probe>(
&'probe mut self,
) -> Result<Box<dyn RiscvInterfaceBuilder<'probe> + 'probe>, RiscvError> {
Ok(Box::new(JtagDtmBuilder::new(self)))
}
fn has_riscv_interface(&self) -> bool {
true
}
fn into_probe(self: Box<Self>) -> Box<dyn DebugProbe> {
self
}
fn try_get_xtensa_interface<'probe>(
&'probe mut self,
state: &'probe mut XtensaDebugInterfaceState,
) -> Result<XtensaCommunicationInterface<'probe>, XtensaError> {
Ok(XtensaCommunicationInterface::new(self, state))
}
fn has_xtensa_interface(&self) -> bool {
true
}
}