probe_rs/core/
core_state.rs

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