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::{BreakpointError, 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(&mut self, address: RegisterId) -> Result<RegisterValue, Error>;
72
73 fn write_core_reg(&mut self, address: RegisterId, value: RegisterValue) -> Result<(), Error>;
75
76 fn available_breakpoint_units(&mut self) -> Result<u32, Error>;
78
79 fn hw_breakpoints(&mut self) -> Result<Vec<Option<u64>>, Error>;
83
84 fn enable_breakpoints(&mut self, state: bool) -> Result<(), Error>;
86
87 fn set_hw_breakpoint(&mut self, unit_index: usize, addr: u64) -> Result<(), Error>;
89
90 fn clear_hw_breakpoint(&mut self, unit_index: usize) -> Result<(), Error>;
92
93 fn registers(&self) -> &'static CoreRegisters;
95
96 fn program_counter(&self) -> &'static CoreRegister;
98
99 fn frame_pointer(&self) -> &'static CoreRegister;
101
102 fn stack_pointer(&self) -> &'static CoreRegister;
104
105 fn return_address(&self) -> &'static CoreRegister;
107
108 fn hw_breakpoints_enabled(&self) -> bool;
110
111 fn architecture(&self) -> Architecture;
113
114 fn core_type(&self) -> CoreType;
116
117 fn instruction_set(&mut self) -> Result<InstructionSet, Error>;
121
122 fn endianness(&mut self) -> Result<Endian, Error> {
125 Ok(Endian::Little)
127 }
128
129 fn fpu_support(&mut self) -> Result<bool, Error>;
133
134 fn floating_point_register_count(&mut self) -> Result<usize, Error>;
138
139 fn reset_catch_set(&mut self) -> Result<(), Error>;
145
146 fn reset_catch_clear(&mut self) -> Result<(), Error>;
150
151 fn debug_core_stop(&mut self) -> Result<(), Error>;
153
154 fn enable_vector_catch(&mut self, _condition: VectorCatchCondition) -> Result<(), Error> {
156 Err(Error::NotImplemented("vector catch"))
157 }
158
159 fn disable_vector_catch(&mut self, _condition: VectorCatchCondition) -> Result<(), Error> {
161 Err(Error::NotImplemented("vector catch"))
162 }
163
164 fn is_64_bit(&self) -> bool {
166 false
167 }
168
169 fn spill_registers(&mut self) -> Result<(), Error> {
171 Ok(())
174 }
175}
176
177pub struct Core<'probe> {
184 id: usize,
185 name: &'probe str,
186 target: &'probe Target,
187
188 inner: Box<dyn CoreInterface + 'probe>,
189}
190
191impl CoreMemoryInterface for Core<'_> {
192 type ErrorType = Error;
193
194 fn memory(&self) -> &dyn MemoryInterface<Self::ErrorType> {
195 self.inner.as_ref()
196 }
197
198 fn memory_mut(&mut self) -> &mut dyn MemoryInterface<Self::ErrorType> {
199 self.inner.as_mut()
200 }
201}
202
203impl<'probe> Core<'probe> {
204 pub fn inner_mut(&mut self) -> &mut Box<dyn CoreInterface + 'probe> {
206 &mut self.inner
207 }
208
209 pub(crate) fn new(
211 id: usize,
212 name: &'probe str,
213 target: &'probe Target,
214 core: impl CoreInterface + 'probe,
215 ) -> Core<'probe> {
216 Self {
217 id,
218 name,
219 target,
220 inner: Box::new(core),
221 }
222 }
223
224 pub fn memory_regions(&self) -> impl Iterator<Item = &MemoryRegion> {
226 self.target
227 .memory_map
228 .iter()
229 .filter(|r| r.cores().iter().any(|m| m == self.name))
230 }
231
232 pub fn target(&self) -> &Target {
234 self.target
235 }
236
237 pub(crate) fn create_state(
239 id: usize,
240 options: CoreAccessOptions,
241 target: &Target,
242 core_type: CoreType,
243 ) -> CombinedCoreState {
244 CombinedCoreState {
245 id,
246 core_state: CoreState::new(ResolvedCoreOptions::new(target, options)),
247 specific_state: SpecificCoreState::from_core_type(core_type),
248 }
249 }
250
251 pub fn id(&self) -> usize {
253 self.id
254 }
255
256 #[tracing::instrument(skip(self))]
259 pub fn wait_for_core_halted(&mut self, timeout: Duration) -> Result<(), Error> {
260 self.inner.wait_for_core_halted(timeout)
261 }
262
263 pub fn core_halted(&mut self) -> Result<bool, Error> {
266 self.inner.core_halted()
267 }
268
269 #[tracing::instrument(skip(self))]
272 pub fn halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
273 self.inner.halt(timeout)
274 }
275
276 #[tracing::instrument(skip(self))]
278 pub fn run(&mut self) -> Result<(), Error> {
279 self.inner.run()
280 }
281
282 #[tracing::instrument(skip(self))]
287 pub fn reset(&mut self) -> Result<(), Error> {
288 self.inner.reset()
289 }
290
291 #[tracing::instrument(skip(self))]
296 pub fn reset_and_halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
297 self.inner.reset_and_halt(timeout)
298 }
299
300 #[tracing::instrument(skip(self))]
302 pub fn step(&mut self) -> Result<CoreInformation, Error> {
303 self.inner.step()
304 }
305
306 #[tracing::instrument(level = "trace", skip(self))]
308 pub fn status(&mut self) -> Result<CoreStatus, Error> {
309 self.inner.status()
310 }
311
312 #[tracing::instrument(skip(self, address), fields(address))]
327 pub fn read_core_reg<T>(&mut self, address: impl Into<RegisterId>) -> Result<T, Error>
328 where
329 RegisterValue: TryInto<T>,
330 Result<T, <RegisterValue as TryInto<T>>::Error>: RegisterValueResultExt<T>,
331 {
332 let address = address.into();
333
334 tracing::Span::current().record("address", format!("{address:?}"));
335
336 let value = self.inner.read_core_reg(address)?;
337
338 value.try_into().into_crate_error()
339 }
340
341 #[tracing::instrument(skip(self, address, value))]
347 pub fn write_core_reg<T>(
348 &mut self,
349 address: impl Into<RegisterId>,
350 value: T,
351 ) -> Result<(), Error>
352 where
353 T: Into<RegisterValue>,
354 {
355 let address = address.into();
356
357 self.inner.write_core_reg(address, value.into())
358 }
359
360 pub fn available_breakpoint_units(&mut self) -> Result<u32, Error> {
362 self.inner.available_breakpoint_units()
363 }
364
365 fn enable_breakpoints(&mut self, state: bool) -> Result<(), Error> {
367 self.inner.enable_breakpoints(state)
368 }
369
370 pub fn registers(&self) -> &'static CoreRegisters {
372 self.inner.registers()
373 }
374
375 pub fn program_counter(&self) -> &'static CoreRegister {
377 self.inner.program_counter()
378 }
379
380 pub fn frame_pointer(&self) -> &'static CoreRegister {
382 self.inner.frame_pointer()
383 }
384
385 pub fn stack_pointer(&self) -> &'static CoreRegister {
387 self.inner.stack_pointer()
388 }
389
390 pub fn return_address(&self) -> &'static CoreRegister {
392 self.inner.return_address()
393 }
394
395 #[tracing::instrument(skip(self))]
402 pub fn set_hw_breakpoint(&mut self, address: u64) -> Result<(), Error> {
403 if !self.inner.hw_breakpoints_enabled() {
404 self.enable_breakpoints(true)?;
405 }
406
407 let breakpoints = self.inner.hw_breakpoints()?;
409 let breakpoint_comparator_index =
410 match breakpoints.iter().position(|&bp| bp == Some(address)) {
411 Some(breakpoint_comparator_index) => breakpoint_comparator_index,
412 None => breakpoints
413 .iter()
414 .position(|bp| bp.is_none())
415 .ok_or_else(|| Error::Other("No available hardware breakpoints".to_string()))?,
416 };
417
418 tracing::debug!(
419 "Trying to set HW breakpoint #{} with comparator address {:#08x}",
420 breakpoint_comparator_index,
421 address
422 );
423
424 self.inner
426 .set_hw_breakpoint(breakpoint_comparator_index, address)
427 }
428
429 #[tracing::instrument(skip(self))]
436 pub fn set_hw_breakpoint_unit(&mut self, unit_index: usize, addr: u64) -> Result<(), Error> {
437 if !self.inner.hw_breakpoints_enabled() {
438 self.enable_breakpoints(true)?;
439 }
440
441 tracing::debug!(
442 "Trying to set HW breakpoint #{} with comparator address {:#08x}",
443 unit_index,
444 addr
445 );
446
447 self.inner.set_hw_breakpoint(unit_index, addr)
448 }
449
450 #[tracing::instrument(skip(self))]
454 pub fn clear_hw_breakpoint(&mut self, address: u64) -> Result<(), Error> {
455 let bp_position = self
456 .inner
457 .hw_breakpoints()?
458 .iter()
459 .position(|bp| *bp == Some(address));
460
461 tracing::debug!(
462 "Will clear HW breakpoint #{} with comparator address {:#08x}",
463 bp_position.unwrap_or(usize::MAX),
464 address
465 );
466
467 match bp_position {
468 Some(bp_position) => {
469 self.inner.clear_hw_breakpoint(bp_position)?;
470 Ok(())
471 }
472 None => Err(Error::BreakpointOperation(BreakpointError::NotFound(
473 address,
474 ))),
475 }
476 }
477
478 #[tracing::instrument(skip(self))]
484 pub fn clear_all_hw_breakpoints(&mut self) -> Result<(), Error> {
485 for breakpoint in (self.inner.hw_breakpoints()?).into_iter().flatten() {
486 self.clear_hw_breakpoint(breakpoint)?
487 }
488 Ok(())
489 }
490
491 pub fn architecture(&self) -> Architecture {
493 self.inner.architecture()
494 }
495
496 pub fn core_type(&self) -> CoreType {
498 self.inner.core_type()
499 }
500
501 pub fn instruction_set(&mut self) -> Result<InstructionSet, Error> {
505 self.inner.instruction_set()
506 }
507
508 pub fn fpu_support(&mut self) -> Result<bool, Error> {
512 self.inner.fpu_support()
513 }
514
515 pub fn floating_point_register_count(&mut self) -> Result<usize, Error> {
518 self.inner.floating_point_register_count()
519 }
520
521 pub(crate) fn reset_catch_set(&mut self) -> Result<(), Error> {
522 self.inner.reset_catch_set()
523 }
524
525 pub(crate) fn reset_catch_clear(&mut self) -> Result<(), Error> {
526 self.inner.reset_catch_clear()
527 }
528
529 pub(crate) fn debug_core_stop(&mut self) -> Result<(), Error> {
530 self.inner.debug_core_stop()
531 }
532
533 pub fn enable_vector_catch(&mut self, condition: VectorCatchCondition) -> Result<(), Error> {
535 self.inner.enable_vector_catch(condition)
536 }
537
538 pub fn disable_vector_catch(&mut self, condition: VectorCatchCondition) -> Result<(), Error> {
540 self.inner.disable_vector_catch(condition)
541 }
542
543 pub fn is_64_bit(&self) -> bool {
545 self.inner.is_64_bit()
546 }
547
548 pub fn spill_registers(&mut self) -> Result<(), Error> {
550 self.inner.spill_registers()
551 }
552}
553
554impl CoreInterface for Core<'_> {
555 fn wait_for_core_halted(&mut self, timeout: Duration) -> Result<(), Error> {
556 self.wait_for_core_halted(timeout)
557 }
558
559 fn core_halted(&mut self) -> Result<bool, Error> {
560 self.core_halted()
561 }
562
563 fn status(&mut self) -> Result<CoreStatus, Error> {
564 self.status()
565 }
566
567 fn halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
568 self.halt(timeout)
569 }
570
571 fn run(&mut self) -> Result<(), Error> {
572 self.run()
573 }
574
575 fn reset(&mut self) -> Result<(), Error> {
576 self.reset()
577 }
578
579 fn reset_and_halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
580 self.reset_and_halt(timeout)
581 }
582
583 fn step(&mut self) -> Result<CoreInformation, Error> {
584 self.step()
585 }
586
587 fn read_core_reg(&mut self, address: RegisterId) -> Result<RegisterValue, Error> {
588 self.read_core_reg(address)
589 }
590
591 fn write_core_reg(&mut self, address: RegisterId, value: RegisterValue) -> Result<(), Error> {
592 self.write_core_reg(address, value)
593 }
594
595 fn available_breakpoint_units(&mut self) -> Result<u32, Error> {
596 self.available_breakpoint_units()
597 }
598
599 fn hw_breakpoints(&mut self) -> Result<Vec<Option<u64>>, Error> {
600 self.inner.hw_breakpoints()
601 }
602
603 fn enable_breakpoints(&mut self, state: bool) -> Result<(), Error> {
604 self.enable_breakpoints(state)
605 }
606
607 fn set_hw_breakpoint(&mut self, unit_index: usize, addr: u64) -> Result<(), Error> {
608 self.set_hw_breakpoint_unit(unit_index, addr)
609 }
610
611 fn clear_hw_breakpoint(&mut self, unit_index: usize) -> Result<(), Error> {
612 self.inner.clear_hw_breakpoint(unit_index)?;
613 Ok(())
614 }
615
616 fn registers(&self) -> &'static CoreRegisters {
617 self.registers()
618 }
619
620 fn program_counter(&self) -> &'static CoreRegister {
621 self.program_counter()
622 }
623
624 fn frame_pointer(&self) -> &'static CoreRegister {
625 self.frame_pointer()
626 }
627
628 fn stack_pointer(&self) -> &'static CoreRegister {
629 self.stack_pointer()
630 }
631
632 fn return_address(&self) -> &'static CoreRegister {
633 self.return_address()
634 }
635
636 fn hw_breakpoints_enabled(&self) -> bool {
637 self.inner.hw_breakpoints_enabled()
638 }
639
640 fn architecture(&self) -> Architecture {
641 self.architecture()
642 }
643
644 fn core_type(&self) -> CoreType {
645 self.core_type()
646 }
647
648 fn endianness(&mut self) -> Result<Endian, Error> {
651 self.inner.endianness()
652 }
653
654 fn instruction_set(&mut self) -> Result<InstructionSet, Error> {
655 self.instruction_set()
656 }
657
658 fn fpu_support(&mut self) -> Result<bool, Error> {
659 self.fpu_support()
660 }
661
662 fn floating_point_register_count(&mut self) -> Result<usize, crate::error::Error> {
663 self.floating_point_register_count()
664 }
665
666 fn reset_catch_set(&mut self) -> Result<(), Error> {
667 self.reset_catch_set()
668 }
669
670 fn reset_catch_clear(&mut self) -> Result<(), Error> {
671 self.reset_catch_clear()
672 }
673
674 fn debug_core_stop(&mut self) -> Result<(), Error> {
675 self.debug_core_stop()
676 }
677
678 fn is_64_bit(&self) -> bool {
679 self.is_64_bit()
680 }
681
682 fn spill_registers(&mut self) -> Result<(), Error> {
683 self.spill_registers()
684 }
685}
686
687pub enum ResolvedCoreOptions {
688 Arm {
689 sequence: Arc<dyn ArmDebugSequence>,
690 options: ArmCoreAccessOptions,
691 },
692 Riscv {
693 sequence: Arc<dyn RiscvDebugSequence>,
694 options: RiscvCoreAccessOptions,
695 },
696 Xtensa {
697 sequence: Arc<dyn XtensaDebugSequence>,
698 options: XtensaCoreAccessOptions,
699 },
700}
701
702impl ResolvedCoreOptions {
703 fn new(target: &Target, options: CoreAccessOptions) -> Self {
704 match (options, target.debug_sequence.clone()) {
705 (CoreAccessOptions::Arm(options), DebugSequence::Arm(sequence)) => {
706 Self::Arm { sequence, options }
707 }
708 (CoreAccessOptions::Riscv(options), DebugSequence::Riscv(sequence)) => {
709 Self::Riscv { sequence, options }
710 }
711 (CoreAccessOptions::Xtensa(options), DebugSequence::Xtensa(sequence)) => {
712 Self::Xtensa { sequence, options }
713 }
714 _ => unreachable!(
715 "Mismatch between core kind and access options. This is a bug, please report it."
716 ),
717 }
718 }
719
720 fn jtag_tap_index(&self) -> usize {
721 match self {
722 Self::Arm { options, .. } => options.jtag_tap.unwrap_or(0),
723 Self::Riscv { options, .. } => options.jtag_tap.unwrap_or(0),
724 Self::Xtensa { options, .. } => options.jtag_tap.unwrap_or(0),
725 }
726 }
727}
728
729impl std::fmt::Debug for ResolvedCoreOptions {
730 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
731 match self {
732 Self::Arm { options, .. } => f
733 .debug_struct("Arm")
734 .field("sequence", &"<ArmDebugSequence>")
735 .field("options", options)
736 .finish(),
737 Self::Riscv { options, .. } => f
738 .debug_struct("Riscv")
739 .field("sequence", &"<RiscvDebugSequence>")
740 .field("options", options)
741 .finish(),
742 Self::Xtensa { options, .. } => f
743 .debug_struct("Xtensa")
744 .field("sequence", &"<XtensaDebugSequence>")
745 .field("options", options)
746 .finish(),
747 }
748 }
749}