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 pub interface: Option<u8>,
809
810 pub is_hid_interface: bool,
812
813 probe_factory: &'static dyn ProbeFactory,
815}
816
817impl std::fmt::Display for DebugProbeInfo {
818 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
819 write!(
820 f,
821 "{} -- {:04x}:{:04x}",
822 self.identifier, self.vendor_id, self.product_id,
823 )?;
824
825 if let Some(interface) = self.interface {
826 write!(f, "-{}", interface)?;
827 }
828
829 write!(
830 f,
831 ":{} ({})",
832 self.serial_number.as_deref().unwrap_or(""),
833 self.probe_factory
834 )
835 }
836}
837
838impl DebugProbeInfo {
839 pub fn new<S: Into<String>>(
841 identifier: S,
842 vendor_id: u16,
843 product_id: u16,
844 serial_number: Option<String>,
845 probe_factory: &'static dyn ProbeFactory,
846 interface: Option<u8>,
847 is_hid_interface: bool,
848 ) -> Self {
849 Self {
850 identifier: identifier.into(),
851 vendor_id,
852 product_id,
853 serial_number,
854 probe_factory,
855 interface,
856 is_hid_interface,
857 }
858 }
859
860 pub fn open(&self) -> Result<Probe, DebugProbeError> {
862 let selector = DebugProbeSelector::from(self);
863 self.probe_factory
864 .open(&selector)
865 .map(Probe::from_specific_probe)
866 }
867
868 pub fn is_probe_type<F: ProbeFactory>(&self) -> bool {
870 self.probe_factory.type_id() == std::any::TypeId::of::<F>()
871 }
872
873 pub fn probe_type(&self) -> String {
877 self.probe_factory.to_string()
878 }
879}
880
881#[derive(thiserror::Error, Debug, docsplay::Display)]
883pub enum DebugProbeSelectorParseError {
884 ParseInt(#[from] std::num::ParseIntError),
886
887 Format,
889}
890
891#[derive(Debug, Clone, PartialEq, Eq, Hash)]
911pub struct DebugProbeSelector {
912 pub vendor_id: u16,
914 pub product_id: u16,
916 pub interface: Option<u8>,
918 pub serial_number: Option<String>,
920}
921
922impl DebugProbeSelector {
923 pub(crate) fn matches(&self, info: &DeviceInfo) -> bool {
924 if self.interface.is_some() {
925 info.interfaces().any(|iface| {
926 self.match_probe_selector(
927 info.vendor_id(),
928 info.product_id(),
929 Some(iface.interface_number()),
930 info.serial_number(),
931 )
932 })
933 } else {
934 self.match_probe_selector(
935 info.vendor_id(),
936 info.product_id(),
937 None,
938 info.serial_number(),
939 )
940 }
941 }
942
943 pub fn matches_probe(&self, info: &DebugProbeInfo) -> bool {
945 self.match_probe_selector(
946 info.vendor_id,
947 info.product_id,
948 info.interface,
949 info.serial_number.as_deref(),
950 )
951 }
952
953 fn match_probe_selector(
954 &self,
955 vendor_id: u16,
956 product_id: u16,
957 interface: Option<u8>,
958 serial_number: Option<&str>,
959 ) -> bool {
960 tracing::trace!(
961 "Matching probe selector:\nVendor ID: {vendor_id:04x} == {:04x}\nProduct ID: {product_id:04x} = {:04x}\nInterface: {interface:?} == {:?}\nSerial Number: {serial_number:?} == {:?}",
962 self.vendor_id,
963 self.product_id,
964 self.interface,
965 self.serial_number
966 );
967
968 vendor_id == self.vendor_id
969 && product_id == self.product_id
970 && self
971 .interface
972 .map(|iface| interface == Some(iface))
973 .unwrap_or(true) && self
975 .serial_number
976 .as_ref()
977 .map(|s| {
978 if let Some(serial_number) = serial_number {
979 serial_number == s
980 } else {
981 s.is_empty()
984 }
985 })
986 .unwrap_or(true)
987 }
988}
989
990impl TryFrom<&str> for DebugProbeSelector {
991 type Error = DebugProbeSelectorParseError;
992 fn try_from(value: &str) -> Result<Self, Self::Error> {
993 let mut split = value.splitn(3, ':');
997
998 let vendor_id = split.next().unwrap(); let mut product_id = split.next().ok_or(DebugProbeSelectorParseError::Format)?;
1000 let interface = if let Some((id, iface)) = product_id.split_once("-") {
1001 product_id = id;
1002 if iface.is_empty() {
1004 Ok(None)
1005 } else {
1006 iface.parse::<u8>().map(Some)
1007 }
1008 } else {
1009 Ok(None)
1010 }?;
1011 let serial_number = split.next().map(|s| s.to_string());
1012
1013 Ok(DebugProbeSelector {
1014 vendor_id: u16::from_str_radix(vendor_id, 16)?,
1015 product_id: u16::from_str_radix(product_id, 16)?,
1016 serial_number,
1017 interface,
1018 })
1019 }
1020}
1021
1022impl TryFrom<String> for DebugProbeSelector {
1023 type Error = DebugProbeSelectorParseError;
1024 fn try_from(value: String) -> Result<Self, Self::Error> {
1025 TryFrom::<&str>::try_from(&value)
1026 }
1027}
1028
1029impl std::str::FromStr for DebugProbeSelector {
1030 type Err = DebugProbeSelectorParseError;
1031 fn from_str(s: &str) -> Result<Self, Self::Err> {
1032 Self::try_from(s)
1033 }
1034}
1035
1036impl From<DebugProbeInfo> for DebugProbeSelector {
1037 fn from(selector: DebugProbeInfo) -> Self {
1038 DebugProbeSelector {
1039 vendor_id: selector.vendor_id,
1040 product_id: selector.product_id,
1041 serial_number: selector.serial_number,
1042 interface: selector.interface,
1043 }
1044 }
1045}
1046
1047impl From<&DebugProbeInfo> for DebugProbeSelector {
1048 fn from(selector: &DebugProbeInfo) -> Self {
1049 DebugProbeSelector {
1050 vendor_id: selector.vendor_id,
1051 product_id: selector.product_id,
1052 serial_number: selector.serial_number.clone(),
1053 interface: selector.interface,
1054 }
1055 }
1056}
1057
1058impl From<&DebugProbeSelector> for DebugProbeSelector {
1059 fn from(selector: &DebugProbeSelector) -> Self {
1060 selector.clone()
1061 }
1062}
1063
1064impl fmt::Display for DebugProbeSelector {
1065 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1066 write!(f, "{:04x}:{:04x}", self.vendor_id, self.product_id)?;
1067 if let Some(ref sn) = self.serial_number {
1068 write!(f, ":{sn}")?;
1069 }
1070 Ok(())
1071 }
1072}
1073
1074impl From<DebugProbeSelector> for String {
1075 fn from(value: DebugProbeSelector) -> String {
1076 value.to_string()
1077 }
1078}
1079
1080impl Serialize for DebugProbeSelector {
1081 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1082 where
1083 S: Serializer,
1084 {
1085 serializer.serialize_str(&self.to_string())
1086 }
1087}
1088
1089impl<'a> Deserialize<'a> for DebugProbeSelector {
1090 fn deserialize<D>(deserializer: D) -> Result<DebugProbeSelector, D::Error>
1091 where
1092 D: Deserializer<'a>,
1093 {
1094 let s = String::deserialize(deserializer)?;
1095 s.parse().map_err(serde::de::Error::custom)
1096 }
1097}
1098
1099pub(crate) trait RawSwdIo: DebugProbe {
1115 fn swd_io<S>(&mut self, swdio: S) -> Result<Vec<bool>, DebugProbeError>
1116 where
1117 S: IntoIterator<Item = IoSequenceItem>;
1118
1119 fn swj_pins(
1120 &mut self,
1121 pin_out: u32,
1122 pin_select: u32,
1123 pin_wait: u32,
1124 ) -> Result<u32, DebugProbeError>;
1125
1126 fn swd_settings(&self) -> &SwdSettings;
1127
1128 fn probe_statistics(&mut self) -> &mut ProbeStatistics;
1129}
1130
1131pub(crate) trait RawJtagIo: DebugProbe {
1133 fn state_mut(&mut self) -> &mut JtagDriverState;
1135
1136 fn state(&self) -> &JtagDriverState;
1138
1139 fn shift_bits(
1141 &mut self,
1142 tms: impl IntoIterator<Item = bool>,
1143 tdi: impl IntoIterator<Item = bool>,
1144 cap: impl IntoIterator<Item = bool>,
1145 ) -> Result<(), DebugProbeError> {
1146 for ((tms, tdi), cap) in tms.into_iter().zip(tdi.into_iter()).zip(cap.into_iter()) {
1147 self.shift_bit(tms, tdi, cap)?;
1148 }
1149
1150 Ok(())
1151 }
1152
1153 fn shift_bit(&mut self, tms: bool, tdi: bool, capture: bool) -> Result<(), DebugProbeError>;
1158
1159 fn read_captured_bits(&mut self) -> Result<BitVec, DebugProbeError>;
1161
1162 fn reset_jtag_state_machine(&mut self) -> Result<(), DebugProbeError> {
1164 tracing::debug!("Resetting JTAG chain by setting tms high for 5 bits");
1165
1166 let tms = [true, true, true, true, true, false];
1168 let tdi = std::iter::repeat(true);
1169
1170 self.shift_bits(tms, tdi, std::iter::repeat(false))?;
1171 let response = self.read_captured_bits()?;
1172
1173 tracing::debug!("Response to reset: {response}");
1174
1175 Ok(())
1176 }
1177}
1178
1179#[derive(Debug, Clone, Copy, PartialEq)]
1180pub(crate) enum IoSequenceItem {
1181 Output(bool),
1182 Input,
1183}
1184
1185#[derive(Debug)]
1186pub(crate) struct SwdSettings {
1187 pub num_idle_cycles_between_writes: usize,
1193
1194 pub num_retries_after_wait: usize,
1197
1198 pub max_retry_idle_cycles_after_wait: usize,
1202
1203 pub idle_cycles_before_write_verify: usize,
1217
1218 pub idle_cycles_after_transfer: usize,
1223}
1224
1225impl Default for SwdSettings {
1226 fn default() -> Self {
1227 Self {
1228 num_idle_cycles_between_writes: 2,
1229 num_retries_after_wait: 1000,
1230 max_retry_idle_cycles_after_wait: 128,
1231 idle_cycles_before_write_verify: 8,
1232 idle_cycles_after_transfer: 8,
1233 }
1234 }
1235}
1236
1237#[derive(Debug)]
1242pub(crate) struct JtagDriverState {
1243 pub state: JtagState,
1244 pub expected_scan_chain: Option<Vec<ScanChainElement>>,
1245 pub scan_chain: Vec<ScanChainElement>,
1246 pub chain_params: ChainParams,
1247 pub jtag_idle_cycles: usize,
1250}
1251impl JtagDriverState {
1252 fn max_ir_address(&self) -> u32 {
1253 (1 << self.chain_params.irlen) - 1
1254 }
1255}
1256
1257impl Default for JtagDriverState {
1258 fn default() -> Self {
1259 Self {
1260 state: JtagState::Reset,
1261 expected_scan_chain: None,
1262 scan_chain: Vec::new(),
1263 chain_params: ChainParams::default(),
1264 jtag_idle_cycles: 0,
1265 }
1266 }
1267}
1268
1269#[derive(Default, Debug)]
1270pub(crate) struct ProbeStatistics {
1271 num_transfers: usize,
1280
1281 num_extra_transfers: usize,
1284
1285 num_io_calls: usize,
1291
1292 num_wait_resp: usize,
1294
1295 num_faults: usize,
1297}
1298
1299impl ProbeStatistics {
1300 pub fn record_extra_transfer(&mut self) {
1301 self.num_extra_transfers += 1;
1302 }
1303
1304 pub fn record_transfers(&mut self, num_transfers: usize) {
1305 self.num_transfers += num_transfers;
1306 }
1307
1308 pub fn report_io(&mut self) {
1309 self.num_io_calls += 1;
1310 }
1311
1312 pub fn report_swd_response<T>(&mut self, response: &Result<T, DapError>) {
1313 match response {
1314 Err(DapError::FaultResponse) => self.num_faults += 1,
1315 Err(DapError::WaitResponse) => self.num_wait_resp += 1,
1316 _ => (),
1318 }
1319 }
1320}
1321
1322pub(crate) trait AutoImplementJtagAccess: RawJtagIo + 'static {}
1327
1328pub trait JtagAccess: DebugProbe {
1333 fn set_scan_chain(&mut self, scan_chain: &[ScanChainElement]) -> Result<(), DebugProbeError>;
1348
1349 fn scan_chain(&mut self) -> Result<&[ScanChainElement], DebugProbeError>;
1356
1357 fn shift_raw_sequence(&mut self, sequence: JtagSequence) -> Result<BitVec, DebugProbeError>;
1359
1360 fn tap_reset(&mut self) -> Result<(), DebugProbeError>;
1362
1363 fn set_idle_cycles(&mut self, idle_cycles: u8) -> Result<(), DebugProbeError>;
1368
1369 fn idle_cycles(&self) -> u8;
1371
1372 fn select_target(&mut self, index: usize) -> Result<(), DebugProbeError> {
1377 if index != 0 {
1378 return Err(DebugProbeError::NotImplemented {
1379 function_name: "select_jtag_tap",
1380 });
1381 }
1382
1383 Ok(())
1384 }
1385
1386 fn read_register(&mut self, address: u32, len: u32) -> Result<BitVec, DebugProbeError> {
1390 let data = vec![0u8; len.div_ceil(8) as usize];
1391
1392 self.write_register(address, &data, len)
1393 }
1394
1395 fn write_register(
1401 &mut self,
1402 address: u32,
1403 data: &[u8],
1404 len: u32,
1405 ) -> Result<BitVec, DebugProbeError>;
1406
1407 fn write_dr(&mut self, data: &[u8], len: u32) -> Result<BitVec, DebugProbeError>;
1411
1412 fn write_register_batch(
1414 &mut self,
1415 writes: &CommandQueue<JtagCommand>,
1416 ) -> Result<DeferredResultSet<CommandResult>, BatchExecutionError> {
1417 tracing::debug!(
1418 "Using default `JtagAccess::write_register_batch` hurts performance. Please implement proper batching for this probe."
1419 );
1420 let mut results = DeferredResultSet::new();
1421
1422 for (idx, write) in writes.iter() {
1423 match write {
1424 JtagCommand::WriteRegister(write) => {
1425 match self
1426 .write_register(write.address, &write.data, write.len)
1427 .map_err(crate::Error::Probe)
1428 .and_then(|response| (write.transform)(write, &response))
1429 {
1430 Ok(res) => results.push(idx, res),
1431 Err(e) => return Err(BatchExecutionError::new(e, results)),
1432 }
1433 }
1434
1435 JtagCommand::ShiftDr(write) => {
1436 match self
1437 .write_dr(&write.data, write.len)
1438 .map_err(crate::Error::Probe)
1439 .and_then(|response| (write.transform)(write, &response))
1440 {
1441 Ok(res) => results.push(idx, res),
1442 Err(e) => return Err(BatchExecutionError::new(e, results)),
1443 }
1444 }
1445 }
1446 }
1447
1448 Ok(results)
1449 }
1450}
1451
1452pub struct JtagSequence {
1454 pub tdo_capture: bool,
1456
1457 pub tms: bool,
1459
1460 pub data: BitVec,
1462}
1463
1464#[derive(Debug, Clone)]
1466pub struct JtagWriteCommand {
1467 pub address: u32,
1469
1470 pub data: Vec<u8>,
1472
1473 pub len: u32,
1475
1476 pub transform: fn(&JtagWriteCommand, &BitSlice) -> Result<CommandResult, crate::Error>,
1478}
1479
1480#[derive(Debug, Clone)]
1482pub struct ShiftDrCommand {
1483 pub data: Vec<u8>,
1485
1486 pub len: u32,
1488
1489 pub transform: fn(&ShiftDrCommand, &BitSlice) -> Result<CommandResult, crate::Error>,
1491}
1492
1493#[derive(Debug, Clone)]
1495pub enum JtagCommand {
1496 WriteRegister(JtagWriteCommand),
1498 ShiftDr(ShiftDrCommand),
1500}
1501
1502impl From<JtagWriteCommand> for JtagCommand {
1503 fn from(cmd: JtagWriteCommand) -> Self {
1504 JtagCommand::WriteRegister(cmd)
1505 }
1506}
1507
1508impl From<ShiftDrCommand> for JtagCommand {
1509 fn from(cmd: ShiftDrCommand) -> Self {
1510 JtagCommand::ShiftDr(cmd)
1511 }
1512}
1513
1514#[derive(Clone, Copy, Debug, Default)]
1516pub(crate) struct ChainParams {
1517 pub index: usize,
1518 pub irpre: usize,
1519 pub irpost: usize,
1520 pub drpre: usize,
1521 pub drpost: usize,
1522 pub irlen: usize,
1523}
1524
1525impl ChainParams {
1526 fn from_jtag_chain(chain: &[ScanChainElement], selected: usize) -> Option<Self> {
1527 let mut params = Self {
1528 index: selected,
1529 ..Default::default()
1530 };
1531 let mut found = false;
1532 for (index, tap) in chain.iter().enumerate() {
1533 let ir_len = tap.ir_len() as usize;
1534 if index == selected {
1535 params.irlen = ir_len;
1536 found = true;
1537 } else if found {
1538 params.irpost += ir_len;
1539 params.drpost += 1;
1540 } else {
1541 params.irpre += ir_len;
1542 params.drpre += 1;
1543 }
1544 }
1545
1546 found.then_some(params)
1547 }
1548}
1549
1550#[derive(thiserror::Error, Debug)]
1552pub struct BatchExecutionError {
1553 #[source]
1555 pub error: crate::Error,
1556
1557 pub results: DeferredResultSet<CommandResult>,
1559}
1560
1561impl BatchExecutionError {
1562 pub(crate) fn new(
1563 error: crate::Error,
1564 results: DeferredResultSet<CommandResult>,
1565 ) -> BatchExecutionError {
1566 BatchExecutionError { error, results }
1567 }
1568}
1569
1570impl std::fmt::Display for BatchExecutionError {
1571 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1572 write!(
1573 f,
1574 "Error cause was {}. Successful command count {}",
1575 self.error,
1576 self.results.len()
1577 )
1578 }
1579}
1580
1581#[derive(Debug, Clone)]
1583pub enum CommandResult {
1584 None,
1586
1587 U8(u8),
1589
1590 U16(u16),
1592
1593 U32(u32),
1595
1596 VecU8(Vec<u8>),
1598}
1599
1600impl CommandResult {
1601 pub fn into_u32(self) -> u32 {
1607 match self {
1608 CommandResult::U32(val) => val,
1609 _ => panic!("CommandResult is not a u32"),
1610 }
1611 }
1612
1613 pub fn into_u8(self) -> u8 {
1619 match self {
1620 CommandResult::U8(val) => val,
1621 _ => panic!("CommandResult is not a u8"),
1622 }
1623 }
1624}
1625
1626pub struct CommandQueue<T> {
1631 commands: Vec<(DeferredResultIndex, T)>,
1632 cursor: usize,
1633}
1634
1635impl<T: std::fmt::Debug> std::fmt::Debug for CommandQueue<T> {
1636 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1637 f.debug_struct("CommandQueue")
1638 .field("commands", &self.len())
1639 .finish()
1640 }
1641}
1642
1643impl<T> Default for CommandQueue<T> {
1644 fn default() -> Self {
1645 Self {
1646 commands: Vec::new(),
1647 cursor: 0,
1648 }
1649 }
1650}
1651
1652impl<T> CommandQueue<T> {
1653 pub fn new() -> Self {
1655 Self::default()
1656 }
1657
1658 pub fn schedule(&mut self, command: impl Into<T>) -> DeferredResultIndex {
1662 let index = DeferredResultIndex::new();
1663 self.commands.push((index.clone(), command.into()));
1664 index
1665 }
1666
1667 pub fn len(&self) -> usize {
1669 self.commands[self.cursor..].len()
1670 }
1671
1672 pub fn is_empty(&self) -> bool {
1674 self.len() == 0
1675 }
1676
1677 pub(crate) fn iter(&self) -> impl Iterator<Item = &(DeferredResultIndex, T)> {
1678 self.commands[self.cursor..].iter()
1679 }
1680
1681 pub(crate) fn rewind(&mut self, by: usize) -> bool {
1685 if self.cursor >= by {
1686 self.cursor -= by;
1687 true
1688 } else {
1689 false
1690 }
1691 }
1692
1693 pub(crate) fn consume(&mut self, len: usize) {
1695 debug_assert!(self.len() >= len);
1696 self.cursor += len;
1697 }
1698}
1699
1700pub struct DeferredResultSet<T>(HashMap<DeferredResultIndex, T>);
1702
1703impl<T: std::fmt::Debug> std::fmt::Debug for DeferredResultSet<T> {
1704 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1705 f.debug_tuple("DeferredResultSet").field(&self.0).finish()
1706 }
1707}
1708
1709impl<T> Default for DeferredResultSet<T> {
1710 fn default() -> Self {
1711 Self(HashMap::default())
1712 }
1713}
1714
1715impl<T> DeferredResultSet<T> {
1716 pub fn new() -> Self {
1718 Self::default()
1719 }
1720
1721 pub fn with_capacity(capacity: usize) -> Self {
1723 Self(HashMap::with_capacity(capacity))
1724 }
1725
1726 pub(crate) fn push(&mut self, idx: &DeferredResultIndex, result: T) {
1727 self.0.insert(idx.clone(), result);
1728 }
1729
1730 pub fn len(&self) -> usize {
1732 self.0.len()
1733 }
1734
1735 pub fn is_empty(&self) -> bool {
1737 self.0.is_empty()
1738 }
1739
1740 pub(crate) fn merge_from(&mut self, other: DeferredResultSet<T>) {
1741 self.0.extend(other.0);
1742 self.0.retain(|k, _| k.should_capture());
1743 }
1744
1745 pub fn take(&mut self, index: DeferredResultIndex) -> Result<T, DeferredResultIndex> {
1747 self.0.remove(&index).ok_or(index)
1748 }
1749}
1750
1751#[derive(Eq)]
1755pub struct DeferredResultIndex(Arc<()>);
1756
1757impl PartialEq for DeferredResultIndex {
1758 fn eq(&self, other: &Self) -> bool {
1759 Arc::ptr_eq(&self.0, &other.0)
1760 }
1761}
1762
1763impl fmt::Debug for DeferredResultIndex {
1764 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1765 f.debug_tuple("DeferredResultIndex")
1766 .field(&self.id())
1767 .finish()
1768 }
1769}
1770
1771impl DeferredResultIndex {
1772 fn new() -> Self {
1774 Self(Arc::new(()))
1775 }
1776
1777 fn id(&self) -> usize {
1778 Arc::as_ptr(&self.0) as usize
1779 }
1780
1781 pub(crate) fn should_capture(&self) -> bool {
1782 Arc::strong_count(&self.0) > 1
1786 }
1787
1788 fn clone(&self) -> Self {
1790 Self(self.0.clone())
1791 }
1792}
1793
1794impl std::hash::Hash for DeferredResultIndex {
1795 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1796 self.id().hash(state)
1797 }
1798}
1799
1800#[derive(PartialEq, Eq, Debug, Copy, Clone, Default, Serialize, Deserialize)]
1802pub enum AttachMethod {
1803 #[default]
1805 Normal,
1806 UnderReset,
1810}
1811
1812#[cfg(test)]
1813mod test {
1814 use super::*;
1815
1816 #[test]
1817 fn test_is_probe_factory() {
1818 let probe_info = DebugProbeInfo::new(
1819 "Mock probe",
1820 0x12,
1821 0x23,
1822 Some("mock_serial".to_owned()),
1823 &ftdi::FtdiProbeFactory,
1824 None,
1825 false,
1826 );
1827
1828 assert!(probe_info.is_probe_type::<ftdi::FtdiProbeFactory>());
1829 assert!(!probe_info.is_probe_type::<espusbjtag::EspUsbJtagFactory>());
1830 }
1831
1832 #[test]
1833 fn test_parsing_many_colons() {
1834 let selector: DebugProbeSelector = "303a:1001:DC:DA:0C:D3:FE:D8".try_into().unwrap();
1835
1836 assert_eq!(selector.vendor_id, 0x303a);
1837 assert_eq!(selector.product_id, 0x1001);
1838 assert_eq!(
1839 selector.serial_number,
1840 Some("DC:DA:0C:D3:FE:D8".to_string())
1841 );
1842 }
1843
1844 #[test]
1845 fn missing_serial_is_none() {
1846 let selector: DebugProbeSelector = "303a:1001".try_into().unwrap();
1847
1848 assert_eq!(selector.vendor_id, 0x303a);
1849 assert_eq!(selector.product_id, 0x1001);
1850 assert_eq!(selector.serial_number, None);
1851
1852 let matches = selector.match_probe_selector(0x303a, 0x1001, None, None);
1853 let matches_with_serial =
1854 selector.match_probe_selector(0x303a, 0x1001, None, Some("serial"));
1855 assert!(matches);
1856 assert!(matches_with_serial);
1857 }
1858
1859 #[test]
1860 fn empty_serial_is_some() {
1861 let selector: DebugProbeSelector = "303a:1001:".try_into().unwrap();
1862
1863 assert_eq!(selector.vendor_id, 0x303a);
1864 assert_eq!(selector.product_id, 0x1001);
1865 assert_eq!(selector.serial_number, Some(String::new()));
1866
1867 let matches = selector.match_probe_selector(0x303a, 0x1001, None, None);
1868 let matches_with_serial =
1869 selector.match_probe_selector(0x303a, 0x1001, None, Some("serial"));
1870 assert!(matches);
1871 assert!(!matches_with_serial);
1872 }
1873
1874 #[test]
1875 fn missing_interface_is_none() {
1876 let selector: DebugProbeSelector = "303a:1001".try_into().unwrap();
1877
1878 assert_eq!(selector.vendor_id, 0x303a);
1879 assert_eq!(selector.product_id, 0x1001);
1880 assert_eq!(selector.interface, None);
1881
1882 let matches = selector.match_probe_selector(0x303a, 0x1001, None, None);
1883 let matches_with_interface = selector.match_probe_selector(0x303a, 0x1001, Some(0), None);
1884 assert!(matches);
1885 assert!(matches_with_interface);
1886 }
1887
1888 #[test]
1889 fn empty_interface_is_none() {
1890 let selector: DebugProbeSelector = "303a:1001-".try_into().unwrap();
1891
1892 assert_eq!(selector.vendor_id, 0x303a);
1893 assert_eq!(selector.product_id, 0x1001);
1894 assert_eq!(selector.interface, None);
1895
1896 let matches = selector.match_probe_selector(0x303a, 0x1001, None, None);
1897 let matches_with_interface = selector.match_probe_selector(0x303a, 0x1001, Some(0), None);
1898 assert!(matches);
1899 assert!(matches_with_interface);
1900 }
1901
1902 #[test]
1903 fn set_interface_matches() {
1904 let selector: DebugProbeSelector = "303a:1001-0".try_into().unwrap();
1905
1906 assert_eq!(selector.vendor_id, 0x303a);
1907 assert_eq!(selector.product_id, 0x1001);
1908 assert_eq!(selector.interface, Some(0));
1909
1910 let no_match = selector.match_probe_selector(0x303a, 0x1001, None, None);
1911 let matches_with_interface = selector.match_probe_selector(0x303a, 0x1001, Some(0), None);
1912 let no_match_with_wrong_interface =
1913 selector.match_probe_selector(0x303a, 0x1001, Some(1), None);
1914 assert!(!no_match);
1915 assert!(matches_with_interface);
1916 assert!(!no_match_with_wrong_interface);
1917 }
1918}