Skip to main content

probe_rs/core/
core_state.rs

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