probe_rs/core/
core_state.rs

1use crate::{
2    Core, CoreType, Error, Target,
3    architecture::{
4        arm::{
5            ApV2Address, ArmDebugInterface, FullyQualifiedApAddress,
6            core::{CortexAState, CortexMState},
7            dp::DpAddress,
8        },
9        riscv::{RiscvCoreState, communication_interface::RiscvCommunicationInterface},
10        xtensa::{XtensaCoreState, communication_interface::XtensaCommunicationInterface},
11    },
12};
13
14use super::ResolvedCoreOptions;
15
16#[derive(Debug)]
17pub(crate) struct CombinedCoreState {
18    pub(crate) core_state: CoreState,
19
20    pub(crate) specific_state: SpecificCoreState,
21
22    pub(crate) id: usize,
23}
24
25impl CombinedCoreState {
26    pub fn id(&self) -> usize {
27        self.id
28    }
29
30    pub fn core_type(&self) -> CoreType {
31        self.specific_state.core_type()
32    }
33
34    pub fn jtag_tap_index(&self) -> usize {
35        self.core_state.core_access_options.jtag_tap_index()
36    }
37
38    pub(crate) fn attach_arm<'probe>(
39        &'probe mut self,
40        target: &'probe Target,
41        arm_interface: &'probe mut Box<dyn ArmDebugInterface>,
42    ) -> Result<Core<'probe>, Error> {
43        let name = &target.cores[self.id].name;
44
45        let memory = arm_interface.memory_interface(&self.arm_memory_ap())?;
46
47        let ResolvedCoreOptions::Arm { options, sequence } = &self.core_state.core_access_options
48        else {
49            unreachable!(
50                "The stored core state is not compatible with the ARM architecture. \
51                This should never happen. Please file a bug if it does."
52            );
53        };
54        let debug_sequence = sequence.clone();
55
56        Ok(match &mut self.specific_state {
57            SpecificCoreState::Armv6m(s) => Core::new(
58                self.id,
59                name,
60                target,
61                crate::architecture::arm::armv6m::Armv6m::new(memory, s, debug_sequence)?,
62            ),
63            SpecificCoreState::Armv7a(s) => Core::new(
64                self.id,
65                name,
66                target,
67                crate::architecture::arm::armv7a::Armv7a::new(
68                    memory,
69                    s,
70                    options.debug_base.expect("base_address not specified"),
71                    debug_sequence,
72                )?,
73            ),
74            SpecificCoreState::Armv7m(s) | SpecificCoreState::Armv7em(s) => Core::new(
75                self.id,
76                name,
77                target,
78                crate::architecture::arm::armv7m::Armv7m::new(memory, s, debug_sequence)?,
79            ),
80            SpecificCoreState::Armv8a(s) => Core::new(
81                self.id,
82                name,
83                target,
84                crate::architecture::arm::armv8a::Armv8a::new(
85                    memory,
86                    s,
87                    options.debug_base.expect("base_address not specified"),
88                    options.cti_base.expect("cti_address not specified"),
89                    debug_sequence,
90                )?,
91            ),
92            SpecificCoreState::Armv8m(s) => Core::new(
93                self.id,
94                name,
95                target,
96                crate::architecture::arm::armv8m::Armv8m::new(memory, s, debug_sequence)?,
97            ),
98            _ => {
99                unreachable!(
100                    "The stored core state is not compatible with the ARM architecture. \
101                    This should never happen. Please file a bug if it does."
102                );
103            }
104        })
105    }
106
107    pub(crate) fn enable_arm_debug(
108        &self,
109        interface: &mut dyn ArmDebugInterface,
110    ) -> Result<(), Error> {
111        let ResolvedCoreOptions::Arm { sequence, options } = &self.core_state.core_access_options
112        else {
113            unreachable!(
114                "The stored core state is not compatible with the ARM architecture. \
115                This should never happen. Please file a bug if it does."
116            );
117        };
118
119        tracing::debug_span!("debug_core_start", id = self.id()).in_scope(|| {
120            // Enable debug mode
121            sequence.debug_core_start(
122                interface,
123                &self.arm_memory_ap(),
124                self.core_type(),
125                options.debug_base,
126                options.cti_base,
127            )
128        })?;
129
130        Ok(())
131    }
132
133    pub(crate) fn arm_reset_catch_set(
134        &self,
135        interface: &mut dyn ArmDebugInterface,
136    ) -> Result<(), Error> {
137        let ResolvedCoreOptions::Arm { sequence, options } = &self.core_state.core_access_options
138        else {
139            unreachable!(
140                "The stored core state is not compatible with the ARM architecture. \
141                This should never happen. Please file a bug if it does."
142            );
143        };
144
145        let mut memory_interface = interface.memory_interface(&self.arm_memory_ap())?;
146
147        let reset_catch_span = tracing::debug_span!("reset_catch_set", id = self.id()).entered();
148        sequence.reset_catch_set(&mut *memory_interface, self.core_type(), options.debug_base)?;
149
150        drop(reset_catch_span);
151
152        Ok(())
153    }
154
155    pub(crate) fn attach_riscv<'probe>(
156        &'probe mut self,
157        target: &'probe Target,
158        mut interface: RiscvCommunicationInterface<'probe>,
159    ) -> Result<Core<'probe>, Error> {
160        let name = &target.cores[self.id].name;
161
162        let ResolvedCoreOptions::Riscv { options, sequence } = &self.core_state.core_access_options
163        else {
164            unreachable!(
165                "The stored core state is not compatible with the RISC-V architecture. \
166                This should never happen. Please file a bug if it does."
167            );
168        };
169        let debug_sequence = sequence.clone();
170
171        let SpecificCoreState::Riscv(s) = &mut self.specific_state else {
172            unreachable!(
173                "The stored core state is not compatible with the RISC-V architecture. \
174                This should never happen. Please file a bug if it does."
175            );
176        };
177
178        let hart = options.hart_id.unwrap_or_default();
179        interface.select_hart(hart)?;
180
181        Ok(Core::new(
182            self.id,
183            name,
184            target,
185            crate::architecture::riscv::Riscv32::new(interface, s, debug_sequence)?,
186        ))
187    }
188
189    pub(crate) fn attach_xtensa<'probe>(
190        &'probe mut self,
191        target: &'probe Target,
192        interface: XtensaCommunicationInterface<'probe>,
193    ) -> Result<Core<'probe>, Error> {
194        let name = &target.cores[self.id].name;
195
196        let ResolvedCoreOptions::Xtensa { sequence, .. } = &self.core_state.core_access_options
197        else {
198            unreachable!(
199                "The stored core state is not compatible with the Xtensa architecture. \
200                This should never happen. Please file a bug if it does."
201            );
202        };
203        let debug_sequence = sequence.clone();
204
205        let SpecificCoreState::Xtensa(s) = &mut self.specific_state else {
206            unreachable!(
207                "The stored core state is not compatible with the Xtensa architecture. \
208                This should never happen. Please file a bug if it does."
209            );
210        };
211
212        Ok(Core::new(
213            self.id,
214            name,
215            target,
216            crate::architecture::xtensa::Xtensa::new(interface, s, debug_sequence)?,
217        ))
218    }
219
220    /// Get the memory AP for this core.
221    ///
222    /// ## Panic
223    ///
224    /// This function will panic if the core is not an ARM core and doesn't have a memory AP
225    pub(crate) fn arm_memory_ap(&self) -> FullyQualifiedApAddress {
226        self.core_state.memory_ap()
227    }
228}
229
230/// A generic core state which caches the generic parts of the core state.
231#[derive(Debug)]
232pub struct CoreState {
233    /// Information needed to access the core
234    core_access_options: ResolvedCoreOptions,
235}
236
237impl CoreState {
238    /// Creates a new core state from the core ID.
239    pub fn new(core_access_options: ResolvedCoreOptions) -> Self {
240        Self {
241            core_access_options,
242        }
243    }
244
245    pub(crate) fn memory_ap(&self) -> FullyQualifiedApAddress {
246        let ResolvedCoreOptions::Arm { options, .. } = &self.core_access_options else {
247            unreachable!(
248                "The stored core state is not compatible with the ARM architecture. \
249                This should never happen. Please file a bug if it does."
250            );
251        };
252
253        let dp = match options.targetsel {
254            None => DpAddress::Default,
255            Some(x) => DpAddress::Multidrop(x),
256        };
257        match &options.ap {
258            probe_rs_target::ApAddress::V1(ap) => FullyQualifiedApAddress::v1_with_dp(dp, *ap),
259            probe_rs_target::ApAddress::V2(ap) => {
260                FullyQualifiedApAddress::v2_with_dp(dp, ApV2Address::new(*ap))
261            }
262        }
263    }
264}
265
266/// The architecture specific core state.
267#[derive(Debug)]
268pub enum SpecificCoreState {
269    /// The state of an ARMv6-M core.
270    Armv6m(CortexMState),
271    /// The state of an ARMv7-A core.
272    Armv7a(CortexAState),
273    /// The state of an ARMv7-M core.
274    Armv7m(CortexMState),
275    /// The state of an ARMv7-EM core.
276    Armv7em(CortexMState),
277    /// The state of an ARMv8-A core.
278    Armv8a(CortexAState),
279    /// The state of an ARMv8-M core.
280    Armv8m(CortexMState),
281    /// The state of an RISC-V core.
282    Riscv(RiscvCoreState),
283    /// The state of an Xtensa core.
284    Xtensa(XtensaCoreState),
285}
286
287impl SpecificCoreState {
288    pub(crate) fn from_core_type(typ: CoreType) -> Self {
289        match typ {
290            CoreType::Armv6m => SpecificCoreState::Armv6m(CortexMState::new()),
291            CoreType::Armv7a => SpecificCoreState::Armv7a(CortexAState::new()),
292            CoreType::Armv7m => SpecificCoreState::Armv7m(CortexMState::new()),
293            CoreType::Armv7em => SpecificCoreState::Armv7m(CortexMState::new()),
294            CoreType::Armv8a => SpecificCoreState::Armv8a(CortexAState::new()),
295            CoreType::Armv8m => SpecificCoreState::Armv8m(CortexMState::new()),
296            CoreType::Riscv => SpecificCoreState::Riscv(RiscvCoreState::new()),
297            CoreType::Xtensa => SpecificCoreState::Xtensa(XtensaCoreState::new()),
298        }
299    }
300
301    pub(crate) fn core_type(&self) -> CoreType {
302        match self {
303            SpecificCoreState::Armv6m(_) => CoreType::Armv6m,
304            SpecificCoreState::Armv7a(_) => CoreType::Armv7a,
305            SpecificCoreState::Armv7m(_) => CoreType::Armv7m,
306            SpecificCoreState::Armv7em(_) => CoreType::Armv7em,
307            SpecificCoreState::Armv8a(_) => CoreType::Armv8a,
308            SpecificCoreState::Armv8m(_) => CoreType::Armv8m,
309            SpecificCoreState::Riscv(_) => CoreType::Riscv,
310            SpecificCoreState::Xtensa(_) => CoreType::Xtensa,
311        }
312    }
313}