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 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 pub(crate) fn arm_memory_ap(&self) -> FullyQualifiedApAddress {
233 self.core_state.memory_ap()
234 }
235}
236
237#[derive(Debug)]
239pub struct CoreState {
240 core_access_options: ResolvedCoreOptions,
242}
243
244impl CoreState {
245 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#[derive(Debug)]
275pub enum SpecificCoreState {
276 Armv6m(CortexMState),
278 Armv7a(CortexAState),
280 Armv7m(CortexMState),
282 Armv7em(CortexMState),
284 Armv8a(CortexAState),
286 Armv8m(CortexMState),
288 Riscv(RiscvCoreState),
290 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}