1mod commands;
3mod tools;
4
5use crate::{
6 CoreStatus,
7 architecture::{
8 arm::{
9 ArmCommunicationInterface, ArmDebugInterface, ArmError, DapError, Pins, RawDapAccess,
10 RegisterAddress, SwoAccess, SwoConfig, SwoMode,
11 communication_interface::DapProbe,
12 dp::{Abort, Ctrl, DpRegister},
13 sequences::ArmDebugSequence,
14 swo::poll_interval_from_buf_size,
15 },
16 riscv::{
17 communication_interface::{RiscvError, RiscvInterfaceBuilder},
18 dtm::jtag_dtm::JtagDtmBuilder,
19 },
20 xtensa::communication_interface::{
21 XtensaCommunicationInterface, XtensaDebugInterfaceState, XtensaError,
22 },
23 },
24 probe::{
25 AutoImplementJtagAccess, BatchCommand, DebugProbe, DebugProbeError, DebugProbeSelector,
26 JtagAccess, JtagDriverState, ProbeFactory, WireProtocol,
27 cmsisdap::commands::{
28 CmsisDapError, RequestError,
29 general::info::{CapabilitiesCommand, PacketCountCommand, SWOTraceBufferSizeCommand},
30 },
31 },
32};
33
34use commands::{
35 CmsisDapDevice, Status,
36 general::{
37 connect::{ConnectRequest, ConnectResponse},
38 disconnect::{DisconnectRequest, DisconnectResponse},
39 host_status::{HostStatusRequest, HostStatusResponse},
40 info::Capabilities,
41 reset::{ResetRequest, ResetResponse},
42 },
43 jtag::{
44 JtagBuffer,
45 configure::ConfigureRequest as JtagConfigureRequest,
46 sequence::{
47 Sequence as JtagSequence, SequenceRequest as JtagSequenceRequest,
48 SequenceResponse as JtagSequenceResponse,
49 },
50 },
51 swd,
52 swj::{
53 clock::SWJClockRequest,
54 pins::{SWJPinsRequest, SWJPinsRequestBuilder, SWJPinsResponse},
55 sequence::{SequenceRequest, SequenceResponse},
56 },
57 swo,
58 transfer::{
59 Ack, TransferBlockRequest, TransferBlockResponse, TransferRequest,
60 configure::ConfigureRequest,
61 },
62};
63use probe_rs_target::ScanChainElement;
64
65use std::{fmt::Write, sync::Arc, time::Duration};
66
67use bitvec::prelude::*;
68
69use super::common::{ScanChainError, extract_idcodes, extract_ir_lengths};
70
71#[derive(Debug)]
73pub struct CmsisDapFactory;
74
75impl std::fmt::Display for CmsisDapFactory {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 f.write_str("CMSIS-DAP")
78 }
79}
80
81impl ProbeFactory for CmsisDapFactory {
82 fn open(&self, selector: &DebugProbeSelector) -> Result<Box<dyn DebugProbe>, DebugProbeError> {
83 CmsisDap::new_from_device(tools::open_device_from_selector(selector)?)
84 .map(Box::new)
85 .map(DebugProbe::into_probe)
86 }
87
88 fn list_probes(&self) -> Vec<crate::probe::list::ProbeListItem> {
89 tools::list_cmsisdap_devices()
90 }
91}
92
93pub struct CmsisDap {
95 device: CmsisDapDevice,
96 _hw_version: u8,
97 _jtag_version: u8,
98 protocol: Option<WireProtocol>,
99
100 packet_size: u16,
101 packet_count: u8,
102 capabilities: Capabilities,
103 swo_buffer_size: Option<usize>,
104 swo_active: bool,
105 swo_streaming: bool,
106 connected: bool,
107
108 speed_khz: u32,
110
111 batch: Vec<BatchCommand>,
112
113 jtag_state: JtagDriverState,
114 jtag_buffer: JtagBuffer,
115}
116
117impl std::fmt::Debug for CmsisDap {
118 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119 fmt.debug_struct("CmsisDap")
120 .field("protocol", &self.protocol)
121 .field("packet_size", &self.packet_size)
122 .field("packet_count", &self.packet_count)
123 .field("capabilities", &self.capabilities)
124 .field("swo_buffer_size", &self.swo_buffer_size)
125 .field("swo_active", &self.swo_active)
126 .field("swo_streaming", &self.swo_streaming)
127 .field("speed_khz", &self.speed_khz)
128 .finish()
129 }
130}
131
132impl CmsisDap {
133 fn new_from_device(mut device: CmsisDapDevice) -> Result<Self, DebugProbeError> {
134 device.drain();
137
138 let packet_size = device.find_packet_size()? as u16;
141
142 let packet_count = commands::send_command(&mut device, &PacketCountCommand {})?;
144 let caps: Capabilities = commands::send_command(&mut device, &CapabilitiesCommand {})?;
145 tracing::debug!("Detected probe capabilities: {:?}", caps);
146 let mut swo_buffer_size = None;
147 if caps.swo_uart_implemented || caps.swo_manchester_implemented {
148 let swo_size = commands::send_command(&mut device, &SWOTraceBufferSizeCommand {})?;
149 swo_buffer_size = Some(swo_size as usize);
150 tracing::debug!("Probe SWO buffer size: {}", swo_size);
151 }
152
153 Ok(Self {
154 device,
155 _hw_version: 0,
156 _jtag_version: 0,
157 protocol: None,
158 packet_count,
159 packet_size,
160 capabilities: caps,
161 swo_buffer_size,
162 swo_active: false,
163 swo_streaming: false,
164 connected: false,
165 speed_khz: 1_000,
166 batch: Vec::new(),
167 jtag_state: JtagDriverState::default(),
168 jtag_buffer: JtagBuffer::new(packet_size - 1),
169 })
170 }
171
172 fn set_swj_clock(&mut self, clock_speed_hz: u32) -> Result<(), CmsisDapError> {
176 let request = SWJClockRequest { clock_speed_hz };
177 commands::send_command(&mut self.device, &request).and_then(|v| match v.status {
178 Status::DapOk => Ok(()),
179 Status::DapError => Err(CmsisDapError::ErrorResponse(RequestError::SWJClock {
180 request,
181 })),
182 })
183 }
184
185 fn transfer_configure(&mut self, request: ConfigureRequest) -> Result<(), CmsisDapError> {
186 commands::send_command(&mut self.device, &request).and_then(|v| match v.status {
187 Status::DapOk => Ok(()),
188 Status::DapError => Err(CmsisDapError::ErrorResponse(
189 RequestError::TransferConfigure { request },
190 )),
191 })
192 }
193
194 fn configure_swd(
195 &mut self,
196 request: swd::configure::ConfigureRequest,
197 ) -> Result<(), CmsisDapError> {
198 commands::send_command(&mut self.device, &request).and_then(|v| match v.status {
199 Status::DapOk => Ok(()),
200 Status::DapError => Err(CmsisDapError::ErrorResponse(RequestError::SwdConfigure {
201 request,
202 })),
203 })
204 }
205
206 fn jtag_ensure_test_logic_reset(&mut self) -> Result<(), CmsisDapError> {
208 let sequence = JtagSequence::no_capture(true, bits![0; 6])?;
209 let sequences = vec![sequence];
210
211 self.send_jtag_sequences(JtagSequenceRequest::new(sequences)?)?;
212
213 Ok(())
214 }
215
216 fn jtag_ensure_run_test_idle(&mut self) -> Result<(), CmsisDapError> {
218 self.jtag_ensure_test_logic_reset()?;
222
223 let sequence = JtagSequence::no_capture(false, bits![0; 1])?;
225 let sequences = vec![sequence];
226 self.send_jtag_sequences(JtagSequenceRequest::new(sequences)?)?;
227
228 Ok(())
229 }
230
231 fn jtag_scan(
237 &mut self,
238 ir_lengths: Option<&[usize]>,
239 ) -> Result<Vec<ScanChainElement>, CmsisDapError> {
240 let (ir, dr) = self.jtag_reset_scan()?;
241 let idcodes = extract_idcodes(&dr)?;
242 let ir_lens = extract_ir_lengths(&ir, idcodes.len(), ir_lengths)?;
243
244 Ok(idcodes
245 .into_iter()
246 .zip(ir_lens)
247 .map(|(idcode, irlen)| ScanChainElement {
248 ir_len: Some(irlen as u8),
249 name: idcode.map(|i| i.to_string()),
250 })
251 .collect())
252 }
253
254 fn jtag_reset_scan(&mut self) -> Result<(BitVec, BitVec), CmsisDapError> {
258 let dr = self.jtag_scan_dr()?;
259 let ir = self.jtag_scan_ir()?;
260
261 self.jtag_ensure_run_test_idle()?;
263
264 Ok((ir, dr))
265 }
266
267 fn jtag_scan_ir(&mut self) -> Result<BitVec, CmsisDapError> {
272 self.jtag_ensure_shift_ir()?;
273 let data = self.jtag_scan_inner("IR")?;
274 Ok(data)
275 }
276
277 fn jtag_scan_dr(&mut self) -> Result<BitVec, CmsisDapError> {
282 self.jtag_ensure_shift_dr()?;
283 let data = self.jtag_scan_inner("DR")?;
284 Ok(data)
285 }
286
287 fn jtag_scan_inner(&mut self, name: &'static str) -> Result<BitVec, CmsisDapError> {
290 const MAX_LENGTH: usize = 128;
292 const BYTES_PER_REQUEST: usize = 16;
294 const REQUESTS: usize = MAX_LENGTH.div_ceil(BYTES_PER_REQUEST * 8);
296
297 let mut tdo_bytes: BitVec = BitVec::with_capacity(REQUESTS * BYTES_PER_REQUEST * 8);
299 for _ in 0..REQUESTS {
300 let sequences = vec![
301 JtagSequence::capture(false, bits![0; 64])?,
302 JtagSequence::capture(false, bits![0; 64])?,
303 ];
304
305 tdo_bytes.extend_from_bitslice(
306 &self.send_jtag_sequences(JtagSequenceRequest::new(sequences)?)?,
307 );
308 }
309 let d0 = tdo_bytes;
310
311 let mut tdo_bytes: BitVec<u8> = BitVec::with_capacity(REQUESTS * BYTES_PER_REQUEST * 8);
313 for _ in 0..REQUESTS {
314 let sequences = vec![
315 JtagSequence::capture(false, bits![1; 64])?,
316 JtagSequence::capture(false, bits![1; 64])?,
317 ];
318
319 tdo_bytes.extend_from_bitslice(
320 &self.send_jtag_sequences(JtagSequenceRequest::new(sequences)?)?,
321 );
322 }
323 let d1 = tdo_bytes;
324
325 let n = match d1.first_one() {
327 Some(n) => {
328 tracing::info!("JTAG {name} scan chain detected as {n} bits long");
329 n
330 }
331 None => {
332 let expected_bit = 1;
333 tracing::error!(
334 "JTAG {name} scan chain either broken or too long: did not detect {expected_bit}"
335 );
336 return Err(CmsisDapError::ErrorResponse(
337 RequestError::BrokenScanChain { name, expected_bit },
338 ));
339 }
340 };
341
342 if n == 0 {
344 tracing::error!("JTAG {name} scan chain is empty");
345 return Err(CmsisDapError::ErrorResponse(RequestError::EmptyScanChain {
346 name,
347 }));
348 }
349
350 if d0[n..].any() {
352 let expected_bit = 0;
353 tracing::error!(
354 "JTAG {name} scan chain either broken or too long: did not detect {expected_bit}"
355 );
356 return Err(CmsisDapError::ErrorResponse(
357 RequestError::BrokenScanChain { name, expected_bit },
358 ));
359 }
360
361 let data = d0[..n].to_bitvec();
363
364 Ok(data)
365 }
366
367 fn jtag_ensure_shift_dr(&mut self) -> Result<(), CmsisDapError> {
368 self.jtag_ensure_test_logic_reset()?;
370
371 let sequences = vec![
373 JtagSequence::no_capture(false, bits![0; 1])?,
374 JtagSequence::no_capture(true, bits![0; 1])?,
375 JtagSequence::no_capture(false, bits![0; 2])?,
376 ];
377 self.send_jtag_sequences(JtagSequenceRequest::new(sequences)?)?;
378
379 Ok(())
380 }
381
382 fn jtag_ensure_shift_ir(&mut self) -> Result<(), CmsisDapError> {
383 self.jtag_ensure_test_logic_reset()?;
385
386 let sequences = vec![
388 JtagSequence::no_capture(false, bits![0; 1])?,
389 JtagSequence::no_capture(true, bits![0; 2])?,
390 JtagSequence::no_capture(false, bits![0; 2])?,
391 ];
392 self.send_jtag_sequences(JtagSequenceRequest::new(sequences)?)?;
393
394 Ok(())
395 }
396
397 fn send_jtag_configure(&mut self, request: JtagConfigureRequest) -> Result<(), CmsisDapError> {
398 commands::send_command(&mut self.device, &request).and_then(|v| match v.status {
399 Status::DapOk => Ok(()),
400 Status::DapError => Err(CmsisDapError::ErrorResponse(RequestError::JtagConfigure {
401 request,
402 })),
403 })
404 }
405
406 fn send_jtag_sequences(
407 &mut self,
408 request: JtagSequenceRequest,
409 ) -> Result<BitVec, CmsisDapError> {
410 commands::send_command(&mut self.device, &request).and_then(|v| match v {
411 JtagSequenceResponse(Status::DapOk, tdo) => Ok(tdo),
412 JtagSequenceResponse(Status::DapError, _) => {
413 Err(CmsisDapError::ErrorResponse(RequestError::JtagSequence {
414 request,
415 }))
416 }
417 })
418 }
419
420 fn send_swj_sequences(&mut self, request: SequenceRequest) -> Result<(), CmsisDapError> {
421 commands::send_command(&mut self.device, &request).and_then(|v| match v {
425 SequenceResponse(Status::DapOk) => Ok(()),
426 SequenceResponse(Status::DapError) => {
427 Err(CmsisDapError::ErrorResponse(RequestError::SwjSequence {
428 request,
429 }))
430 }
431 })
432 }
433
434 fn read_ctrl_register(&mut self) -> Result<Ctrl, ArmError> {
443 let mut request = TransferRequest::read(Ctrl::ADDRESS);
444 request.dap_index = self.jtag_state.chain_params.index as u8;
445 let response =
446 commands::send_command(&mut self.device, &request).map_err(DebugProbeError::from)?;
447
448 if response.last_transfer_response.protocol_error {
452 Err(DapError::Protocol(
455 self.protocol
456 .expect("A wire protocol should have been selected by now"),
457 )
458 .into())
459 } else {
460 if response.last_transfer_response.ack != Ack::Ok {
461 tracing::debug!(
462 "Error reading debug port CTRL register: {:?}. This should never fail!",
463 response.last_transfer_response.ack
464 );
465 }
466
467 match response.last_transfer_response.ack {
468 Ack::Ok => {
469 Ok(Ctrl(response.transfers[0].data.expect(
470 "CMSIS-DAP probe should always return data for a read.",
471 )))
472 }
473 Ack::Wait => Err(DapError::WaitResponse.into()),
474 Ack::Fault => Err(DapError::FaultResponse.into()),
475 Ack::NoAck => Err(DapError::NoAcknowledge.into()),
476 }
477 }
478 }
479
480 fn write_abort(&mut self, abort: Abort) -> Result<(), ArmError> {
481 let mut request = TransferRequest::write(Abort::ADDRESS, abort.into());
482 request.dap_index = self.jtag_state.chain_params.index as u8;
483 let response =
484 commands::send_command(&mut self.device, &request).map_err(DebugProbeError::from)?;
485
486 if response.last_transfer_response.protocol_error {
490 Err(DapError::Protocol(
493 self.protocol
494 .expect("A wire protocol should have been selected by now"),
495 )
496 .into())
497 } else {
498 match response.last_transfer_response.ack {
499 Ack::Ok => Ok(()),
500 Ack::Wait => Err(DapError::WaitResponse.into()),
501 Ack::Fault => Err(DapError::FaultResponse.into()),
502 Ack::NoAck => Err(DapError::NoAcknowledge.into()),
503 }
504 }
505 }
506
507 fn handle_sticky_err(&mut self) -> Result<(), ArmError> {
510 let ctrl = self.read_ctrl_register();
511 tracing::trace!("Ctrl/Stat register value is: {:?}", ctrl);
512
513 match ctrl {
514 Ok(ctrl) if !ctrl.sticky_err() => Ok(()),
515 Ok(_) | Err(ArmError::Dap(DapError::FaultResponse)) => {
516 self.write_abort({
518 let mut abort = Abort(0);
519 abort.set_stkerrclr(true);
520 abort
521 })
522 }
523 Err(e) => Err(e),
524 }
525 }
526
527 #[tracing::instrument(skip(self))]
535 fn process_batch(&mut self) -> Result<Option<u32>, ArmError> {
536 let batch = std::mem::take(&mut self.batch);
537 if batch.is_empty() {
538 return Ok(None);
539 }
540
541 tracing::debug!("{} items in batch", batch.len());
542
543 let mut transfers = TransferRequest::empty();
544 transfers.dap_index = self.jtag_state.chain_params.index as u8;
545 for command in batch.iter().cloned() {
546 match command {
547 BatchCommand::Read(port) => {
548 transfers.add_read(port);
549 }
550 BatchCommand::Write(port, value) => {
551 transfers.add_write(port, value);
552 }
553 }
554 }
555
556 let response =
557 commands::send_command(&mut self.device, &transfers).map_err(DebugProbeError::from)?;
558
559 let count = response.transfers.len();
560
561 tracing::debug!("{} of batch of {} items executed", count, batch.len());
562
563 if response.last_transfer_response.protocol_error {
564 tracing::warn!(
565 "Protocol error in response to command {}",
566 batch[count.saturating_sub(1)]
567 );
568
569 return Err(DapError::Protocol(
570 self.protocol
571 .expect("A wire protocol should have been selected by now"),
572 )
573 .into());
574 }
575
576 match response.last_transfer_response.ack {
577 Ack::Ok => {
578 if count < batch.len() {
586 tracing::warn!(
587 "CMSIS_DAP: Only {}/{} transfers were executed, but no error was reported.",
588 count,
589 batch.len()
590 );
591 return Err(DebugProbeError::Other(format!(
592 "Possible error in CMSIS-DAP probe: Only {}/{} transfers were executed, but no error was reported.",
593 count,
594 batch.len()
595 )).into());
596 }
597
598 tracing::trace!("Last transfer status: ACK");
599 Ok(response.transfers[count - 1].data)
600 }
601 Ack::NoAck => {
602 tracing::debug!(
603 "Transfer status for batch item {}/{}: NACK",
604 count,
605 batch.len()
606 );
607 Err(DapError::NoAcknowledge.into())
609 }
610 Ack::Fault => {
611 tracing::debug!(
612 "Transfer status for batch item {}/{}: FAULT",
613 count,
614 batch.len()
615 );
616
617 self.handle_sticky_err()?;
621
622 Err(DapError::FaultResponse.into())
623 }
624 Ack::Wait => {
625 tracing::debug!(
626 "Transfer status for batch item {}/{}: WAIT",
627 count,
628 batch.len()
629 );
630
631 self.write_abort({
632 let mut abort = Abort(0);
633 abort.set_dapabort(true);
634 abort
635 })?;
636
637 Err(DapError::WaitResponse.into())
638 }
639 }
640 }
641
642 fn batch_add(&mut self, command: BatchCommand) -> Result<Option<u32>, ArmError> {
649 tracing::debug!("Adding command to batch: {}", command);
650
651 let command_is_read = matches!(command, BatchCommand::Read(_));
652 self.batch.push(command);
653
654 let max_writes = (self.packet_size as usize - 3) / (1 + 4);
658 if command_is_read || self.batch.len() == max_writes {
659 self.process_batch()
660 } else {
661 Ok(None)
662 }
663 }
664
665 fn set_swo_transport(
669 &mut self,
670 transport: swo::TransportRequest,
671 ) -> Result<(), DebugProbeError> {
672 let response = commands::send_command(&mut self.device, &transport)?;
673 match response.status {
674 Status::DapOk => Ok(()),
675 Status::DapError => {
676 Err(CmsisDapError::ErrorResponse(RequestError::SwoTransport { transport }).into())
677 }
678 }
679 }
680
681 fn set_swo_mode(&mut self, mode: swo::ModeRequest) -> Result<(), DebugProbeError> {
685 let response = commands::send_command(&mut self.device, &mode)?;
686 match response.status {
687 Status::DapOk => Ok(()),
688 Status::DapError => {
689 Err(CmsisDapError::ErrorResponse(RequestError::SwoMode { mode }).into())
690 }
691 }
692 }
693
694 fn set_swo_baudrate(&mut self, request: swo::BaudrateRequest) -> Result<u32, DebugProbeError> {
701 let response = commands::send_command(&mut self.device, &request)?;
702 tracing::debug!("Requested baud {}, got {}", request.baudrate, response);
703 if response == 0 {
704 Err(CmsisDapError::SwoBaudrateNotConfigured.into())
705 } else {
706 Ok(response)
707 }
708 }
709
710 fn start_swo_capture(&mut self) -> Result<(), DebugProbeError> {
712 let command = swo::ControlRequest::Start;
713 let response = commands::send_command(&mut self.device, &command)?;
714 match response.status {
715 Status::DapOk => Ok(()),
716 Status::DapError => {
717 Err(CmsisDapError::ErrorResponse(RequestError::SwoControl { command }).into())
718 }
719 }
720 }
721
722 fn stop_swo_capture(&mut self) -> Result<(), DebugProbeError> {
724 let command = swo::ControlRequest::Stop;
725 let response = commands::send_command(&mut self.device, &command)?;
726 match response.status {
727 Status::DapOk => Ok(()),
728 Status::DapError => {
729 Err(CmsisDapError::ErrorResponse(RequestError::SwoControl { command }).into())
730 }
731 }
732 }
733
734 #[expect(dead_code)]
736 fn get_swo_status(&mut self) -> Result<swo::StatusResponse, DebugProbeError> {
737 Ok(commands::send_command(
738 &mut self.device,
739 &swo::StatusRequest,
740 )?)
741 }
742
743 #[expect(dead_code)]
749 fn get_swo_extended_status(
750 &mut self,
751 request: swo::ExtendedStatusRequest,
752 ) -> Result<swo::ExtendedStatusResponse, DebugProbeError> {
753 Ok(commands::send_command(&mut self.device, &request)?)
754 }
755
756 fn get_swo_data(&mut self) -> Result<Vec<u8>, DebugProbeError> {
758 match self.swo_buffer_size {
759 Some(swo_buffer_size) => {
760 let n = usize::min(swo_buffer_size, self.packet_size as usize) as u16;
764
765 let response: swo::DataResponse =
766 commands::send_command(&mut self.device, &swo::DataRequest { max_count: n })?;
767 if response.status.error {
768 Err(CmsisDapError::SwoTraceStreamError.into())
769 } else {
770 Ok(response.data)
771 }
772 }
773 None => Ok(Vec::new()),
774 }
775 }
776
777 fn connect_if_needed(&mut self) -> Result<(), DebugProbeError> {
778 if self.connected {
779 return Ok(());
780 }
781
782 let protocol: ConnectRequest = if let Some(protocol) = self.protocol {
783 match protocol {
784 WireProtocol::Swd => ConnectRequest::Swd,
785 WireProtocol::Jtag => ConnectRequest::Jtag,
786 }
787 } else {
788 ConnectRequest::DefaultPort
789 };
790
791 let used_protocol =
792 commands::send_command(&mut self.device, &protocol).and_then(|v| match v {
793 ConnectResponse::SuccessfulInitForSWD => Ok(WireProtocol::Swd),
794 ConnectResponse::SuccessfulInitForJTAG => Ok(WireProtocol::Jtag),
795 ConnectResponse::InitFailed => {
796 Err(CmsisDapError::ErrorResponse(RequestError::InitFailed {
797 protocol: self.protocol,
798 }))
799 }
800 })?;
801
802 tracing::info!("Using protocol {}", used_protocol);
804 self.protocol = Some(used_protocol);
805
806 if matches!(self.protocol, Some(WireProtocol::Jtag)) {
809 commands::send_command(
810 &mut self.device,
811 &SWJPinsRequestBuilder::new().ntrst(true).build(),
812 )
813 .ok();
814 }
815 self.connected = true;
816
817 Ok(())
818 }
819
820 fn handle_transfer_block_response(
821 &mut self,
822 address: RegisterAddress,
823 resp: &TransferBlockResponse,
824 executed_transfers: usize,
825 total_transfers: usize,
826 ) -> Result<(), ArmError> {
827 if resp.transfer_response.protocol_error {
828 tracing::warn!(
829 "Protocol error in block read from register {:?}, read {}/{}",
830 address,
831 executed_transfers,
832 total_transfers,
833 );
834
835 return Err(
837 DapError::Protocol(self.protocol.expect("Protocol has been selected")).into(),
838 );
839 }
840
841 match resp.transfer_response.ack {
842 Ack::Ok => Ok(()),
844 Ack::Fault => {
845 tracing::debug!(
849 "FAULT response in block read from register {:?}, read {}/{}",
850 address,
851 executed_transfers,
852 total_transfers,
853 );
854
855 self.handle_sticky_err()?;
859
860 Err(DapError::FaultResponse.into())
861 }
862 Ack::NoAck => {
863 tracing::debug!(
867 "NACK response in block read from register {:?}, read {}/{}",
868 address,
869 executed_transfers,
870 total_transfers
871 );
872 Err(DapError::NoAcknowledge.into())
874 }
875 Ack::Wait => {
876 tracing::debug!(
880 "WAIT response in block read from register {:?}, read {}/{}",
881 address,
882 executed_transfers,
883 total_transfers
884 );
885
886 self.write_abort({
887 let mut abort = Abort(0);
888 abort.set_dapabort(true);
889 abort
890 })?;
891
892 Err(DapError::WaitResponse.into())
893 }
894 }
895 }
896}
897
898impl DebugProbe for CmsisDap {
899 fn get_name(&self) -> &str {
900 match &self.device {
901 CmsisDapDevice::V2 { handle, .. } => format!(
902 "CMSIS-DAP V2 IF: {} DESC: {:?}",
903 handle.interface_number(),
904 handle.descriptor()
905 )
906 .leak(),
907
908 #[cfg(feature = "cmsisdap_v1")]
909 _ => "CMSIS-DAP V1",
910 }
911 }
912
913 fn speed_khz(&self) -> u32 {
917 self.speed_khz
918 }
919
920 fn set_speed(&mut self, speed_khz: u32) -> Result<u32, DebugProbeError> {
924 self.set_swj_clock(speed_khz * 1_000)?;
925 self.speed_khz = speed_khz;
926
927 Ok(speed_khz)
928 }
929
930 #[tracing::instrument(skip(self))]
932 fn attach(&mut self) -> Result<(), DebugProbeError> {
933 tracing::debug!("Attaching to target system (clock = {}kHz)", self.speed_khz);
934
935 self.connect_if_needed()?;
937
938 self.set_speed(self.speed_khz)?;
940
941 self.transfer_configure(ConfigureRequest {
942 idle_cycles: 0,
943 wait_retry: 0xffff,
944 match_retry: 0,
945 })?;
946
947 if self.active_protocol() == Some(WireProtocol::Jtag) {
948 } else {
954 self.configure_swd(swd::configure::ConfigureRequest {})?;
955 }
956
957 let _: Result<HostStatusResponse, _> =
959 commands::send_command(&mut self.device, &HostStatusRequest::connected(true));
960
961 Ok(())
962 }
963
964 fn detach(&mut self) -> Result<(), crate::Error> {
966 self.process_batch()?;
967
968 if self.swo_active {
969 self.disable_swo()?;
970 }
971
972 let response = commands::send_command(&mut self.device, &DisconnectRequest {})
973 .map_err(DebugProbeError::from)?;
974
975 let request = HostStatusRequest::connected(false);
977 let _: Result<HostStatusResponse, _> = commands::send_command(&mut self.device, &request);
978
979 self.connected = false;
980
981 match response {
982 DisconnectResponse(Status::DapOk) => Ok(()),
983 DisconnectResponse(Status::DapError) => Err(crate::Error::Probe(
984 CmsisDapError::ErrorResponse(RequestError::HostStatus { request }).into(),
985 )),
986 }
987 }
988
989 fn select_protocol(&mut self, protocol: WireProtocol) -> Result<(), DebugProbeError> {
990 match protocol {
991 WireProtocol::Jtag if self.capabilities.jtag_implemented => {
992 self.protocol = Some(WireProtocol::Jtag);
993 Ok(())
994 }
995 WireProtocol::Swd if self.capabilities.swd_implemented => {
996 self.protocol = Some(WireProtocol::Swd);
997 Ok(())
998 }
999 _ => Err(DebugProbeError::UnsupportedProtocol(protocol)),
1000 }
1001 }
1002
1003 fn active_protocol(&self) -> Option<WireProtocol> {
1004 self.protocol
1005 }
1006
1007 fn target_reset(&mut self) -> Result<(), DebugProbeError> {
1009 commands::send_command(&mut self.device, &ResetRequest).map(|v: ResetResponse| {
1010 tracing::info!("Target reset response: {:?}", v);
1011 })?;
1012 Ok(())
1013 }
1014
1015 fn target_reset_assert(&mut self) -> Result<(), DebugProbeError> {
1016 let request = SWJPinsRequestBuilder::new().nreset(false).build();
1017
1018 commands::send_command(&mut self.device, &request).map(|v: SWJPinsResponse| {
1019 tracing::info!("Pin response: {:?}", v);
1020 })?;
1021 Ok(())
1022 }
1023
1024 fn target_reset_deassert(&mut self) -> Result<(), DebugProbeError> {
1025 let request = SWJPinsRequestBuilder::new().nreset(true).build();
1026
1027 commands::send_command(&mut self.device, &request).map(|v: SWJPinsResponse| {
1028 tracing::info!("Pin response: {:?}", v);
1029 })?;
1030 Ok(())
1031 }
1032
1033 fn get_swo_interface(&self) -> Option<&dyn SwoAccess> {
1034 Some(self as _)
1035 }
1036
1037 fn get_swo_interface_mut(&mut self) -> Option<&mut dyn SwoAccess> {
1038 Some(self as _)
1039 }
1040
1041 fn try_get_arm_debug_interface<'probe>(
1042 self: Box<Self>,
1043 sequence: Arc<dyn ArmDebugSequence>,
1044 ) -> Result<Box<dyn ArmDebugInterface + 'probe>, (Box<dyn DebugProbe>, ArmError)> {
1045 Ok(ArmCommunicationInterface::create(self, sequence, false))
1046 }
1047
1048 fn has_arm_interface(&self) -> bool {
1049 true
1050 }
1051
1052 fn into_probe(self: Box<Self>) -> Box<dyn DebugProbe> {
1053 self
1054 }
1055
1056 fn try_as_jtag_probe(&mut self) -> Option<&mut dyn JtagAccess> {
1057 Some(self)
1058 }
1059
1060 fn try_as_dap_probe(&mut self) -> Option<&mut dyn DapProbe> {
1061 Some(self)
1062 }
1063
1064 fn has_riscv_interface(&self) -> bool {
1065 true
1067 }
1068
1069 fn try_get_riscv_interface_builder<'probe>(
1070 &'probe mut self,
1071 ) -> Result<Box<dyn RiscvInterfaceBuilder<'probe> + 'probe>, RiscvError> {
1072 Ok(Box::new(JtagDtmBuilder::new(self)))
1073 }
1074
1075 fn try_get_xtensa_interface<'probe>(
1076 &'probe mut self,
1077 state: &'probe mut XtensaDebugInterfaceState,
1078 ) -> Result<XtensaCommunicationInterface<'probe>, XtensaError> {
1079 Ok(XtensaCommunicationInterface::new(self, state))
1080 }
1081
1082 fn has_xtensa_interface(&self) -> bool {
1083 true
1084 }
1085}
1086
1087impl AutoImplementJtagAccess for CmsisDap {}
1089
1090impl RawDapAccess for CmsisDap {
1091 fn core_status_notification(&mut self, status: CoreStatus) -> Result<(), DebugProbeError> {
1092 let running = status.is_running();
1093 commands::send_command(&mut self.device, &HostStatusRequest::running(running))?;
1094 Ok(())
1095 }
1096
1097 fn raw_read_register(&mut self, address: RegisterAddress) -> Result<u32, ArmError> {
1099 let res = self.batch_add(BatchCommand::Read(address))?;
1100
1101 res.ok_or_else(|| {
1105 DebugProbeError::Other("CMSIS-DAP read did not return any data".to_string()).into()
1106 })
1107 }
1108
1109 fn raw_write_register(&mut self, address: RegisterAddress, value: u32) -> Result<(), ArmError> {
1111 self.batch_add(BatchCommand::Write(address, value))
1112 .map(|_| ())
1113 }
1114
1115 fn raw_write_block(
1116 &mut self,
1117 address: RegisterAddress,
1118 values: &[u32],
1119 ) -> Result<(), ArmError> {
1120 self.process_batch()?;
1121
1122 let max_packet_size_words = (self.packet_size - 6) / 4;
1133
1134 let data_chunk_len = max_packet_size_words as usize;
1135
1136 let total_writes = values.len();
1137
1138 for (i, chunk) in values.chunks(data_chunk_len).enumerate() {
1139 let mut request = TransferBlockRequest::write_request(address, Vec::from(chunk));
1140 request.dap_index = self.jtag_state.chain_params.index as u8;
1141
1142 tracing::debug!("Transfer block: chunk={}, len={} bytes", i, chunk.len() * 4);
1143
1144 let resp: TransferBlockResponse = commands::send_command(&mut self.device, &request)
1145 .map_err(DebugProbeError::from)?;
1146
1147 let executed_writes = i * data_chunk_len + usize::from(resp.transfer_count);
1148
1149 self.handle_transfer_block_response(address, &resp, executed_writes, total_writes)?;
1150 }
1151
1152 Ok(())
1153 }
1154
1155 fn raw_read_block(
1156 &mut self,
1157 address: RegisterAddress,
1158 values: &mut [u32],
1159 ) -> Result<(), ArmError> {
1160 self.process_batch()?;
1161
1162 let max_packet_size_words = (self.packet_size - 6) / 4;
1173
1174 let data_chunk_len = max_packet_size_words as usize;
1175
1176 let total_num_reads = values.len();
1177
1178 for (i, chunk) in values.chunks_mut(data_chunk_len).enumerate() {
1179 let mut request = TransferBlockRequest::read_request(address, chunk.len() as u16);
1180 request.dap_index = self.jtag_state.chain_params.index as u8;
1181
1182 tracing::debug!("Transfer block: chunk={}, len={} bytes", i, chunk.len() * 4);
1183
1184 let resp: TransferBlockResponse = commands::send_command(&mut self.device, &request)
1185 .map_err(DebugProbeError::from)?;
1186
1187 let executed_reads = i * data_chunk_len + usize::from(resp.transfer_count);
1188
1189 self.handle_transfer_block_response(address, &resp, executed_reads, total_num_reads)?;
1190
1191 chunk.clone_from_slice(&resp.transfer_data[..]);
1192 }
1193
1194 Ok(())
1195 }
1196
1197 fn raw_flush(&mut self) -> Result<(), ArmError> {
1198 self.process_batch()?;
1199 Ok(())
1200 }
1201
1202 fn into_probe(self: Box<Self>) -> Box<dyn DebugProbe> {
1203 self
1204 }
1205
1206 fn configure_jtag(&mut self, skip_scan: bool) -> Result<(), DebugProbeError> {
1207 let ir_lengths = if skip_scan {
1208 self.jtag_state
1209 .expected_scan_chain
1210 .as_ref()
1211 .map(|chain| chain.iter().filter_map(|s| s.ir_len).collect::<Vec<u8>>())
1212 .unwrap_or_default()
1213 } else {
1214 let chain = self.jtag_scan(
1215 self.jtag_state
1216 .expected_scan_chain
1217 .as_ref()
1218 .map(|chain| {
1219 chain
1220 .iter()
1221 .filter_map(|s| s.ir_len)
1222 .map(|s| s as usize)
1223 .collect::<Vec<usize>>()
1224 })
1225 .as_deref(),
1226 )?;
1227 chain.iter().map(|item| item.ir_len()).collect()
1228 };
1229 tracing::info!("Configuring JTAG with ir lengths: {:?}", ir_lengths);
1230 self.send_jtag_configure(JtagConfigureRequest::new(ir_lengths)?)?;
1231
1232 Ok(())
1233 }
1234
1235 fn jtag_sequence(&mut self, cycles: u8, tms: bool, tdi: u64) -> Result<(), DebugProbeError> {
1236 self.connect_if_needed()?;
1237
1238 let tdi_bytes = tdi.to_le_bytes();
1239 let sequence = JtagSequence::new(cycles, false, tms, tdi_bytes)?;
1240 let sequences = vec![sequence];
1241
1242 self.send_jtag_sequences(JtagSequenceRequest::new(sequences)?)?;
1243
1244 Ok(())
1245 }
1246
1247 fn swj_sequence(&mut self, bit_len: u8, bits: u64) -> Result<(), DebugProbeError> {
1248 self.connect_if_needed()?;
1249
1250 let data = bits.to_le_bytes();
1251
1252 if tracing::enabled!(tracing::Level::TRACE) {
1253 let mut seq = String::new();
1254
1255 let _ = write!(&mut seq, "swj sequence:");
1256
1257 for i in 0..bit_len {
1258 let bit = (bits >> i) & 1;
1259
1260 if bit == 1 {
1261 let _ = write!(&mut seq, "1");
1262 } else {
1263 let _ = write!(&mut seq, "0");
1264 }
1265 }
1266 tracing::trace!("{}", seq);
1267 }
1268
1269 self.send_swj_sequences(SequenceRequest::new(&data, bit_len)?)?;
1270
1271 Ok(())
1272 }
1273
1274 fn swj_pins(
1275 &mut self,
1276 pin_out: u32,
1277 pin_select: u32,
1278 pin_wait: u32,
1279 ) -> Result<u32, DebugProbeError> {
1280 self.connect_if_needed()?;
1281
1282 let request = SWJPinsRequest::from_raw_values(pin_out as u8, pin_select as u8, pin_wait);
1283
1284 let Pins(response) = commands::send_command(&mut self.device, &request)?;
1285
1286 Ok(response as u32)
1287 }
1288}
1289
1290impl DapProbe for CmsisDap {}
1291
1292impl SwoAccess for CmsisDap {
1293 fn enable_swo(&mut self, config: &SwoConfig) -> Result<(), ArmError> {
1294 let caps = self.capabilities;
1295
1296 match config.mode() {
1298 SwoMode::Uart if !caps.swo_uart_implemented => {
1299 return Err(ArmError::Probe(CmsisDapError::SwoModeNotAvailable.into()));
1300 }
1301 SwoMode::Manchester if !caps.swo_manchester_implemented => {
1302 return Err(ArmError::Probe(CmsisDapError::SwoModeNotAvailable.into()));
1303 }
1304 _ => (),
1305 }
1306
1307 self.stop_swo_capture()?;
1309
1310 if caps.swo_streaming_trace_implemented && self.device.swo_streaming_supported() {
1314 tracing::debug!("Starting SWO capture with streaming transport");
1315 self.set_swo_transport(swo::TransportRequest::WinUsbEndpoint)?;
1316 self.swo_streaming = true;
1317 } else {
1318 tracing::debug!("Starting SWO capture with polled transport");
1319 self.set_swo_transport(swo::TransportRequest::DataCommand)?;
1320 self.swo_streaming = false;
1321 }
1322
1323 match config.mode() {
1325 SwoMode::Uart => self.set_swo_mode(swo::ModeRequest::Uart)?,
1326 SwoMode::Manchester => self.set_swo_mode(swo::ModeRequest::Manchester)?,
1327 }
1328
1329 let baud = self.set_swo_baudrate(swo::BaudrateRequest {
1331 baudrate: config.baud(),
1332 })?;
1333 if baud != config.baud() {
1334 tracing::warn!(
1335 "Target SWO baud rate not met: requested {}, got {}",
1336 config.baud(),
1337 baud
1338 );
1339 }
1340
1341 self.start_swo_capture()?;
1342
1343 self.swo_active = true;
1344 Ok(())
1345 }
1346
1347 fn disable_swo(&mut self) -> Result<(), ArmError> {
1348 tracing::debug!("Stopping SWO capture");
1349 self.stop_swo_capture()?;
1350 self.swo_active = false;
1351 Ok(())
1352 }
1353
1354 fn read_swo_timeout(&mut self, timeout: Duration) -> Result<Vec<u8>, ArmError> {
1355 if self.swo_active {
1356 if self.swo_streaming {
1357 let buffer = self
1358 .device
1359 .read_swo_stream(timeout)
1360 .map_err(DebugProbeError::from)?;
1361 tracing::trace!("SWO streaming buffer: {:?}", buffer);
1362 Ok(buffer)
1363 } else {
1364 let data = self.get_swo_data()?;
1365 tracing::trace!("SWO polled data: {:?}", data);
1366 Ok(data)
1367 }
1368 } else {
1369 Ok(Vec::new())
1370 }
1371 }
1372
1373 fn swo_poll_interval_hint(&mut self, config: &SwoConfig) -> Option<Duration> {
1374 let caps = self.capabilities;
1375 if caps.swo_streaming_trace_implemented && self.device.swo_streaming_supported() {
1376 Some(Duration::from_secs(0))
1378 } else {
1379 match self.swo_buffer_size {
1380 Some(buf_size) => poll_interval_from_buf_size(config, buf_size),
1382
1383 None => None,
1385 }
1386 }
1387 }
1388
1389 fn swo_buffer_size(&mut self) -> Option<usize> {
1390 self.swo_buffer_size
1391 }
1392}
1393
1394impl Drop for CmsisDap {
1395 fn drop(&mut self) {
1396 tracing::debug!("Detaching from CMSIS-DAP probe");
1397 let _ = self.process_batch();
1399
1400 if self.swo_active {
1403 let _ = self.disable_swo();
1404 }
1405
1406 let _ = self.detach();
1407 }
1408}
1409
1410impl From<ScanChainError> for CmsisDapError {
1411 fn from(error: ScanChainError) -> Self {
1412 match error {
1413 ScanChainError::InvalidIdCode => CmsisDapError::InvalidIdCode,
1414 ScanChainError::InvalidIR => CmsisDapError::InvalidIR,
1415 }
1416 }
1417}