1use crate::{
2 CoreStatus,
3 architecture::arm::{
4 ApAddress, ArmError, DapAccess, FullyQualifiedApAddress, RawDapAccess, RegisterAddress,
5 SwoAccess, SwoConfig, ap,
6 dp::{
7 Ctrl, DPIDR, DebugPortId, DebugPortVersion, DpAccess, DpAddress, DpRegisterAddress,
8 Select1, SelectV1, SelectV3,
9 },
10 memory::{ADIMemoryInterface, ArmMemoryInterface, Component},
11 sequences::ArmDebugSequence,
12 },
13 probe::{DebugProbe, DebugProbeError, Probe, WireProtocol},
14};
15use jep106::JEP106Code;
16
17use std::{
18 collections::{BTreeSet, HashMap, hash_map},
19 fmt::Debug,
20 sync::Arc,
21 time::Duration,
22};
23
24#[derive(Debug, thiserror::Error, Clone, PartialEq, Eq, Copy)]
27pub enum DapError {
28 #[error("A protocol error occurred in the {0} communication between probe and device.")]
30 Protocol(WireProtocol),
31 #[error("Target device did not respond to request.")]
33 NoAcknowledge,
34 #[error("Target device responded with a FAULT response to the request.")]
36 FaultResponse,
37 #[error("Target device responded with a WAIT response to the request.")]
39 WaitResponse,
40 #[error("Incorrect parity on READ request.")]
42 IncorrectParity,
43}
44
45pub trait ArmDebugInterface: DapAccess + SwdSequence + SwoAccess + Send {
47 fn reinitialize(&mut self) -> Result<(), ArmError>;
59
60 fn access_ports(
65 &mut self,
66 dp: DpAddress,
67 ) -> Result<BTreeSet<FullyQualifiedApAddress>, ArmError>;
68
69 fn close(self: Box<Self>) -> Probe;
71
72 fn select_debug_port(&mut self, dp: DpAddress) -> Result<(), ArmError>;
78
79 fn current_debug_port(&self) -> Option<DpAddress>;
83
84 fn memory_interface(
86 &mut self,
87 access_port: &FullyQualifiedApAddress,
88 ) -> Result<Box<dyn ArmMemoryInterface + '_>, ArmError>;
89}
90
91pub fn read_chip_info_from_rom_table(
93 probe: &mut dyn ArmDebugInterface,
94 dp: DpAddress,
95) -> Result<Option<ArmChipInfo>, ArmError> {
96 for ap in probe.access_ports(dp)? {
97 if let Ok(mut memory) = probe.memory_interface(&ap) {
98 let base_address = memory.base_address()?;
99 let component = Component::try_parse(&mut *memory, base_address)?;
100
101 if let Component::Class1RomTable(component_id, _) = component
102 && let Some(jep106) = component_id.peripheral_id().jep106()
103 {
104 return Ok(Some(ArmChipInfo {
105 manufacturer: jep106,
106 part: component_id.peripheral_id().part(),
107 }));
108 }
109 }
110 }
111
112 Ok(None)
113}
114
115pub trait SwdSequence {
117 fn swj_sequence(&mut self, bit_len: u8, bits: u64) -> Result<(), DebugProbeError>;
119
120 fn swj_pins(
122 &mut self,
123 pin_out: u32,
124 pin_select: u32,
125 pin_wait: u32,
126 ) -> Result<u32, DebugProbeError>;
127}
128
129#[derive(Debug, Clone, Copy, PartialEq, Eq)]
130pub(crate) enum SelectCache {
131 DPv1(SelectV1),
132 DPv3(SelectV3, Select1),
133}
134impl SelectCache {
135 pub fn dp_bank_sel(&self) -> u8 {
136 match self {
137 SelectCache::DPv1(s) => s.dp_bank_sel(),
138 SelectCache::DPv3(s, _) => s.dp_bank_sel(),
139 }
140 }
141 pub fn set_dp_bank_sel(&mut self, bank: u8) {
142 match self {
143 SelectCache::DPv1(s) => s.set_dp_bank_sel(bank),
144 SelectCache::DPv3(s, _) => s.set_dp_bank_sel(bank),
145 }
146 }
147}
148#[derive(Debug)]
149pub(crate) struct DpState {
150 pub debug_port_version: DebugPortVersion,
151
152 pub(crate) current_select: SelectCache,
153}
154
155impl DpState {
156 pub fn new() -> Self {
157 Self {
158 debug_port_version: DebugPortVersion::Unsupported(0xFF),
159 current_select: SelectCache::DPv1(SelectV1(0)),
160 }
161 }
162}
163
164#[derive(Debug)]
168pub struct ArmCommunicationInterface {
169 probe: Option<Box<dyn DapProbe>>,
170
171 current_dp: Option<DpAddress>,
176 dps: HashMap<DpAddress, DpState>,
177 use_overrun_detect: bool,
178 sequence: Arc<dyn ArmDebugSequence>,
179}
180
181impl Drop for ArmCommunicationInterface {
182 fn drop(&mut self) {
183 if self.probe.is_some() {
184 self.disconnect();
185
186 self.probe = None;
188 }
189 }
190}
191
192impl ArmCommunicationInterface {
193 pub(crate) fn probe_mut(&mut self) -> &mut dyn DapProbe {
194 self.probe.as_deref_mut().expect("ArmCommunicationInterface is in an inconsistent state. This is a bug, please report it.")
196 }
197
198 fn close(mut self) -> Probe {
199 self.disconnect();
200
201 let probe = self.probe.take().unwrap();
202
203 Probe::from_attached_probe(RawDapAccess::into_probe(probe))
204 }
205
206 fn disconnect(&mut self) {
209 let probe = self.probe.as_deref_mut().unwrap();
210
211 if let Some(current_dp) = self.current_dp.take() {
212 let _stop_span = tracing::debug_span!("debug_port_stop").entered();
213
214 self.sequence.debug_port_stop(probe, current_dp).ok();
216
217 drop(_stop_span);
218
219 for dp in self.dps.keys().filter(|dp| **dp != current_dp) {
221 if self.sequence.debug_port_connect(probe, *dp).is_ok() {
223 self.sequence.debug_port_stop(probe, *dp).ok();
224 } else {
225 tracing::warn!("Failed to stop DP {:x?}", dp);
226 }
227 }
228 };
229
230 probe.raw_flush().ok();
231 }
232}
233
234pub trait DapProbe: RawDapAccess + DebugProbe {}
239
240impl ArmDebugInterface for ArmCommunicationInterface {
241 fn reinitialize(&mut self) -> Result<(), ArmError> {
242 let current_dp = self.current_dp;
243
244 self.disconnect();
246
247 assert!(self.current_dp.is_none());
249
250 if let Some(dp) = current_dp {
252 self.select_dp(dp)?;
253 }
254
255 Ok(())
256 }
257
258 fn memory_interface(
259 &mut self,
260 access_port_address: &FullyQualifiedApAddress,
261 ) -> Result<Box<dyn ArmMemoryInterface + '_>, ArmError> {
262 let memory_interface = match access_port_address.ap() {
263 ApAddress::V1(_) => Box::new(ADIMemoryInterface::new(self, access_port_address)?)
264 as Box<dyn ArmMemoryInterface + '_>,
265 ApAddress::V2(_) => ap::v2::new_memory_interface(self, access_port_address)?,
266 };
267 Ok(memory_interface)
268 }
269
270 fn current_debug_port(&self) -> Option<DpAddress> {
271 self.current_dp
272 }
273
274 fn close(self: Box<Self>) -> Probe {
275 ArmCommunicationInterface::close(*self)
276 }
277
278 fn access_ports(
279 &mut self,
280 dp: DpAddress,
281 ) -> Result<BTreeSet<FullyQualifiedApAddress>, ArmError> {
282 match self.select_dp(dp).map(|state| state.debug_port_version)? {
283 DebugPortVersion::DPv0 | DebugPortVersion::DPv1 | DebugPortVersion::DPv2 => {
284 Ok(ap::v1::valid_access_ports(self, dp).into_iter().collect())
285 }
286 DebugPortVersion::DPv3 => ap::v2::enumerate_access_ports(self, dp),
287 DebugPortVersion::Unsupported(_) => unreachable!(),
288 }
289 }
290
291 fn select_debug_port(&mut self, dp: DpAddress) -> Result<(), ArmError> {
292 let _ = self.select_dp(dp)?;
293 Ok(())
294 }
295}
296
297impl SwdSequence for ArmCommunicationInterface {
298 fn swj_sequence(&mut self, bit_len: u8, bits: u64) -> Result<(), DebugProbeError> {
299 self.probe_mut().swj_sequence(bit_len, bits)?;
300
301 Ok(())
302 }
303
304 fn swj_pins(
305 &mut self,
306 pin_out: u32,
307 pin_select: u32,
308 pin_wait: u32,
309 ) -> Result<u32, DebugProbeError> {
310 self.probe_mut().swj_pins(pin_out, pin_select, pin_wait)
311 }
312}
313
314impl ArmCommunicationInterface {
315 pub fn create(
318 probe: Box<dyn DapProbe>,
319 sequence: Arc<dyn ArmDebugSequence>,
320 use_overrun_detect: bool,
321 ) -> Box<dyn ArmDebugInterface> {
322 let interface = ArmCommunicationInterface {
323 probe: Some(probe),
324 current_dp: None,
325 dps: Default::default(),
326 use_overrun_detect,
327 sequence,
328 };
329
330 Box::new(interface)
331 }
332
333 pub fn core_status_notification(&mut self, state: CoreStatus) {
335 self.probe_mut().core_status_notification(state).ok();
336 }
337
338 fn select_dp(&mut self, dp: DpAddress) -> Result<&mut DpState, ArmError> {
339 let mut switched_dp = false;
340
341 let sequence = self.sequence.clone();
342
343 if self.current_dp != Some(dp) {
344 tracing::debug!("Selecting DP {:x?}", dp);
345
346 switched_dp = true;
347
348 self.probe_mut().raw_flush()?;
349
350 if self.current_dp.is_none() {
353 sequence.debug_port_setup(&mut *self.probe_mut(), dp)?;
354 } else {
355 if let Err(e) = sequence.debug_port_connect(&mut *self.probe_mut(), dp) {
357 tracing::warn!("Failed to switch to DP {:x?}: {}", dp, e);
358
359 sequence.debug_port_setup(&mut *self.probe_mut(), dp)?;
361 }
362 }
363
364 self.current_dp = Some(dp);
365 }
366
367 if let hash_map::Entry::Vacant(entry) = self.dps.entry(dp) {
369 let sequence = self.sequence.clone();
370
371 entry.insert(DpState::new());
372
373 let start_span = tracing::debug_span!("debug_port_start").entered();
374 sequence.debug_port_start(self, dp)?;
375 drop(start_span);
376
377 let mut ctrl_reg: Ctrl = self.read_dp_register(dp)?;
381 if ctrl_reg.orun_detect() != self.use_overrun_detect {
382 tracing::debug!("Setting orun_detect: {}", self.use_overrun_detect);
383 ctrl_reg.set_orun_detect(self.use_overrun_detect);
385 self.write_dp_register(dp, ctrl_reg)?;
386 }
387
388 let idr: DebugPortId = self.read_dp_register::<DPIDR>(dp)?.into();
389 tracing::info!(
390 "Debug Port version: {} MinDP: {:?}",
391 idr.version,
392 idr.min_dp_support
393 );
394
395 let state = self
396 .dps
397 .get_mut(&dp)
398 .expect("This DP State was inserted earlier in this function");
399 state.debug_port_version = idr.version;
400 if idr.version == DebugPortVersion::DPv3 {
401 state.current_select = SelectCache::DPv3(SelectV3(0), Select1(0));
402 }
403 } else if switched_dp {
404 let sequence = self.sequence.clone();
405
406 let start_span = tracing::debug_span!("debug_port_start").entered();
407 sequence.debug_port_start(self, dp)?;
408 drop(start_span);
409 }
410
411 Ok(self.dps.get_mut(&dp).unwrap())
413 }
414
415 fn select_dp_and_dp_bank(
416 &mut self,
417 dp: DpAddress,
418 dp_register_address: &DpRegisterAddress,
419 ) -> Result<(), ArmError> {
420 let dp_state = self.select_dp(dp)?;
421
422 let &DpRegisterAddress {
428 bank,
429 address: addr,
430 } = dp_register_address;
431
432 if addr != 0 && addr != 4 {
433 return Ok(());
434 }
435
436 let bank = bank.unwrap_or(0);
437
438 if bank != dp_state.current_select.dp_bank_sel() {
439 dp_state.current_select.set_dp_bank_sel(bank);
440
441 tracing::debug!("Changing DP_BANK_SEL to {:x?}", dp_state.current_select);
442
443 match dp_state.current_select {
444 SelectCache::DPv1(select) => self.write_dp_register(dp, select)?,
445 SelectCache::DPv3(select, _) => self.write_dp_register(dp, select)?,
446 }
447 }
448
449 Ok(())
450 }
451
452 fn select_ap_and_ap_bank(
453 &mut self,
454 ap: &FullyQualifiedApAddress,
455 ap_register_address: u64,
456 ) -> Result<(), ArmError> {
457 let dp_state = self.select_dp(ap.dp())?;
458
459 let previous_select = dp_state.current_select;
460 match (ap.ap(), &mut dp_state.current_select) {
461 (ApAddress::V1(port), SelectCache::DPv1(s)) => {
462 let ap_register_address = (ap_register_address & 0xFF) as u8;
463 let ap_bank = ap_register_address >> 4;
464 s.set_ap_sel(*port);
465 s.set_ap_bank_sel(ap_bank);
466 }
467 (ApAddress::V2(base), SelectCache::DPv3(s, s1)) => {
468 let address = base.0.unwrap_or(0) + ap_register_address;
469 s.set_addr(((address >> 4) & 0xFFFF_FFFF) as u32);
470 s1.set_addr((address >> 32) as u32);
471 }
472 _ => unreachable!(
473 "Did not expect to be called with {ap:x?}. This is a bug, please report it."
474 ),
475 }
476
477 if previous_select != dp_state.current_select {
478 tracing::debug!("Changing SELECT to {:x?}", dp_state.current_select);
479
480 match dp_state.current_select {
481 SelectCache::DPv1(select) => {
482 self.write_dp_register(ap.dp(), select)?;
483 }
484 SelectCache::DPv3(select, select1) => {
485 self.write_dp_register(ap.dp(), select)?;
486 self.write_dp_register(ap.dp(), select1)?;
487 }
488 }
489 }
490
491 Ok(())
492 }
493}
494
495impl SwoAccess for ArmCommunicationInterface {
496 fn enable_swo(&mut self, config: &SwoConfig) -> Result<(), ArmError> {
497 match self.probe_mut().get_swo_interface_mut() {
498 Some(interface) => interface.enable_swo(config),
499 None => Err(ArmError::ArchitectureRequired(&["ARMv7", "ARMv8"])),
500 }
501 }
502
503 fn disable_swo(&mut self) -> Result<(), ArmError> {
504 match self.probe_mut().get_swo_interface_mut() {
505 Some(interface) => interface.disable_swo(),
506 None => Err(ArmError::ArchitectureRequired(&["ARMv7", "ARMv8"])),
507 }
508 }
509
510 fn read_swo_timeout(&mut self, timeout: Duration) -> Result<Vec<u8>, ArmError> {
511 match self.probe_mut().get_swo_interface_mut() {
512 Some(interface) => interface.read_swo_timeout(timeout),
513 None => Err(ArmError::ArchitectureRequired(&["ARMv7", "ARMv8"])),
514 }
515 }
516}
517
518impl DapAccess for ArmCommunicationInterface {
519 fn read_raw_dp_register(
520 &mut self,
521 dp: DpAddress,
522 address: DpRegisterAddress,
523 ) -> Result<u32, ArmError> {
524 self.select_dp_and_dp_bank(dp, &address)?;
525 let result = self.probe_mut().raw_read_register(address.into())?;
526 Ok(result)
527 }
528
529 fn write_raw_dp_register(
530 &mut self,
531 dp: DpAddress,
532 address: DpRegisterAddress,
533 value: u32,
534 ) -> Result<(), ArmError> {
535 self.select_dp_and_dp_bank(dp, &address)?;
536 self.probe_mut().raw_write_register(address.into(), value)?;
537 Ok(())
538 }
539
540 fn read_raw_ap_register(
541 &mut self,
542 ap: &FullyQualifiedApAddress,
543 address: u64,
544 ) -> Result<u32, ArmError> {
545 self.select_ap_and_ap_bank(ap, address)?;
546
547 let result = self
548 .probe_mut()
549 .raw_read_register(RegisterAddress::ApRegister((address & 0xFF) as u8))?;
550
551 Ok(result)
552 }
553
554 fn read_raw_ap_register_repeated(
555 &mut self,
556 ap: &FullyQualifiedApAddress,
557 address: u64,
558 values: &mut [u32],
559 ) -> Result<(), ArmError> {
560 self.select_ap_and_ap_bank(ap, address)?;
561
562 self.probe_mut()
563 .raw_read_block(RegisterAddress::ApRegister((address & 0xFF) as u8), values)?;
564 Ok(())
565 }
566
567 fn write_raw_ap_register(
568 &mut self,
569 ap: &FullyQualifiedApAddress,
570 address: u64,
571 value: u32,
572 ) -> Result<(), ArmError> {
573 self.select_ap_and_ap_bank(ap, address)?;
574
575 self.probe_mut()
576 .raw_write_register(RegisterAddress::ApRegister((address & 0xFF) as u8), value)?;
577
578 Ok(())
579 }
580
581 fn write_raw_ap_register_repeated(
582 &mut self,
583 ap: &FullyQualifiedApAddress,
584 address: u64,
585 values: &[u32],
586 ) -> Result<(), ArmError> {
587 self.select_ap_and_ap_bank(ap, address)?;
588
589 self.probe_mut()
590 .raw_write_block(RegisterAddress::ApRegister((address & 0xFF) as u8), values)?;
591 Ok(())
592 }
593
594 fn flush(&mut self) -> Result<(), ArmError> {
595 self.probe_mut().raw_flush()
596 }
597
598 fn try_dap_probe(&self) -> Option<&dyn DapProbe> {
599 self.probe.as_deref()
600 }
601
602 fn try_dap_probe_mut(&mut self) -> Option<&mut dyn DapProbe> {
603 self.probe
604 .as_deref_mut()
605 .map(|p: &mut (dyn DapProbe + 'static)| p as &mut (dyn DapProbe + '_))
607 }
608}
609
610#[derive(Debug, Clone, Copy)]
614pub struct ArmChipInfo {
615 pub manufacturer: JEP106Code,
617 pub part: u16,
622}
623
624impl std::fmt::Display for ArmChipInfo {
625 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
626 let manu = match self.manufacturer.get() {
627 Some(name) => name.to_string(),
628 None => format!(
629 "<unknown manufacturer (cc={:2x}, id={:2x})>",
630 self.manufacturer.cc, self.manufacturer.id
631 ),
632 };
633 write!(f, "{} 0x{:04x}", manu, self.part)
634 }
635}