1use crate::{
2 CoreType, Endian, InstructionSet, MemoryInterface, Target,
3 architecture::{
4 arm::sequences::ArmDebugSequence, riscv::sequences::RiscvDebugSequence,
5 xtensa::sequences::XtensaDebugSequence,
6 },
7 config::DebugSequence,
8 error::Error,
9 memory::CoreMemoryInterface,
10};
11pub use probe_rs_target::{Architecture, CoreAccessOptions};
12use probe_rs_target::{
13 ArmCoreAccessOptions, MemoryRegion, RiscvCoreAccessOptions, XtensaCoreAccessOptions,
14};
15use std::{sync::Arc, time::Duration};
16
17pub mod core_state;
18pub mod core_status;
19pub mod dump;
20pub mod memory_mapped_registers;
21pub mod registers;
22
23pub use core_state::*;
24pub use core_status::*;
25pub use memory_mapped_registers::MemoryMappedRegister;
26pub use registers::*;
27
28#[derive(Debug, Clone)]
30pub struct CoreInformation {
31 pub pc: u64,
33}
34
35pub trait CoreInterface: MemoryInterface {
37 fn wait_for_core_halted(&mut self, timeout: Duration) -> Result<(), Error>;
40
41 fn core_halted(&mut self) -> Result<bool, Error>;
44
45 fn status(&mut self) -> Result<CoreStatus, Error>;
47
48 fn halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error>;
51
52 fn run(&mut self) -> Result<(), Error>;
54
55 fn reset(&mut self) -> Result<(), Error>;
60
61 fn reset_and_halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error>;
66
67 fn step(&mut self) -> Result<CoreInformation, Error>;
69
70 fn read_core_reg(
72 &mut self,
73 address: registers::RegisterId,
74 ) -> Result<registers::RegisterValue, Error>;
75
76 fn write_core_reg(
78 &mut self,
79 address: registers::RegisterId,
80 value: registers::RegisterValue,
81 ) -> Result<(), Error>;
82
83 fn available_breakpoint_units(&mut self) -> Result<u32, Error>;
85
86 fn hw_breakpoints(&mut self) -> Result<Vec<Option<u64>>, Error>;
90
91 fn enable_breakpoints(&mut self, state: bool) -> Result<(), Error>;
93
94 fn set_hw_breakpoint(&mut self, unit_index: usize, addr: u64) -> Result<(), Error>;
96
97 fn clear_hw_breakpoint(&mut self, unit_index: usize) -> Result<(), Error>;
99
100 fn registers(&self) -> &'static registers::CoreRegisters;
102
103 fn program_counter(&self) -> &'static CoreRegister;
105
106 fn frame_pointer(&self) -> &'static CoreRegister;
108
109 fn stack_pointer(&self) -> &'static CoreRegister;
111
112 fn return_address(&self) -> &'static CoreRegister;
114
115 fn hw_breakpoints_enabled(&self) -> bool;
117
118 fn debug_on_sw_breakpoint(&mut self, _enabled: bool) -> Result<(), Error> {
120 Ok(())
122 }
123
124 fn architecture(&self) -> Architecture;
126
127 fn core_type(&self) -> CoreType;
129
130 fn instruction_set(&mut self) -> Result<InstructionSet, Error>;
134
135 fn endianness(&mut self) -> Result<Endian, Error> {
138 Ok(Endian::Little)
140 }
141
142 fn fpu_support(&mut self) -> Result<bool, Error>;
146
147 fn floating_point_register_count(&mut self) -> Result<usize, Error>;
151
152 fn reset_catch_set(&mut self) -> Result<(), Error>;
158
159 fn reset_catch_clear(&mut self) -> Result<(), Error>;
163
164 fn debug_core_stop(&mut self) -> Result<(), Error>;
166
167 fn on_session_stop(&mut self) -> Result<(), Error> {
169 Ok(())
170 }
171
172 fn enable_vector_catch(&mut self, _condition: VectorCatchCondition) -> Result<(), Error> {
174 Err(Error::NotImplemented("vector catch"))
175 }
176
177 fn disable_vector_catch(&mut self, _condition: VectorCatchCondition) -> Result<(), Error> {
179 Err(Error::NotImplemented("vector catch"))
180 }
181
182 fn is_64_bit(&self) -> bool {
184 false
185 }
186}
187
188pub struct Core<'probe> {
195 id: usize,
196 name: &'probe str,
197 target: &'probe Target,
198
199 inner: Box<dyn CoreInterface + 'probe>,
200}
201
202impl CoreMemoryInterface for Core<'_> {
203 type ErrorType = Error;
204
205 fn memory(&self) -> &dyn MemoryInterface<Self::ErrorType> {
206 self.inner.as_ref()
207 }
208
209 fn memory_mut(&mut self) -> &mut dyn MemoryInterface<Self::ErrorType> {
210 self.inner.as_mut()
211 }
212}
213
214impl<'probe> Core<'probe> {
215 pub fn inner_mut(&mut self) -> &mut Box<dyn CoreInterface + 'probe> {
217 &mut self.inner
218 }
219
220 pub(crate) fn new(
222 id: usize,
223 name: &'probe str,
224 target: &'probe Target,
225 core: impl CoreInterface + 'probe,
226 ) -> Core<'probe> {
227 Self {
228 id,
229 name,
230 target,
231 inner: Box::new(core),
232 }
233 }
234
235 pub fn memory_regions(&self) -> impl Iterator<Item = &MemoryRegion> {
237 self.target
238 .memory_map
239 .iter()
240 .filter(|r| r.cores().iter().any(|m| m == self.name))
241 }
242
243 pub fn target(&self) -> &Target {
245 self.target
246 }
247
248 pub(crate) fn create_state(
250 id: usize,
251 options: CoreAccessOptions,
252 target: &Target,
253 core_type: CoreType,
254 ) -> CombinedCoreState {
255 CombinedCoreState {
256 id,
257 core_state: CoreState::new(ResolvedCoreOptions::new(target, options)),
258 specific_state: SpecificCoreState::from_core_type(core_type),
259 }
260 }
261
262 pub fn id(&self) -> usize {
264 self.id
265 }
266
267 #[tracing::instrument(skip(self))]
270 pub fn wait_for_core_halted(&mut self, timeout: Duration) -> Result<(), Error> {
271 self.inner.wait_for_core_halted(timeout)
272 }
273
274 pub fn core_halted(&mut self) -> Result<bool, Error> {
277 self.inner.core_halted()
278 }
279
280 #[tracing::instrument(skip(self))]
283 pub fn halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
284 self.inner.halt(timeout)
285 }
286
287 #[tracing::instrument(skip(self))]
289 pub fn run(&mut self) -> Result<(), Error> {
290 self.inner.run()
291 }
292
293 #[tracing::instrument(skip(self))]
298 pub fn reset(&mut self) -> Result<(), Error> {
299 self.inner.reset()
300 }
301
302 #[tracing::instrument(skip(self))]
307 pub fn reset_and_halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
308 self.inner.reset_and_halt(timeout)
309 }
310
311 #[tracing::instrument(skip(self))]
313 pub fn step(&mut self) -> Result<CoreInformation, Error> {
314 self.inner.step()
315 }
316
317 #[tracing::instrument(level = "trace", skip(self))]
319 pub fn status(&mut self) -> Result<CoreStatus, Error> {
320 self.inner.status()
321 }
322
323 #[tracing::instrument(skip(self, address), fields(address))]
338 pub fn read_core_reg<T>(
339 &mut self,
340 address: impl Into<registers::RegisterId>,
341 ) -> Result<T, Error>
342 where
343 registers::RegisterValue: TryInto<T>,
344 Result<T, <registers::RegisterValue as TryInto<T>>::Error>: RegisterValueResultExt<T>,
345 {
346 let address = address.into();
347
348 tracing::Span::current().record("address", format!("{address:?}"));
349
350 let value = self.inner.read_core_reg(address)?;
351
352 value.try_into().into_crate_error()
353 }
354
355 #[tracing::instrument(skip(self, address, value))]
361 pub fn write_core_reg<T>(
362 &mut self,
363 address: impl Into<registers::RegisterId>,
364 value: T,
365 ) -> Result<(), Error>
366 where
367 T: Into<registers::RegisterValue>,
368 {
369 let address = address.into();
370
371 self.inner.write_core_reg(address, value.into())
372 }
373
374 pub fn available_breakpoint_units(&mut self) -> Result<u32, Error> {
376 self.inner.available_breakpoint_units()
377 }
378
379 fn enable_breakpoints(&mut self, state: bool) -> Result<(), Error> {
381 self.inner.enable_breakpoints(state)
382 }
383
384 #[tracing::instrument(skip(self))]
386 pub fn debug_on_sw_breakpoint(&mut self, enabled: bool) -> Result<(), Error> {
387 self.inner.debug_on_sw_breakpoint(enabled)
388 }
389
390 pub fn registers(&self) -> &'static registers::CoreRegisters {
392 self.inner.registers()
393 }
394
395 pub fn program_counter(&self) -> &'static CoreRegister {
397 self.inner.program_counter()
398 }
399
400 pub fn frame_pointer(&self) -> &'static CoreRegister {
402 self.inner.frame_pointer()
403 }
404
405 pub fn stack_pointer(&self) -> &'static CoreRegister {
407 self.inner.stack_pointer()
408 }
409
410 pub fn return_address(&self) -> &'static CoreRegister {
412 self.inner.return_address()
413 }
414
415 #[tracing::instrument(skip(self))]
422 pub fn set_hw_breakpoint(&mut self, address: u64) -> Result<(), Error> {
423 if !self.inner.hw_breakpoints_enabled() {
424 self.enable_breakpoints(true)?;
425 }
426
427 let breakpoints = self.inner.hw_breakpoints()?;
429 let breakpoint_comparator_index =
430 match breakpoints.iter().position(|&bp| bp == Some(address)) {
431 Some(breakpoint_comparator_index) => breakpoint_comparator_index,
432 None => breakpoints
433 .iter()
434 .position(|bp| bp.is_none())
435 .ok_or_else(|| Error::Other("No available hardware breakpoints".to_string()))?,
436 };
437
438 tracing::debug!(
439 "Trying to set HW breakpoint #{} with comparator address {:#08x}",
440 breakpoint_comparator_index,
441 address
442 );
443
444 self.inner
446 .set_hw_breakpoint(breakpoint_comparator_index, address)
447 }
448
449 #[tracing::instrument(skip(self))]
456 pub fn set_hw_breakpoint_unit(&mut self, unit_index: usize, addr: u64) -> Result<(), Error> {
457 if !self.inner.hw_breakpoints_enabled() {
458 self.enable_breakpoints(true)?;
459 }
460
461 tracing::debug!(
462 "Trying to set HW breakpoint #{} with comparator address {:#08x}",
463 unit_index,
464 addr
465 );
466
467 self.inner.set_hw_breakpoint(unit_index, addr)
468 }
469
470 #[tracing::instrument(skip(self))]
474 pub fn clear_hw_breakpoint(&mut self, address: u64) -> Result<(), Error> {
475 let bp_position = self
476 .inner
477 .hw_breakpoints()?
478 .iter()
479 .position(|bp| *bp == Some(address));
480
481 tracing::debug!(
482 "Will clear HW breakpoint #{} with comparator address {:#08x}",
483 bp_position.unwrap_or(usize::MAX),
484 address
485 );
486
487 match bp_position {
488 Some(bp_position) => {
489 self.inner.clear_hw_breakpoint(bp_position)?;
490 Ok(())
491 }
492 None => Err(Error::Other(format!(
493 "No breakpoint found at address {:#010x}",
494 address
495 ))),
496 }
497 }
498
499 #[tracing::instrument(skip(self))]
505 pub fn clear_all_hw_breakpoints(&mut self) -> Result<(), Error> {
506 for breakpoint in (self.inner.hw_breakpoints()?).into_iter().flatten() {
507 self.clear_hw_breakpoint(breakpoint)?
508 }
509 Ok(())
510 }
511
512 pub fn architecture(&self) -> Architecture {
514 self.inner.architecture()
515 }
516
517 pub fn core_type(&self) -> CoreType {
519 self.inner.core_type()
520 }
521
522 pub fn instruction_set(&mut self) -> Result<InstructionSet, Error> {
526 self.inner.instruction_set()
527 }
528
529 pub fn fpu_support(&mut self) -> Result<bool, Error> {
533 self.inner.fpu_support()
534 }
535
536 pub fn floating_point_register_count(&mut self) -> Result<usize, Error> {
539 self.inner.floating_point_register_count()
540 }
541
542 pub(crate) fn reset_catch_set(&mut self) -> Result<(), Error> {
543 self.inner.reset_catch_set()
544 }
545
546 pub(crate) fn reset_catch_clear(&mut self) -> Result<(), Error> {
547 self.inner.reset_catch_clear()
548 }
549
550 pub(crate) fn debug_core_stop(&mut self) -> Result<(), Error> {
551 self.inner.debug_core_stop()
552 }
553
554 pub fn enable_vector_catch(&mut self, condition: VectorCatchCondition) -> Result<(), Error> {
556 self.inner.enable_vector_catch(condition)
557 }
558
559 pub fn disable_vector_catch(&mut self, condition: VectorCatchCondition) -> Result<(), Error> {
561 self.inner.disable_vector_catch(condition)
562 }
563
564 pub fn is_64_bit(&self) -> bool {
566 self.inner.is_64_bit()
567 }
568}
569
570impl CoreInterface for Core<'_> {
571 fn wait_for_core_halted(&mut self, timeout: Duration) -> Result<(), Error> {
572 self.wait_for_core_halted(timeout)
573 }
574
575 fn core_halted(&mut self) -> Result<bool, Error> {
576 self.core_halted()
577 }
578
579 fn status(&mut self) -> Result<CoreStatus, Error> {
580 self.status()
581 }
582
583 fn halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
584 self.halt(timeout)
585 }
586
587 fn run(&mut self) -> Result<(), Error> {
588 self.run()
589 }
590
591 fn reset(&mut self) -> Result<(), Error> {
592 self.reset()
593 }
594
595 fn reset_and_halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
596 self.reset_and_halt(timeout)
597 }
598
599 fn step(&mut self) -> Result<CoreInformation, Error> {
600 self.step()
601 }
602
603 fn read_core_reg(
604 &mut self,
605 address: registers::RegisterId,
606 ) -> Result<registers::RegisterValue, Error> {
607 self.read_core_reg(address)
608 }
609
610 fn write_core_reg(
611 &mut self,
612 address: registers::RegisterId,
613 value: registers::RegisterValue,
614 ) -> Result<(), Error> {
615 self.write_core_reg(address, value)
616 }
617
618 fn available_breakpoint_units(&mut self) -> Result<u32, Error> {
619 self.available_breakpoint_units()
620 }
621
622 fn hw_breakpoints(&mut self) -> Result<Vec<Option<u64>>, Error> {
623 self.inner.hw_breakpoints()
624 }
625
626 fn enable_breakpoints(&mut self, state: bool) -> Result<(), Error> {
627 self.enable_breakpoints(state)
628 }
629
630 fn set_hw_breakpoint(&mut self, unit_index: usize, addr: u64) -> Result<(), Error> {
631 self.set_hw_breakpoint_unit(unit_index, addr)
632 }
633
634 fn clear_hw_breakpoint(&mut self, unit_index: usize) -> Result<(), Error> {
635 self.inner.clear_hw_breakpoint(unit_index)?;
636 Ok(())
637 }
638
639 fn registers(&self) -> &'static registers::CoreRegisters {
640 self.registers()
641 }
642
643 fn program_counter(&self) -> &'static CoreRegister {
644 self.program_counter()
645 }
646
647 fn frame_pointer(&self) -> &'static CoreRegister {
648 self.frame_pointer()
649 }
650
651 fn stack_pointer(&self) -> &'static CoreRegister {
652 self.stack_pointer()
653 }
654
655 fn return_address(&self) -> &'static CoreRegister {
656 self.return_address()
657 }
658
659 fn hw_breakpoints_enabled(&self) -> bool {
660 self.inner.hw_breakpoints_enabled()
661 }
662
663 fn architecture(&self) -> Architecture {
664 self.architecture()
665 }
666
667 fn core_type(&self) -> CoreType {
668 self.core_type()
669 }
670
671 fn instruction_set(&mut self) -> Result<InstructionSet, Error> {
672 self.instruction_set()
673 }
674
675 fn fpu_support(&mut self) -> Result<bool, Error> {
676 self.fpu_support()
677 }
678
679 fn floating_point_register_count(&mut self) -> Result<usize, crate::error::Error> {
680 self.floating_point_register_count()
681 }
682
683 fn reset_catch_set(&mut self) -> Result<(), Error> {
684 self.reset_catch_set()
685 }
686
687 fn reset_catch_clear(&mut self) -> Result<(), Error> {
688 self.reset_catch_clear()
689 }
690
691 fn debug_core_stop(&mut self) -> Result<(), Error> {
692 self.debug_core_stop()
693 }
694
695 fn is_64_bit(&self) -> bool {
696 self.is_64_bit()
697 }
698}
699
700pub enum ResolvedCoreOptions {
701 Arm {
702 sequence: Arc<dyn ArmDebugSequence>,
703 options: ArmCoreAccessOptions,
704 },
705 Riscv {
706 sequence: Arc<dyn RiscvDebugSequence>,
707 options: RiscvCoreAccessOptions,
708 },
709 Xtensa {
710 sequence: Arc<dyn XtensaDebugSequence>,
711 options: XtensaCoreAccessOptions,
712 },
713}
714
715impl ResolvedCoreOptions {
716 fn new(target: &Target, options: CoreAccessOptions) -> Self {
717 match (options, target.debug_sequence.clone()) {
718 (CoreAccessOptions::Arm(options), DebugSequence::Arm(sequence)) => {
719 Self::Arm { sequence, options }
720 }
721 (CoreAccessOptions::Riscv(options), DebugSequence::Riscv(sequence)) => {
722 Self::Riscv { sequence, options }
723 }
724 (CoreAccessOptions::Xtensa(options), DebugSequence::Xtensa(sequence)) => {
725 Self::Xtensa { sequence, options }
726 }
727 _ => unreachable!(
728 "Mismatch between core kind and access options. This is a bug, please report it."
729 ),
730 }
731 }
732
733 fn interface_idx(&self) -> usize {
734 match self {
735 Self::Arm { options, .. } => options.jtag_tap.unwrap_or(0),
736 Self::Riscv { options, .. } => options.jtag_tap.unwrap_or(0),
737 Self::Xtensa { options, .. } => options.jtag_tap.unwrap_or(0),
738 }
739 }
740}
741
742impl std::fmt::Debug for ResolvedCoreOptions {
743 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
744 match self {
745 Self::Arm { options, .. } => f
746 .debug_struct("Arm")
747 .field("sequence", &"<ArmDebugSequence>")
748 .field("options", options)
749 .finish(),
750 Self::Riscv { options, .. } => f
751 .debug_struct("Riscv")
752 .field("sequence", &"<RiscvDebugSequence>")
753 .field("options", options)
754 .finish(),
755 Self::Xtensa { options, .. } => f
756 .debug_struct("Xtensa")
757 .field("sequence", &"<XtensaDebugSequence>")
758 .field("options", options)
759 .finish(),
760 }
761 }
762}