1pub(crate) mod common;
3pub(crate) mod usb_util;
4
5pub mod blackmagic;
6pub mod ch347usbjtag;
7pub mod cmsisdap;
8pub mod espusbjtag;
9pub mod fake_probe;
10pub mod ftdi;
11pub mod glasgow;
12pub mod jlink;
13pub mod list;
14pub mod sifliuart;
15pub mod stlink;
16pub mod wlink;
17
18use crate::architecture::arm::sequences::{ArmDebugSequence, DefaultArmSequence};
19use crate::architecture::arm::{ArmDebugInterface, ArmError, DapError};
20use crate::architecture::arm::{RegisterAddress, SwoAccess, communication_interface::DapProbe};
21use crate::architecture::riscv::communication_interface::{RiscvError, RiscvInterfaceBuilder};
22use crate::architecture::xtensa::communication_interface::{
23 XtensaCommunicationInterface, XtensaDebugInterfaceState, XtensaError,
24};
25use crate::config::TargetSelector;
26use crate::config::registry::Registry;
27use crate::probe::common::JtagState;
28use crate::{Error, Permissions, Session};
29use bitvec::slice::BitSlice;
30use bitvec::vec::BitVec;
31use common::ScanChainError;
32use nusb::DeviceInfo;
33use probe_rs_target::ScanChainElement;
34use serde::{Deserialize, Deserializer, Serialize, Serializer};
35use std::any::Any;
36use std::collections::HashMap;
37use std::fmt;
38use std::sync::Arc;
39
40const LOW_TARGET_VOLTAGE_WARNING_THRESHOLD: f32 = 1.4;
43
44#[derive(Copy, Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize)]
48pub enum WireProtocol {
49 Swd,
52 Jtag,
55}
56
57impl fmt::Display for WireProtocol {
58 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
59 match self {
60 WireProtocol::Swd => f.write_str("SWD"),
61 WireProtocol::Jtag => f.write_str("JTAG"),
62 }
63 }
64}
65
66impl std::str::FromStr for WireProtocol {
67 type Err = String;
68
69 fn from_str(s: &str) -> Result<Self, Self::Err> {
70 match &s.to_ascii_lowercase()[..] {
71 "swd" => Ok(WireProtocol::Swd),
72 "jtag" => Ok(WireProtocol::Jtag),
73 _ => Err(format!(
74 "'{s}' is not a valid protocol. Choose either 'swd' or 'jtag'."
75 )),
76 }
77 }
78}
79
80#[derive(Clone, Debug)]
85pub enum BatchCommand {
86 Read(RegisterAddress),
88
89 Write(RegisterAddress, u32),
91}
92
93impl fmt::Display for BatchCommand {
94 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95 match self {
96 BatchCommand::Read(port) => {
97 write!(f, "Read(port={port:?})")
98 }
99 BatchCommand::Write(port, data) => {
100 write!(f, "Write(port={port:?}, data={data:#010x})")
101 }
102 }
103 }
104}
105
106pub trait ProbeError: std::error::Error + Send + Sync + std::any::Any {}
108
109impl std::error::Error for Box<dyn ProbeError> {
110 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
111 self.as_ref().source()
112 }
113}
114
115#[derive(Debug, thiserror::Error)]
117#[error(transparent)]
118pub struct BoxedProbeError(#[from] Box<dyn ProbeError>);
119
120impl BoxedProbeError {
121 fn as_any(&self) -> &dyn std::any::Any {
122 self.0.as_ref()
123 }
124
125 pub fn is<T: ProbeError>(&self) -> bool {
127 self.as_any().is::<T>()
128 }
129
130 pub fn downcast_ref<T: ProbeError>(&self) -> Option<&T> {
132 self.as_any().downcast_ref()
133 }
134
135 pub fn downcast_mut<T: ProbeError>(&mut self) -> Option<&mut T> {
137 let any: &mut dyn std::any::Any = self.0.as_mut();
138 any.downcast_mut()
139 }
140}
141
142impl<T> From<T> for BoxedProbeError
143where
144 T: ProbeError,
145{
146 fn from(e: T) -> Self {
147 BoxedProbeError(Box::new(e))
148 }
149}
150
151#[derive(thiserror::Error, Debug, docsplay::Display)]
153pub enum DebugProbeError {
154 Usb(#[source] std::io::Error),
156
157 ProbeSpecific(#[source] BoxedProbeError),
159
160 ProbeCouldNotBeCreated(#[from] ProbeCreationError),
162
163 UnsupportedProtocol(WireProtocol),
165
166 #[ignore_extra_doc_attributes]
173 InterfaceNotAvailable {
174 interface_name: &'static str,
176 },
177
178 UnsupportedSpeed(u32),
180
181 #[ignore_extra_doc_attributes]
186 NotAttached,
187
188 #[ignore_extra_doc_attributes]
193 Attached,
194
195 TargetNotFound,
197
198 BatchError(BatchCommand),
200
201 #[ignore_extra_doc_attributes]
206 NotImplemented {
207 function_name: &'static str,
209 },
210
211 CommandNotSupportedByProbe {
214 command_name: &'static str,
216 },
217
218 JtagScanChain(#[from] ScanChainError),
220
221 #[display("{0}")]
223 Other(String),
224
225 Timeout,
227}
228
229impl<T: ProbeError> From<T> for DebugProbeError {
230 fn from(e: T) -> Self {
231 Self::ProbeSpecific(BoxedProbeError::from(e))
232 }
233}
234
235#[derive(thiserror::Error, Debug, docsplay::Display)]
240pub enum ProbeCreationError {
241 NotFound,
244
245 CouldNotOpen,
247
248 #[cfg(feature = "cmsisdap_v1")]
250 HidApi(#[from] hidapi::HidError),
251
252 Usb(#[source] std::io::Error),
254
255 ProbeSpecific(#[source] BoxedProbeError),
257
258 #[display("{0}")]
260 Other(&'static str),
261}
262
263impl<T: ProbeError> From<T> for ProbeCreationError {
264 fn from(e: T) -> Self {
265 Self::ProbeSpecific(BoxedProbeError::from(e))
266 }
267}
268
269#[derive(Debug)]
288pub struct Probe {
289 inner: Box<dyn DebugProbe>,
290 attached: bool,
291}
292
293impl Probe {
294 pub fn new(probe: impl DebugProbe + 'static) -> Self {
296 Self {
297 inner: Box::new(probe),
298 attached: false,
299 }
300 }
301
302 pub(crate) fn from_attached_probe(probe: Box<dyn DebugProbe>) -> Self {
303 Self {
304 inner: probe,
305 attached: true,
306 }
307 }
308
309 pub fn from_specific_probe(probe: Box<dyn DebugProbe>) -> Self {
311 Probe {
312 inner: probe,
313 attached: false,
314 }
315 }
316
317 pub fn get_name(&self) -> String {
319 self.inner.get_name().to_string()
320 }
321
322 pub fn attach(
329 self,
330 target: impl Into<TargetSelector>,
331 permissions: Permissions,
332 ) -> Result<Session, Error> {
333 let registry = Registry::from_builtin_families();
334 self.attach_with_registry(target, permissions, ®istry)
335 }
336
337 pub fn attach_with_registry(
344 self,
345 target: impl Into<TargetSelector>,
346 permissions: Permissions,
347 registry: &Registry,
348 ) -> Result<Session, Error> {
349 Session::new(
350 self,
351 target.into(),
352 AttachMethod::Normal,
353 permissions,
354 registry,
355 )
356 }
357
358 pub fn attach_to_unspecified(&mut self) -> Result<(), Error> {
361 self.inner.attach()?;
362 self.attached = true;
363 Ok(())
364 }
365
366 pub fn attach_to_unspecified_under_reset(&mut self) -> Result<(), Error> {
368 if let Some(dap_probe) = self.try_as_dap_probe() {
369 DefaultArmSequence(()).reset_hardware_assert(dap_probe)?;
370 } else {
371 tracing::info!(
372 "Custom reset sequences are not supported on {}.",
373 self.get_name()
374 );
375 tracing::info!("Falling back to standard probe reset.");
376 self.target_reset_assert()?;
377 }
378 self.attach_to_unspecified()?;
379 Ok(())
380 }
381
382 pub fn attach_under_reset(
390 self,
391 target: impl Into<TargetSelector>,
392 permissions: Permissions,
393 ) -> Result<Session, Error> {
394 let registry = Registry::from_builtin_families();
395 self.attach_under_reset_with_registry(target, permissions, ®istry)
396 }
397
398 pub fn attach_under_reset_with_registry(
406 self,
407 target: impl Into<TargetSelector>,
408 permissions: Permissions,
409 registry: &Registry,
410 ) -> Result<Session, Error> {
411 Session::new(
413 self,
414 target.into(),
415 AttachMethod::UnderReset,
416 permissions,
417 registry,
418 )
419 .map_err(|e| match e {
420 Error::Arm(ArmError::Timeout)
421 | Error::Riscv(RiscvError::Timeout)
422 | Error::Xtensa(XtensaError::Timeout) => Error::Other(
423 "Timeout while attaching to target under reset. \
424 This can happen if the target is not responding to the reset sequence. \
425 Ensure the chip's reset pin is connected, or try attaching without reset \
426 (`connectUnderReset = false` for DAP Clients, or remove `connect-under-reset` \
427 option from CLI options.)."
428 .to_string(),
429 ),
430 e => e,
431 })
432 }
433
434 pub fn select_protocol(&mut self, protocol: WireProtocol) -> Result<(), DebugProbeError> {
436 if !self.attached {
437 self.inner.select_protocol(protocol)
438 } else {
439 Err(DebugProbeError::Attached)
440 }
441 }
442
443 pub fn protocol(&self) -> Option<WireProtocol> {
447 self.inner.active_protocol()
448 }
449
450 pub fn detach(&mut self) -> Result<(), crate::Error> {
452 self.attached = false;
453 self.inner.detach()?;
454 Ok(())
455 }
456
457 pub fn target_reset(&mut self) -> Result<(), DebugProbeError> {
459 self.inner.target_reset()
460 }
461
462 pub fn target_reset_assert(&mut self) -> Result<(), DebugProbeError> {
467 tracing::debug!("Asserting target reset");
468 self.inner.target_reset_assert()
469 }
470
471 pub fn target_reset_deassert(&mut self) -> Result<(), DebugProbeError> {
476 tracing::debug!("Deasserting target reset");
477 self.inner.target_reset_deassert()
478 }
479
480 pub fn set_speed(&mut self, speed_khz: u32) -> Result<u32, DebugProbeError> {
482 if !self.attached {
483 self.inner.set_speed(speed_khz)
484 } else {
485 Err(DebugProbeError::Attached)
486 }
487 }
488
489 pub fn speed_khz(&self) -> u32 {
495 self.inner.speed_khz()
496 }
497
498 pub fn has_xtensa_interface(&self) -> bool {
501 self.inner.has_xtensa_interface()
502 }
503
504 pub fn try_get_xtensa_interface<'probe>(
513 &'probe mut self,
514 state: &'probe mut XtensaDebugInterfaceState,
515 ) -> Result<XtensaCommunicationInterface<'probe>, XtensaError> {
516 if !self.attached {
517 Err(DebugProbeError::NotAttached.into())
518 } else {
519 Ok(self.inner.try_get_xtensa_interface(state)?)
520 }
521 }
522
523 pub fn has_arm_debug_interface(&self) -> bool {
526 self.inner.has_arm_interface()
527 }
528
529 pub fn try_into_arm_debug_interface<'probe>(
534 self,
535 sequence: Arc<dyn ArmDebugSequence>,
536 ) -> Result<Box<dyn ArmDebugInterface + 'probe>, (Self, ArmError)> {
537 if !self.attached {
538 Err((self, DebugProbeError::NotAttached.into()))
539 } else {
540 self.inner
541 .try_get_arm_debug_interface(sequence)
542 .map_err(|(probe, err)| (Probe::from_attached_probe(probe), err))
543 }
544 }
545
546 pub fn has_riscv_interface(&self) -> bool {
548 self.inner.has_riscv_interface()
549 }
550
551 pub fn try_get_riscv_interface_builder<'probe>(
559 &'probe mut self,
560 ) -> Result<Box<dyn RiscvInterfaceBuilder<'probe> + 'probe>, RiscvError> {
561 if !self.attached {
562 Err(DebugProbeError::NotAttached.into())
563 } else {
564 self.inner.try_get_riscv_interface_builder()
565 }
566 }
567
568 pub fn try_as_jtag_probe(&mut self) -> Option<&mut dyn JtagAccess> {
570 self.inner.try_as_jtag_probe()
571 }
572
573 pub fn get_swo_interface(&self) -> Option<&dyn SwoAccess> {
577 self.inner.get_swo_interface()
578 }
579
580 pub fn get_swo_interface_mut(&mut self) -> Option<&mut dyn SwoAccess> {
584 self.inner.get_swo_interface_mut()
585 }
586
587 pub fn try_as_dap_probe(&mut self) -> Option<&mut dyn DapProbe> {
591 self.inner.try_as_dap_probe()
592 }
593
594 pub fn get_target_voltage(&mut self) -> Result<Option<f32>, DebugProbeError> {
598 self.inner.get_target_voltage()
599 }
600
601 pub fn try_into<P: DebugProbe>(&mut self) -> Option<&mut P> {
603 (self.inner.as_mut() as &mut dyn Any).downcast_mut::<P>()
604 }
605}
606
607pub trait ProbeFactory: std::any::Any + std::fmt::Display + std::fmt::Debug + Sync {
614 fn open(&self, selector: &DebugProbeSelector) -> Result<Box<dyn DebugProbe>, DebugProbeError>;
618
619 fn list_probes(&self) -> Vec<DebugProbeInfo>;
621
622 fn list_probes_filtered(&self, selector: Option<&DebugProbeSelector>) -> Vec<DebugProbeInfo> {
626 self.list_probes()
629 .into_iter()
630 .filter(|probe| selector.as_ref().is_none_or(|s| s.matches_probe(probe)))
631 .collect()
632 }
633}
634
635pub trait DebugProbe: Any + Send + fmt::Debug {
639 fn get_name(&self) -> &str;
641
642 fn speed_khz(&self) -> u32;
648
649 fn set_speed(&mut self, speed_khz: u32) -> Result<u32, DebugProbeError>;
661
662 fn attach(&mut self) -> Result<(), DebugProbeError>;
666
667 fn detach(&mut self) -> Result<(), crate::Error>;
675
676 fn target_reset(&mut self) -> Result<(), DebugProbeError>;
678
679 fn target_reset_assert(&mut self) -> Result<(), DebugProbeError>;
681
682 fn target_reset_deassert(&mut self) -> Result<(), DebugProbeError>;
684
685 fn select_protocol(&mut self, protocol: WireProtocol) -> Result<(), DebugProbeError>;
687
688 fn active_protocol(&self) -> Option<WireProtocol>;
690
691 fn has_arm_interface(&self) -> bool {
693 false
694 }
695
696 fn try_as_jtag_probe(&mut self) -> Option<&mut dyn JtagAccess> {
698 None
699 }
700
701 fn try_get_arm_debug_interface<'probe>(
704 self: Box<Self>,
705 _sequence: Arc<dyn ArmDebugSequence>,
706 ) -> Result<Box<dyn ArmDebugInterface + 'probe>, (Box<dyn DebugProbe>, ArmError)> {
707 Err((
708 self.into_probe(),
709 DebugProbeError::InterfaceNotAvailable {
710 interface_name: "ARM",
711 }
712 .into(),
713 ))
714 }
715
716 fn try_get_riscv_interface_builder<'probe>(
722 &'probe mut self,
723 ) -> Result<Box<dyn RiscvInterfaceBuilder<'probe> + 'probe>, RiscvError> {
724 Err(DebugProbeError::InterfaceNotAvailable {
725 interface_name: "RISC-V",
726 }
727 .into())
728 }
729
730 fn has_riscv_interface(&self) -> bool {
732 false
733 }
734
735 fn try_get_xtensa_interface<'probe>(
738 &'probe mut self,
739 _state: &'probe mut XtensaDebugInterfaceState,
740 ) -> Result<XtensaCommunicationInterface<'probe>, XtensaError> {
741 Err(DebugProbeError::InterfaceNotAvailable {
742 interface_name: "Xtensa",
743 }
744 .into())
745 }
746
747 fn has_xtensa_interface(&self) -> bool {
749 false
750 }
751
752 fn get_swo_interface(&self) -> Option<&dyn SwoAccess> {
756 None
757 }
758
759 fn get_swo_interface_mut(&mut self) -> Option<&mut dyn SwoAccess> {
763 None
764 }
765
766 fn into_probe(self: Box<Self>) -> Box<dyn DebugProbe>;
768
769 fn try_as_dap_probe(&mut self) -> Option<&mut dyn DapProbe> {
773 None
774 }
775
776 fn get_target_voltage(&mut self) -> Result<Option<f32>, DebugProbeError> {
779 Ok(None)
780 }
781}
782
783impl PartialEq for dyn ProbeFactory {
784 fn eq(&self, other: &Self) -> bool {
785 self.type_id() == other.type_id()
789 && std::ptr::eq(
790 self as *const _ as *const (),
791 other as *const _ as *const (),
792 )
793 }
794}
795
796#[derive(Debug, Clone, PartialEq)]
798pub struct DebugProbeInfo {
799 pub identifier: String,
801 pub vendor_id: u16,
803 pub product_id: u16,
805 pub serial_number: Option<String>,
807
808 pub hid_interface: Option<u8>,
811
812 probe_factory: &'static dyn ProbeFactory,
814}
815
816impl std::fmt::Display for DebugProbeInfo {
817 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
818 write!(
819 f,
820 "{} -- {:04x}:{:04x}:{} ({})",
821 self.identifier,
822 self.vendor_id,
823 self.product_id,
824 self.serial_number.as_deref().unwrap_or(""),
825 self.probe_factory,
826 )
827 }
828}
829
830impl DebugProbeInfo {
831 pub fn new<S: Into<String>>(
833 identifier: S,
834 vendor_id: u16,
835 product_id: u16,
836 serial_number: Option<String>,
837 probe_factory: &'static dyn ProbeFactory,
838 hid_interface: Option<u8>,
839 ) -> Self {
840 Self {
841 identifier: identifier.into(),
842 vendor_id,
843 product_id,
844 serial_number,
845 probe_factory,
846 hid_interface,
847 }
848 }
849
850 pub fn open(&self) -> Result<Probe, DebugProbeError> {
852 let selector = DebugProbeSelector::from(self);
853 self.probe_factory
854 .open(&selector)
855 .map(Probe::from_specific_probe)
856 }
857
858 pub fn is_probe_type<F: ProbeFactory>(&self) -> bool {
860 self.probe_factory.type_id() == std::any::TypeId::of::<F>()
861 }
862
863 pub fn probe_type(&self) -> String {
867 self.probe_factory.to_string()
868 }
869}
870
871#[derive(thiserror::Error, Debug, docsplay::Display)]
873pub enum DebugProbeSelectorParseError {
874 ParseInt(#[from] std::num::ParseIntError),
876
877 Format,
879}
880
881#[derive(Debug, Clone, PartialEq, Eq, Hash)]
901pub struct DebugProbeSelector {
902 pub vendor_id: u16,
904 pub product_id: u16,
906 pub serial_number: Option<String>,
908}
909
910impl DebugProbeSelector {
911 pub(crate) fn matches(&self, info: &DeviceInfo) -> bool {
912 self.match_probe_selector(info.vendor_id(), info.product_id(), info.serial_number())
913 }
914
915 pub fn matches_probe(&self, info: &DebugProbeInfo) -> bool {
917 self.match_probe_selector(
918 info.vendor_id,
919 info.product_id,
920 info.serial_number.as_deref(),
921 )
922 }
923
924 fn match_probe_selector(
925 &self,
926 vendor_id: u16,
927 product_id: u16,
928 serial_number: Option<&str>,
929 ) -> bool {
930 vendor_id == self.vendor_id
931 && product_id == self.product_id
932 && self
933 .serial_number
934 .as_ref()
935 .map(|s| {
936 if let Some(serial_number) = serial_number {
937 serial_number == s
938 } else {
939 s.is_empty()
942 }
943 })
944 .unwrap_or(true)
945 }
946}
947
948impl TryFrom<&str> for DebugProbeSelector {
949 type Error = DebugProbeSelectorParseError;
950 fn try_from(value: &str) -> Result<Self, Self::Error> {
951 let mut split = value.splitn(3, ':');
955
956 let vendor_id = split.next().unwrap(); let product_id = split.next().ok_or(DebugProbeSelectorParseError::Format)?;
958 let serial_number = split.next().map(|s| s.to_string());
959
960 Ok(DebugProbeSelector {
961 vendor_id: u16::from_str_radix(vendor_id, 16)?,
962 product_id: u16::from_str_radix(product_id, 16)?,
963 serial_number,
964 })
965 }
966}
967
968impl TryFrom<String> for DebugProbeSelector {
969 type Error = DebugProbeSelectorParseError;
970 fn try_from(value: String) -> Result<Self, Self::Error> {
971 TryFrom::<&str>::try_from(&value)
972 }
973}
974
975impl std::str::FromStr for DebugProbeSelector {
976 type Err = DebugProbeSelectorParseError;
977 fn from_str(s: &str) -> Result<Self, Self::Err> {
978 Self::try_from(s)
979 }
980}
981
982impl From<DebugProbeInfo> for DebugProbeSelector {
983 fn from(selector: DebugProbeInfo) -> Self {
984 DebugProbeSelector {
985 vendor_id: selector.vendor_id,
986 product_id: selector.product_id,
987 serial_number: selector.serial_number,
988 }
989 }
990}
991
992impl From<&DebugProbeInfo> for DebugProbeSelector {
993 fn from(selector: &DebugProbeInfo) -> Self {
994 DebugProbeSelector {
995 vendor_id: selector.vendor_id,
996 product_id: selector.product_id,
997 serial_number: selector.serial_number.clone(),
998 }
999 }
1000}
1001
1002impl From<&DebugProbeSelector> for DebugProbeSelector {
1003 fn from(selector: &DebugProbeSelector) -> Self {
1004 selector.clone()
1005 }
1006}
1007
1008impl fmt::Display for DebugProbeSelector {
1009 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1010 write!(f, "{:04x}:{:04x}", self.vendor_id, self.product_id)?;
1011 if let Some(ref sn) = self.serial_number {
1012 write!(f, ":{sn}")?;
1013 }
1014 Ok(())
1015 }
1016}
1017
1018impl From<DebugProbeSelector> for String {
1019 fn from(value: DebugProbeSelector) -> String {
1020 value.to_string()
1021 }
1022}
1023
1024impl Serialize for DebugProbeSelector {
1025 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1026 where
1027 S: Serializer,
1028 {
1029 serializer.serialize_str(&self.to_string())
1030 }
1031}
1032
1033impl<'a> Deserialize<'a> for DebugProbeSelector {
1034 fn deserialize<D>(deserializer: D) -> Result<DebugProbeSelector, D::Error>
1035 where
1036 D: Deserializer<'a>,
1037 {
1038 let s = String::deserialize(deserializer)?;
1039 s.parse().map_err(serde::de::Error::custom)
1040 }
1041}
1042
1043pub(crate) trait RawSwdIo: DebugProbe {
1059 fn swd_io<S>(&mut self, swdio: S) -> Result<Vec<bool>, DebugProbeError>
1060 where
1061 S: IntoIterator<Item = IoSequenceItem>;
1062
1063 fn swj_pins(
1064 &mut self,
1065 pin_out: u32,
1066 pin_select: u32,
1067 pin_wait: u32,
1068 ) -> Result<u32, DebugProbeError>;
1069
1070 fn swd_settings(&self) -> &SwdSettings;
1071
1072 fn probe_statistics(&mut self) -> &mut ProbeStatistics;
1073}
1074
1075pub(crate) trait RawJtagIo: DebugProbe {
1077 fn state_mut(&mut self) -> &mut JtagDriverState;
1079
1080 fn state(&self) -> &JtagDriverState;
1082
1083 fn shift_bits(
1085 &mut self,
1086 tms: impl IntoIterator<Item = bool>,
1087 tdi: impl IntoIterator<Item = bool>,
1088 cap: impl IntoIterator<Item = bool>,
1089 ) -> Result<(), DebugProbeError> {
1090 for ((tms, tdi), cap) in tms.into_iter().zip(tdi.into_iter()).zip(cap.into_iter()) {
1091 self.shift_bit(tms, tdi, cap)?;
1092 }
1093
1094 Ok(())
1095 }
1096
1097 fn shift_bit(&mut self, tms: bool, tdi: bool, capture: bool) -> Result<(), DebugProbeError>;
1102
1103 fn read_captured_bits(&mut self) -> Result<BitVec, DebugProbeError>;
1105
1106 fn reset_jtag_state_machine(&mut self) -> Result<(), DebugProbeError> {
1108 tracing::debug!("Resetting JTAG chain by setting tms high for 5 bits");
1109
1110 let tms = [true, true, true, true, true, false];
1112 let tdi = std::iter::repeat(true);
1113
1114 self.shift_bits(tms, tdi, std::iter::repeat(false))?;
1115 let response = self.read_captured_bits()?;
1116
1117 tracing::debug!("Response to reset: {response}");
1118
1119 Ok(())
1120 }
1121}
1122
1123#[derive(Debug, Clone, Copy, PartialEq)]
1124pub(crate) enum IoSequenceItem {
1125 Output(bool),
1126 Input,
1127}
1128
1129#[derive(Debug)]
1130pub(crate) struct SwdSettings {
1131 pub num_idle_cycles_between_writes: usize,
1137
1138 pub num_retries_after_wait: usize,
1141
1142 pub max_retry_idle_cycles_after_wait: usize,
1146
1147 pub idle_cycles_before_write_verify: usize,
1161
1162 pub idle_cycles_after_transfer: usize,
1167}
1168
1169impl Default for SwdSettings {
1170 fn default() -> Self {
1171 Self {
1172 num_idle_cycles_between_writes: 2,
1173 num_retries_after_wait: 1000,
1174 max_retry_idle_cycles_after_wait: 128,
1175 idle_cycles_before_write_verify: 8,
1176 idle_cycles_after_transfer: 8,
1177 }
1178 }
1179}
1180
1181#[derive(Debug)]
1186pub(crate) struct JtagDriverState {
1187 pub state: JtagState,
1188 pub expected_scan_chain: Option<Vec<ScanChainElement>>,
1189 pub scan_chain: Vec<ScanChainElement>,
1190 pub chain_params: ChainParams,
1191 pub jtag_idle_cycles: usize,
1194}
1195impl JtagDriverState {
1196 fn max_ir_address(&self) -> u32 {
1197 (1 << self.chain_params.irlen) - 1
1198 }
1199}
1200
1201impl Default for JtagDriverState {
1202 fn default() -> Self {
1203 Self {
1204 state: JtagState::Reset,
1205 expected_scan_chain: None,
1206 scan_chain: Vec::new(),
1207 chain_params: ChainParams::default(),
1208 jtag_idle_cycles: 0,
1209 }
1210 }
1211}
1212
1213#[derive(Default, Debug)]
1214pub(crate) struct ProbeStatistics {
1215 num_transfers: usize,
1224
1225 num_extra_transfers: usize,
1228
1229 num_io_calls: usize,
1235
1236 num_wait_resp: usize,
1238
1239 num_faults: usize,
1241}
1242
1243impl ProbeStatistics {
1244 pub fn record_extra_transfer(&mut self) {
1245 self.num_extra_transfers += 1;
1246 }
1247
1248 pub fn record_transfers(&mut self, num_transfers: usize) {
1249 self.num_transfers += num_transfers;
1250 }
1251
1252 pub fn report_io(&mut self) {
1253 self.num_io_calls += 1;
1254 }
1255
1256 pub fn report_swd_response<T>(&mut self, response: &Result<T, DapError>) {
1257 match response {
1258 Err(DapError::FaultResponse) => self.num_faults += 1,
1259 Err(DapError::WaitResponse) => self.num_wait_resp += 1,
1260 _ => (),
1262 }
1263 }
1264}
1265
1266pub(crate) trait AutoImplementJtagAccess: RawJtagIo + 'static {}
1271
1272pub trait JtagAccess: DebugProbe {
1277 fn set_scan_chain(&mut self, scan_chain: &[ScanChainElement]) -> Result<(), DebugProbeError>;
1292
1293 fn scan_chain(&mut self) -> Result<&[ScanChainElement], DebugProbeError>;
1300
1301 fn shift_raw_sequence(&mut self, sequence: JtagSequence) -> Result<BitVec, DebugProbeError>;
1303
1304 fn tap_reset(&mut self) -> Result<(), DebugProbeError>;
1306
1307 fn set_idle_cycles(&mut self, idle_cycles: u8) -> Result<(), DebugProbeError>;
1312
1313 fn idle_cycles(&self) -> u8;
1315
1316 fn select_target(&mut self, index: usize) -> Result<(), DebugProbeError> {
1321 if index != 0 {
1322 return Err(DebugProbeError::NotImplemented {
1323 function_name: "select_jtag_tap",
1324 });
1325 }
1326
1327 Ok(())
1328 }
1329
1330 fn read_register(&mut self, address: u32, len: u32) -> Result<BitVec, DebugProbeError> {
1334 let data = vec![0u8; len.div_ceil(8) as usize];
1335
1336 self.write_register(address, &data, len)
1337 }
1338
1339 fn write_register(
1345 &mut self,
1346 address: u32,
1347 data: &[u8],
1348 len: u32,
1349 ) -> Result<BitVec, DebugProbeError>;
1350
1351 fn write_dr(&mut self, data: &[u8], len: u32) -> Result<BitVec, DebugProbeError>;
1355
1356 fn write_register_batch(
1358 &mut self,
1359 writes: &CommandQueue<JtagCommand>,
1360 ) -> Result<DeferredResultSet<CommandResult>, BatchExecutionError> {
1361 tracing::debug!(
1362 "Using default `JtagAccess::write_register_batch` hurts performance. Please implement proper batching for this probe."
1363 );
1364 let mut results = DeferredResultSet::new();
1365
1366 for (idx, write) in writes.iter() {
1367 match write {
1368 JtagCommand::WriteRegister(write) => {
1369 match self
1370 .write_register(write.address, &write.data, write.len)
1371 .map_err(crate::Error::Probe)
1372 .and_then(|response| (write.transform)(write, &response))
1373 {
1374 Ok(res) => results.push(idx, res),
1375 Err(e) => return Err(BatchExecutionError::new(e, results)),
1376 }
1377 }
1378
1379 JtagCommand::ShiftDr(write) => {
1380 match self
1381 .write_dr(&write.data, write.len)
1382 .map_err(crate::Error::Probe)
1383 .and_then(|response| (write.transform)(write, &response))
1384 {
1385 Ok(res) => results.push(idx, res),
1386 Err(e) => return Err(BatchExecutionError::new(e, results)),
1387 }
1388 }
1389 }
1390 }
1391
1392 Ok(results)
1393 }
1394}
1395
1396pub struct JtagSequence {
1398 pub tdo_capture: bool,
1400
1401 pub tms: bool,
1403
1404 pub data: BitVec,
1406}
1407
1408#[derive(Debug, Clone)]
1410pub struct JtagWriteCommand {
1411 pub address: u32,
1413
1414 pub data: Vec<u8>,
1416
1417 pub len: u32,
1419
1420 pub transform: fn(&JtagWriteCommand, &BitSlice) -> Result<CommandResult, crate::Error>,
1422}
1423
1424#[derive(Debug, Clone)]
1426pub struct ShiftDrCommand {
1427 pub data: Vec<u8>,
1429
1430 pub len: u32,
1432
1433 pub transform: fn(&ShiftDrCommand, &BitSlice) -> Result<CommandResult, crate::Error>,
1435}
1436
1437#[derive(Debug, Clone)]
1439pub enum JtagCommand {
1440 WriteRegister(JtagWriteCommand),
1442 ShiftDr(ShiftDrCommand),
1444}
1445
1446impl From<JtagWriteCommand> for JtagCommand {
1447 fn from(cmd: JtagWriteCommand) -> Self {
1448 JtagCommand::WriteRegister(cmd)
1449 }
1450}
1451
1452impl From<ShiftDrCommand> for JtagCommand {
1453 fn from(cmd: ShiftDrCommand) -> Self {
1454 JtagCommand::ShiftDr(cmd)
1455 }
1456}
1457
1458#[derive(Clone, Copy, Debug, Default)]
1460pub(crate) struct ChainParams {
1461 pub irpre: usize,
1462 pub irpost: usize,
1463 pub drpre: usize,
1464 pub drpost: usize,
1465 pub irlen: usize,
1466}
1467
1468impl ChainParams {
1469 fn from_jtag_chain(chain: &[ScanChainElement], selected: usize) -> Option<Self> {
1470 let mut params = Self::default();
1471
1472 let mut found = false;
1473 for (index, tap) in chain.iter().enumerate() {
1474 let ir_len = tap.ir_len() as usize;
1475 if index == selected {
1476 params.irlen = ir_len;
1477 found = true;
1478 } else if found {
1479 params.irpost += ir_len;
1480 params.drpost += 1;
1481 } else {
1482 params.irpre += ir_len;
1483 params.drpre += 1;
1484 }
1485 }
1486
1487 found.then_some(params)
1488 }
1489}
1490
1491#[derive(thiserror::Error, Debug)]
1493pub struct BatchExecutionError {
1494 #[source]
1496 pub error: crate::Error,
1497
1498 pub results: DeferredResultSet<CommandResult>,
1500}
1501
1502impl BatchExecutionError {
1503 pub(crate) fn new(
1504 error: crate::Error,
1505 results: DeferredResultSet<CommandResult>,
1506 ) -> BatchExecutionError {
1507 BatchExecutionError { error, results }
1508 }
1509}
1510
1511impl std::fmt::Display for BatchExecutionError {
1512 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1513 write!(
1514 f,
1515 "Error cause was {}. Successful command count {}",
1516 self.error,
1517 self.results.len()
1518 )
1519 }
1520}
1521
1522#[derive(Debug, Clone)]
1524pub enum CommandResult {
1525 None,
1527
1528 U8(u8),
1530
1531 U16(u16),
1533
1534 U32(u32),
1536
1537 VecU8(Vec<u8>),
1539}
1540
1541impl CommandResult {
1542 pub fn into_u32(self) -> u32 {
1548 match self {
1549 CommandResult::U32(val) => val,
1550 _ => panic!("CommandResult is not a u32"),
1551 }
1552 }
1553
1554 pub fn into_u8(self) -> u8 {
1560 match self {
1561 CommandResult::U8(val) => val,
1562 _ => panic!("CommandResult is not a u8"),
1563 }
1564 }
1565}
1566
1567pub struct CommandQueue<T> {
1572 commands: Vec<(DeferredResultIndex, T)>,
1573}
1574
1575impl<T: std::fmt::Debug> std::fmt::Debug for CommandQueue<T> {
1576 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1577 f.debug_struct("CommandQueue")
1578 .field("commands", &self.commands)
1579 .finish()
1580 }
1581}
1582
1583impl<T> Default for CommandQueue<T> {
1584 fn default() -> Self {
1585 Self {
1586 commands: Vec::new(),
1587 }
1588 }
1589}
1590
1591impl<T> CommandQueue<T> {
1592 pub fn new() -> Self {
1594 Self::default()
1595 }
1596
1597 pub fn schedule(&mut self, command: impl Into<T>) -> DeferredResultIndex {
1601 let index = DeferredResultIndex::new();
1602 self.commands.push((index.clone(), command.into()));
1603 index
1604 }
1605
1606 pub fn len(&self) -> usize {
1608 self.commands.len()
1609 }
1610
1611 pub fn is_empty(&self) -> bool {
1613 self.commands.is_empty()
1614 }
1615
1616 pub(crate) fn iter(&self) -> impl Iterator<Item = &(DeferredResultIndex, T)> {
1617 self.commands.iter()
1618 }
1619
1620 pub(crate) fn consume(&mut self, len: usize) {
1622 self.commands.drain(..len);
1623 }
1624}
1625
1626pub struct DeferredResultSet<T>(HashMap<DeferredResultIndex, T>);
1628
1629impl<T: std::fmt::Debug> std::fmt::Debug for DeferredResultSet<T> {
1630 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1631 f.debug_tuple("DeferredResultSet").field(&self.0).finish()
1632 }
1633}
1634
1635impl<T> Default for DeferredResultSet<T> {
1636 fn default() -> Self {
1637 Self(HashMap::default())
1638 }
1639}
1640
1641impl<T> DeferredResultSet<T> {
1642 pub fn new() -> Self {
1644 Self::default()
1645 }
1646
1647 pub fn with_capacity(capacity: usize) -> Self {
1649 Self(HashMap::with_capacity(capacity))
1650 }
1651
1652 pub(crate) fn push(&mut self, idx: &DeferredResultIndex, result: T) {
1653 self.0.insert(idx.clone(), result);
1654 }
1655
1656 pub fn len(&self) -> usize {
1658 self.0.len()
1659 }
1660
1661 pub fn is_empty(&self) -> bool {
1663 self.0.is_empty()
1664 }
1665
1666 pub(crate) fn merge_from(&mut self, other: DeferredResultSet<T>) {
1667 self.0.extend(other.0);
1668 self.0.retain(|k, _| k.should_capture());
1669 }
1670
1671 pub fn take(&mut self, index: DeferredResultIndex) -> Result<T, DeferredResultIndex> {
1673 self.0.remove(&index).ok_or(index)
1674 }
1675}
1676
1677#[derive(Eq)]
1681pub struct DeferredResultIndex(Arc<()>);
1682
1683impl PartialEq for DeferredResultIndex {
1684 fn eq(&self, other: &Self) -> bool {
1685 Arc::ptr_eq(&self.0, &other.0)
1686 }
1687}
1688
1689impl fmt::Debug for DeferredResultIndex {
1690 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1691 f.debug_tuple("DeferredResultIndex")
1692 .field(&self.id())
1693 .finish()
1694 }
1695}
1696
1697impl DeferredResultIndex {
1698 fn new() -> Self {
1700 Self(Arc::new(()))
1701 }
1702
1703 fn id(&self) -> usize {
1704 Arc::as_ptr(&self.0) as usize
1705 }
1706
1707 pub(crate) fn should_capture(&self) -> bool {
1708 Arc::strong_count(&self.0) > 1
1712 }
1713
1714 fn clone(&self) -> Self {
1716 Self(self.0.clone())
1717 }
1718}
1719
1720impl std::hash::Hash for DeferredResultIndex {
1721 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1722 self.id().hash(state)
1723 }
1724}
1725
1726#[derive(PartialEq, Eq, Debug, Copy, Clone, Default, Serialize, Deserialize)]
1728pub enum AttachMethod {
1729 #[default]
1731 Normal,
1732 UnderReset,
1736}
1737
1738#[cfg(test)]
1739mod test {
1740 use super::*;
1741
1742 #[test]
1743 fn test_is_probe_factory() {
1744 let probe_info = DebugProbeInfo::new(
1745 "Mock probe",
1746 0x12,
1747 0x23,
1748 Some("mock_serial".to_owned()),
1749 &ftdi::FtdiProbeFactory,
1750 None,
1751 );
1752
1753 assert!(probe_info.is_probe_type::<ftdi::FtdiProbeFactory>());
1754 assert!(!probe_info.is_probe_type::<espusbjtag::EspUsbJtagFactory>());
1755 }
1756
1757 #[test]
1758 fn test_parsing_many_colons() {
1759 let selector: DebugProbeSelector = "303a:1001:DC:DA:0C:D3:FE:D8".try_into().unwrap();
1760
1761 assert_eq!(selector.vendor_id, 0x303a);
1762 assert_eq!(selector.product_id, 0x1001);
1763 assert_eq!(
1764 selector.serial_number,
1765 Some("DC:DA:0C:D3:FE:D8".to_string())
1766 );
1767 }
1768
1769 #[test]
1770 fn missing_serial_is_none() {
1771 let selector: DebugProbeSelector = "303a:1001".try_into().unwrap();
1772
1773 assert_eq!(selector.vendor_id, 0x303a);
1774 assert_eq!(selector.product_id, 0x1001);
1775 assert_eq!(selector.serial_number, None);
1776
1777 let matches = selector.match_probe_selector(0x303a, 0x1001, None);
1778 let matches_with_serial = selector.match_probe_selector(0x303a, 0x1001, Some("serial"));
1779 assert!(matches);
1780 assert!(matches_with_serial);
1781 }
1782
1783 #[test]
1784 fn empty_serial_is_some() {
1785 let selector: DebugProbeSelector = "303a:1001:".try_into().unwrap();
1786
1787 assert_eq!(selector.vendor_id, 0x303a);
1788 assert_eq!(selector.product_id, 0x1001);
1789 assert_eq!(selector.serial_number, Some(String::new()));
1790
1791 let matches = selector.match_probe_selector(0x303a, 0x1001, None);
1792 let matches_with_serial = selector.match_probe_selector(0x303a, 0x1001, Some("serial"));
1793 assert!(matches);
1794 assert!(!matches_with_serial);
1795 }
1796}