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 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 pub(crate) fn arm_memory_ap(&self) -> FullyQualifiedApAddress {
253 self.core_state.memory_ap()
254 }
255}
256
257#[derive(Debug)]
259pub struct CoreState {
260 core_access_options: ResolvedCoreOptions,
262}
263
264impl CoreState {
265 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#[derive(Debug)]
299pub enum SpecificCoreState {
300 Armv6m(CortexMState),
302 Armv7a(CortexARState),
304 Armv7r(CortexARState),
306 Armv7m(CortexMState),
308 Armv7em(CortexMState),
310 Armv8a(CortexARState),
312 Armv8m(CortexMState),
314 Riscv(RiscvCoreState),
316 Riscv64(RiscvCoreState),
318 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}