1use crate::{
2 CoreType, Endian, InstructionSet, MemoryInterface, Target,
3 architecture::{
4 arm::sequences::{ArmDebugSequence, DefaultArmSequence},
5 riscv::sequences::{DefaultRiscvSequence, RiscvDebugSequence},
6 xtensa::sequences::{DefaultXtensaSequence, XtensaDebugSequence},
7 },
8 config::DebugSequence,
9 error::{BreakpointError, Error},
10 memory::CoreMemoryInterface,
11};
12pub use probe_rs_target::{Architecture, CoreAccessOptions};
13use probe_rs_target::{
14 ArmCoreAccessOptions, MemoryRegion, RiscvCoreAccessOptions, XtensaCoreAccessOptions,
15};
16use std::{sync::Arc, time::Duration};
17
18pub mod core_state;
19pub mod core_status;
20#[cfg(feature = "coredump")]
21pub mod dump;
22pub mod memory_mapped_registers;
23pub mod registers;
24
25pub use core_state::*;
26pub use core_status::*;
27pub use memory_mapped_registers::MemoryMappedRegister;
28pub use registers::*;
29
30#[derive(Debug, Clone)]
32pub struct CoreInformation {
33 pub pc: u64,
35}
36
37pub trait CoreInterface: MemoryInterface {
39 fn wait_for_core_halted(&mut self, timeout: Duration) -> Result<(), Error>;
42
43 fn core_halted(&mut self) -> Result<bool, Error>;
46
47 fn status(&mut self) -> Result<CoreStatus, Error>;
49
50 fn halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error>;
53
54 fn run(&mut self) -> Result<(), Error>;
56
57 fn reset(&mut self) -> Result<(), Error>;
62
63 fn reset_and_halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error>;
68
69 fn step(&mut self) -> Result<CoreInformation, Error>;
71
72 fn read_core_reg(&mut self, address: RegisterId) -> Result<RegisterValue, Error>;
74
75 fn write_core_reg(&mut self, address: RegisterId, value: RegisterValue) -> Result<(), Error>;
77
78 fn available_breakpoint_units(&mut self) -> Result<u32, Error>;
80
81 fn hw_breakpoints(&mut self) -> Result<Vec<Option<u64>>, Error>;
85
86 fn enable_breakpoints(&mut self, state: bool) -> Result<(), Error>;
88
89 fn set_hw_breakpoint(&mut self, unit_index: usize, addr: u64) -> Result<(), Error>;
91
92 fn clear_hw_breakpoint(&mut self, unit_index: usize) -> Result<(), Error>;
94
95 fn registers(&self) -> &'static CoreRegisters;
97
98 fn program_counter(&self) -> &'static CoreRegister;
100
101 fn frame_pointer(&self) -> &'static CoreRegister;
103
104 fn stack_pointer(&self) -> &'static CoreRegister;
106
107 fn return_address(&self) -> &'static CoreRegister;
109
110 fn hw_breakpoints_enabled(&self) -> bool;
112
113 fn architecture(&self) -> Architecture;
115
116 fn core_type(&self) -> CoreType;
118
119 fn instruction_set(&mut self) -> Result<InstructionSet, Error>;
123
124 fn endianness(&mut self) -> Result<Endian, Error> {
127 Ok(Endian::Little)
129 }
130
131 fn fpu_support(&mut self) -> Result<bool, Error>;
135
136 fn floating_point_register_count(&mut self) -> Result<usize, Error>;
140
141 fn reset_catch_set(&mut self) -> Result<(), Error>;
147
148 fn reset_catch_clear(&mut self) -> Result<(), Error>;
152
153 fn debug_core_stop(&mut self) -> Result<(), Error>;
155
156 fn enable_vector_catch(&mut self, _condition: VectorCatchCondition) -> Result<(), Error> {
158 Err(Error::NotImplemented("vector catch"))
159 }
160
161 fn disable_vector_catch(&mut self, _condition: VectorCatchCondition) -> Result<(), Error> {
163 Err(Error::NotImplemented("vector catch"))
164 }
165
166 fn is_64_bit(&self) -> bool {
168 false
169 }
170
171 fn spill_registers(&mut self) -> Result<(), Error> {
173 Ok(())
176 }
177}
178
179pub struct Core<'probe> {
186 id: usize,
187 name: &'probe str,
188 target: &'probe Target,
189
190 inner: Box<dyn CoreInterface + 'probe>,
191}
192
193impl CoreMemoryInterface for Core<'_> {
194 type ErrorType = Error;
195
196 fn memory(&self) -> &dyn MemoryInterface<Self::ErrorType> {
197 self.inner.as_ref()
198 }
199
200 fn memory_mut(&mut self) -> &mut dyn MemoryInterface<Self::ErrorType> {
201 self.inner.as_mut()
202 }
203}
204
205impl<'probe> Core<'probe> {
206 pub fn inner_mut(&mut self) -> &mut Box<dyn CoreInterface + 'probe> {
208 &mut self.inner
209 }
210
211 pub(crate) fn new(
213 id: usize,
214 name: &'probe str,
215 target: &'probe Target,
216 core: impl CoreInterface + 'probe,
217 ) -> Core<'probe> {
218 Self {
219 id,
220 name,
221 target,
222 inner: Box::new(core),
223 }
224 }
225
226 pub fn memory_regions(&self) -> impl Iterator<Item = &MemoryRegion> {
228 self.target
229 .memory_map
230 .iter()
231 .filter(|r| r.cores().iter().any(|m| m == self.name))
232 }
233
234 pub fn target(&self) -> &Target {
236 self.target
237 }
238
239 pub(crate) fn create_state(
241 id: usize,
242 options: CoreAccessOptions,
243 target: &Target,
244 core_type: CoreType,
245 ) -> CombinedCoreState {
246 CombinedCoreState {
247 id,
248 core_state: CoreState::new(ResolvedCoreOptions::new(target, options)),
249 specific_state: SpecificCoreState::from_core_type(core_type),
250 }
251 }
252
253 pub fn id(&self) -> usize {
255 self.id
256 }
257
258 #[tracing::instrument(skip(self))]
261 pub fn wait_for_core_halted(&mut self, timeout: Duration) -> Result<(), Error> {
262 self.inner.wait_for_core_halted(timeout)
263 }
264
265 pub fn core_halted(&mut self) -> Result<bool, Error> {
268 self.inner.core_halted()
269 }
270
271 #[tracing::instrument(skip(self))]
274 pub fn halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
275 self.inner.halt(timeout)
276 }
277
278 #[tracing::instrument(skip(self))]
280 pub fn run(&mut self) -> Result<(), Error> {
281 self.inner.run()
282 }
283
284 #[tracing::instrument(skip(self))]
289 pub fn reset(&mut self) -> Result<(), Error> {
290 self.inner.reset()
291 }
292
293 #[tracing::instrument(skip(self))]
298 pub fn reset_and_halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
299 self.inner.reset_and_halt(timeout)
300 }
301
302 #[tracing::instrument(skip(self))]
304 pub fn step(&mut self) -> Result<CoreInformation, Error> {
305 self.inner.step()
306 }
307
308 #[tracing::instrument(level = "trace", skip(self))]
310 pub fn status(&mut self) -> Result<CoreStatus, Error> {
311 self.inner.status()
312 }
313
314 #[tracing::instrument(skip(self, address), fields(address))]
329 pub fn read_core_reg<T>(&mut self, address: impl Into<RegisterId>) -> Result<T, Error>
330 where
331 RegisterValue: TryInto<T>,
332 Result<T, <RegisterValue as TryInto<T>>::Error>: RegisterValueResultExt<T>,
333 {
334 let address = address.into();
335
336 tracing::Span::current().record("address", format!("{address:?}"));
337
338 let value = self.inner.read_core_reg(address)?;
339
340 value.try_into().into_crate_error()
341 }
342
343 #[tracing::instrument(skip(self, address, value))]
349 pub fn write_core_reg<T>(
350 &mut self,
351 address: impl Into<RegisterId>,
352 value: T,
353 ) -> Result<(), Error>
354 where
355 T: Into<RegisterValue>,
356 {
357 let address = address.into();
358
359 self.inner.write_core_reg(address, value.into())
360 }
361
362 pub fn available_breakpoint_units(&mut self) -> Result<u32, Error> {
364 self.inner.available_breakpoint_units()
365 }
366
367 fn enable_breakpoints(&mut self, state: bool) -> Result<(), Error> {
369 self.inner.enable_breakpoints(state)
370 }
371
372 pub fn registers(&self) -> &'static CoreRegisters {
374 self.inner.registers()
375 }
376
377 pub fn program_counter(&self) -> &'static CoreRegister {
379 self.inner.program_counter()
380 }
381
382 pub fn frame_pointer(&self) -> &'static CoreRegister {
384 self.inner.frame_pointer()
385 }
386
387 pub fn stack_pointer(&self) -> &'static CoreRegister {
389 self.inner.stack_pointer()
390 }
391
392 pub fn return_address(&self) -> &'static CoreRegister {
394 self.inner.return_address()
395 }
396
397 #[tracing::instrument(skip(self))]
404 pub fn set_hw_breakpoint(&mut self, address: u64) -> Result<(), Error> {
405 if !self.inner.hw_breakpoints_enabled() {
406 self.enable_breakpoints(true)?;
407 }
408
409 let breakpoints = self.inner.hw_breakpoints()?;
411 let breakpoint_comparator_index =
412 match breakpoints.iter().position(|&bp| bp == Some(address)) {
413 Some(breakpoint_comparator_index) => breakpoint_comparator_index,
414 None => breakpoints
415 .iter()
416 .position(|bp| bp.is_none())
417 .ok_or_else(|| Error::Other("No available hardware breakpoints".to_string()))?,
418 };
419
420 tracing::debug!(
421 "Trying to set HW breakpoint #{} with comparator address {:#08x}",
422 breakpoint_comparator_index,
423 address
424 );
425
426 self.inner
428 .set_hw_breakpoint(breakpoint_comparator_index, address)
429 }
430
431 #[tracing::instrument(skip(self))]
438 pub fn set_hw_breakpoint_unit(&mut self, unit_index: usize, addr: u64) -> Result<(), Error> {
439 if !self.inner.hw_breakpoints_enabled() {
440 self.enable_breakpoints(true)?;
441 }
442
443 tracing::debug!(
444 "Trying to set HW breakpoint #{} with comparator address {:#08x}",
445 unit_index,
446 addr
447 );
448
449 self.inner.set_hw_breakpoint(unit_index, addr)
450 }
451
452 #[tracing::instrument(skip(self))]
456 pub fn clear_hw_breakpoint(&mut self, address: u64) -> Result<(), Error> {
457 let bp_position = self
458 .inner
459 .hw_breakpoints()?
460 .iter()
461 .position(|bp| *bp == Some(address));
462
463 tracing::debug!(
464 "Will clear HW breakpoint #{} with comparator address {:#08x}",
465 bp_position.unwrap_or(usize::MAX),
466 address
467 );
468
469 match bp_position {
470 Some(bp_position) => {
471 self.inner.clear_hw_breakpoint(bp_position)?;
472 Ok(())
473 }
474 None => Err(Error::BreakpointOperation(BreakpointError::NotFound(
475 address,
476 ))),
477 }
478 }
479
480 #[tracing::instrument(skip(self))]
486 pub fn clear_all_hw_breakpoints(&mut self) -> Result<(), Error> {
487 for breakpoint in (self.inner.hw_breakpoints()?).into_iter().flatten() {
488 self.clear_hw_breakpoint(breakpoint)?
489 }
490 Ok(())
491 }
492
493 pub fn architecture(&self) -> Architecture {
495 self.inner.architecture()
496 }
497
498 pub fn core_type(&self) -> CoreType {
500 self.inner.core_type()
501 }
502
503 pub fn instruction_set(&mut self) -> Result<InstructionSet, Error> {
507 self.inner.instruction_set()
508 }
509
510 pub fn fpu_support(&mut self) -> Result<bool, Error> {
514 self.inner.fpu_support()
515 }
516
517 pub fn floating_point_register_count(&mut self) -> Result<usize, Error> {
520 self.inner.floating_point_register_count()
521 }
522
523 pub(crate) fn reset_catch_set(&mut self) -> Result<(), Error> {
524 self.inner.reset_catch_set()
525 }
526
527 pub(crate) fn reset_catch_clear(&mut self) -> Result<(), Error> {
528 self.inner.reset_catch_clear()
529 }
530
531 pub(crate) fn debug_core_stop(&mut self) -> Result<(), Error> {
532 self.inner.debug_core_stop()
533 }
534
535 pub fn enable_vector_catch(&mut self, condition: VectorCatchCondition) -> Result<(), Error> {
537 self.inner.enable_vector_catch(condition)
538 }
539
540 pub fn disable_vector_catch(&mut self, condition: VectorCatchCondition) -> Result<(), Error> {
542 self.inner.disable_vector_catch(condition)
543 }
544
545 pub fn is_64_bit(&self) -> bool {
547 self.inner.is_64_bit()
548 }
549
550 pub fn spill_registers(&mut self) -> Result<(), Error> {
552 self.inner.spill_registers()
553 }
554}
555
556impl CoreInterface for Core<'_> {
557 fn wait_for_core_halted(&mut self, timeout: Duration) -> Result<(), Error> {
558 self.wait_for_core_halted(timeout)
559 }
560
561 fn core_halted(&mut self) -> Result<bool, Error> {
562 self.core_halted()
563 }
564
565 fn status(&mut self) -> Result<CoreStatus, Error> {
566 self.status()
567 }
568
569 fn halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
570 self.halt(timeout)
571 }
572
573 fn run(&mut self) -> Result<(), Error> {
574 self.run()
575 }
576
577 fn reset(&mut self) -> Result<(), Error> {
578 self.reset()
579 }
580
581 fn reset_and_halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
582 self.reset_and_halt(timeout)
583 }
584
585 fn step(&mut self) -> Result<CoreInformation, Error> {
586 self.step()
587 }
588
589 fn read_core_reg(&mut self, address: RegisterId) -> Result<RegisterValue, Error> {
590 self.read_core_reg(address)
591 }
592
593 fn write_core_reg(&mut self, address: RegisterId, value: RegisterValue) -> Result<(), Error> {
594 self.write_core_reg(address, value)
595 }
596
597 fn available_breakpoint_units(&mut self) -> Result<u32, Error> {
598 self.available_breakpoint_units()
599 }
600
601 fn hw_breakpoints(&mut self) -> Result<Vec<Option<u64>>, Error> {
602 self.inner.hw_breakpoints()
603 }
604
605 fn enable_breakpoints(&mut self, state: bool) -> Result<(), Error> {
606 self.enable_breakpoints(state)
607 }
608
609 fn set_hw_breakpoint(&mut self, unit_index: usize, addr: u64) -> Result<(), Error> {
610 self.set_hw_breakpoint_unit(unit_index, addr)
611 }
612
613 fn clear_hw_breakpoint(&mut self, unit_index: usize) -> Result<(), Error> {
614 self.inner.clear_hw_breakpoint(unit_index)?;
615 Ok(())
616 }
617
618 fn registers(&self) -> &'static CoreRegisters {
619 self.registers()
620 }
621
622 fn program_counter(&self) -> &'static CoreRegister {
623 self.program_counter()
624 }
625
626 fn frame_pointer(&self) -> &'static CoreRegister {
627 self.frame_pointer()
628 }
629
630 fn stack_pointer(&self) -> &'static CoreRegister {
631 self.stack_pointer()
632 }
633
634 fn return_address(&self) -> &'static CoreRegister {
635 self.return_address()
636 }
637
638 fn hw_breakpoints_enabled(&self) -> bool {
639 self.inner.hw_breakpoints_enabled()
640 }
641
642 fn architecture(&self) -> Architecture {
643 self.architecture()
644 }
645
646 fn core_type(&self) -> CoreType {
647 self.core_type()
648 }
649
650 fn endianness(&mut self) -> Result<Endian, Error> {
653 self.inner.endianness()
654 }
655
656 fn instruction_set(&mut self) -> Result<InstructionSet, Error> {
657 self.instruction_set()
658 }
659
660 fn fpu_support(&mut self) -> Result<bool, Error> {
661 self.fpu_support()
662 }
663
664 fn floating_point_register_count(&mut self) -> Result<usize, crate::error::Error> {
665 self.floating_point_register_count()
666 }
667
668 fn reset_catch_set(&mut self) -> Result<(), Error> {
669 self.reset_catch_set()
670 }
671
672 fn reset_catch_clear(&mut self) -> Result<(), Error> {
673 self.reset_catch_clear()
674 }
675
676 fn debug_core_stop(&mut self) -> Result<(), Error> {
677 self.debug_core_stop()
678 }
679
680 fn is_64_bit(&self) -> bool {
681 self.is_64_bit()
682 }
683
684 fn spill_registers(&mut self) -> Result<(), Error> {
685 self.spill_registers()
686 }
687}
688
689pub enum ResolvedCoreOptions {
690 Arm {
691 sequence: Arc<dyn ArmDebugSequence>,
692 options: ArmCoreAccessOptions,
693 },
694 Riscv {
695 sequence: Arc<dyn RiscvDebugSequence>,
696 options: RiscvCoreAccessOptions,
697 },
698 Xtensa {
699 sequence: Arc<dyn XtensaDebugSequence>,
700 options: XtensaCoreAccessOptions,
701 },
702}
703
704impl ResolvedCoreOptions {
705 fn new(target: &Target, options: CoreAccessOptions) -> Self {
706 match options {
710 CoreAccessOptions::Arm(options) => {
711 let sequence = match &target.debug_sequence {
712 DebugSequence::Arm(s) => s.clone(),
713 _ => DefaultArmSequence::create(),
714 };
715 Self::Arm { sequence, options }
716 }
717 CoreAccessOptions::Riscv(options) => {
718 let sequence = match &target.debug_sequence {
719 DebugSequence::Riscv(s) => s.clone(),
720 _ => DefaultRiscvSequence::create(),
721 };
722 Self::Riscv { sequence, options }
723 }
724 CoreAccessOptions::Xtensa(options) => {
725 let sequence = match &target.debug_sequence {
726 DebugSequence::Xtensa(s) => s.clone(),
727 _ => DefaultXtensaSequence::create(),
728 };
729 Self::Xtensa { sequence, options }
730 }
731 }
732 }
733
734 fn jtag_tap_index(&self) -> usize {
735 match self {
736 Self::Arm { options, .. } => options.jtag_tap.unwrap_or(0),
737 Self::Riscv { options, .. } => options.jtag_tap.unwrap_or(0),
738 Self::Xtensa { options, .. } => options.jtag_tap.unwrap_or(0),
739 }
740 }
741}
742
743impl std::fmt::Debug for ResolvedCoreOptions {
744 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
745 match self {
746 Self::Arm { options, .. } => f
747 .debug_struct("Arm")
748 .field("sequence", &"<ArmDebugSequence>")
749 .field("options", options)
750 .finish(),
751 Self::Riscv { options, .. } => f
752 .debug_struct("Riscv")
753 .field("sequence", &"<RiscvDebugSequence>")
754 .field("options", options)
755 .finish(),
756 Self::Xtensa { options, .. } => f
757 .debug_struct("Xtensa")
758 .field("sequence", &"<XtensaDebugSequence>")
759 .field("options", options)
760 .finish(),
761 }
762 }
763}