1pub(crate) mod generic_ap;
4pub(crate) mod memory_ap;
5mod registers;
6pub mod v1;
7pub mod v2;
8
9pub use generic_ap::GenericAp;
10pub use memory_ap::MemoryAp;
11pub use memory_ap::MemoryApType;
12pub(crate) use registers::define_ap_register;
13pub use registers::{BASE, BASE2, BD0, BD1, BD2, BD3, CFG, CSW, DRW, IDR, MBT, TAR, TAR2};
14
15use crate::architecture::arm::{
16 ArmError, DapAccess, DebugPortError, FullyQualifiedApAddress, RegisterParseError,
17};
18
19use crate::probe::DebugProbeError;
20
21#[derive(Debug)]
23pub enum AccessPort {
24 MemoryAp(memory_ap::MemoryAp),
27 Other(GenericAp),
29}
30impl AccessPortType for AccessPort {
31 fn ap_address(&self) -> &FullyQualifiedApAddress {
32 match self {
33 AccessPort::MemoryAp(mem_ap) => mem_ap.ap_address(),
34 AccessPort::Other(o) => o.ap_address(),
35 }
36 }
37}
38
39#[derive(Debug, thiserror::Error)]
41pub enum AccessPortError {
42 #[error("Failed to read register {name} at address {address:#04x}")]
44 RegisterRead {
45 address: u64,
47 name: &'static str,
49 #[source]
51 source: Box<dyn std::error::Error + Send + Sync>,
52 },
53 #[error("Failed to write register {name} at address {address:#04x}")]
55 RegisterWrite {
56 address: u64,
58 name: &'static str,
60 #[source]
62 source: Box<dyn std::error::Error + Send + Sync>,
63 },
64 #[error("Error while communicating with debug port")]
66 DebugPort(#[from] DebugPortError),
67 #[error("Failed to flush batched writes")]
69 Flush(#[from] DebugProbeError),
70
71 #[error("Error parsing a register")]
73 RegisterParse(#[from] RegisterParseError),
74}
75
76impl AccessPortError {
77 pub fn register_read_error<R: ApRegister, E: std::error::Error + Send + Sync + 'static>(
79 source: E,
80 ) -> Self {
81 AccessPortError::RegisterRead {
82 address: R::ADDRESS,
83 name: R::NAME,
84 source: Box::new(source),
85 }
86 }
87
88 pub fn register_write_error<R: ApRegister, E: std::error::Error + Send + Sync + 'static>(
90 source: E,
91 ) -> Self {
92 AccessPortError::RegisterWrite {
93 address: R::ADDRESS,
94 name: R::NAME,
95 source: Box::new(source),
96 }
97 }
98}
99
100pub trait ApRegAccess<Reg: ApRegister>: AccessPortType {}
102
103pub trait AccessPortType {
105 fn ap_address(&self) -> &FullyQualifiedApAddress;
107}
108
109pub trait ApAccess {
111 fn read_ap_register<PORT, R>(&mut self, port: &PORT) -> Result<R, ArmError>
113 where
114 PORT: AccessPortType + ApRegAccess<R> + ?Sized,
115 R: ApRegister;
116
117 fn read_ap_register_repeated<PORT, R>(
120 &mut self,
121 port: &PORT,
122 values: &mut [u32],
123 ) -> Result<(), ArmError>
124 where
125 PORT: AccessPortType + ApRegAccess<R> + ?Sized,
126 R: ApRegister;
127
128 fn write_ap_register<PORT, R>(&mut self, port: &PORT, register: R) -> Result<(), ArmError>
130 where
131 PORT: AccessPortType + ApRegAccess<R> + ?Sized,
132 R: ApRegister;
133
134 fn write_ap_register_repeated<PORT, R>(
137 &mut self,
138 port: &PORT,
139 values: &[u32],
140 ) -> Result<(), ArmError>
141 where
142 PORT: AccessPortType + ApRegAccess<R> + ?Sized,
143 R: ApRegister;
144}
145
146impl<T: DapAccess> ApAccess for T {
147 #[tracing::instrument(skip(self, port), fields(ap = port.ap_address().ap_v1().ok(), register = R::NAME, value))]
148 fn read_ap_register<PORT, R>(&mut self, port: &PORT) -> Result<R, ArmError>
149 where
150 PORT: AccessPortType + ApRegAccess<R> + ?Sized,
151 R: ApRegister,
152 {
153 let raw_value = self.read_raw_ap_register(port.ap_address(), R::ADDRESS)?;
154
155 tracing::Span::current().record("value", raw_value);
156
157 tracing::debug!("Register read successful");
158
159 Ok(raw_value.try_into()?)
160 }
161
162 fn write_ap_register<PORT, R>(&mut self, port: &PORT, register: R) -> Result<(), ArmError>
163 where
164 PORT: AccessPortType + ApRegAccess<R> + ?Sized,
165 R: ApRegister,
166 {
167 tracing::debug!("Writing AP register {}, value={:x?}", R::NAME, register);
168 self.write_raw_ap_register(port.ap_address(), R::ADDRESS, register.into())
169 .inspect_err(|err| tracing::warn!("Failed to write AP register {}: {}", R::NAME, err))
170 }
171
172 fn write_ap_register_repeated<PORT, R>(
173 &mut self,
174 port: &PORT,
175 values: &[u32],
176 ) -> Result<(), ArmError>
177 where
178 PORT: AccessPortType + ApRegAccess<R> + ?Sized,
179 R: ApRegister,
180 {
181 tracing::debug!(
182 "Writing register {}, block with len={} words",
183 R::NAME,
184 values.len(),
185 );
186 self.write_raw_ap_register_repeated(port.ap_address(), R::ADDRESS, values)
187 }
188
189 fn read_ap_register_repeated<PORT, R>(
190 &mut self,
191 port: &PORT,
192 values: &mut [u32],
193 ) -> Result<(), ArmError>
194 where
195 PORT: AccessPortType + ApRegAccess<R> + ?Sized,
196 R: ApRegister,
197 {
198 tracing::debug!(
199 "Reading register {}, block with len={} words",
200 R::NAME,
201 values.len(),
202 );
203
204 self.read_raw_ap_register_repeated(port.ap_address(), R::ADDRESS, values)
205 }
206}
207
208#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
214pub enum DataSize {
215 U8,
217 U16,
219 #[default]
221 U32,
222 U64,
224 U128,
226 U256,
228 Unknown(u8),
230}
231
232impl DataSize {
233 pub(crate) fn to_byte_count(self) -> usize {
234 match self {
235 DataSize::U8 => 1,
236 DataSize::U16 => 2,
237 DataSize::U32 => 4,
238 DataSize::U64 => 8,
239 DataSize::U128 => 16,
240 DataSize::U256 => 32,
241 DataSize::Unknown(bits) => {
243 unreachable!("byte count requested for unknown data size {bits:#x}")
244 }
245 }
246 }
247}
248
249impl From<DataSize> for u8 {
250 fn from(value: DataSize) -> u8 {
251 match value {
252 DataSize::U8 => 0b000,
253 DataSize::U16 => 0b001,
254 DataSize::U32 => 0b010,
255 DataSize::U64 => 0b011,
256 DataSize::U128 => 0b100,
257 DataSize::U256 => 0b101,
258 DataSize::Unknown(bits) => bits,
259 }
260 }
261}
262
263impl From<u8> for DataSize {
264 fn from(value: u8) -> Self {
265 match value {
266 0b000 => DataSize::U8,
267 0b001 => DataSize::U16,
268 0b010 => DataSize::U32,
269 0b011 => DataSize::U64,
270 0b100 => DataSize::U128,
271 0b101 => DataSize::U256,
272 bits => DataSize::Unknown(bits),
273 }
274 }
275}
276
277#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
284pub enum AddressIncrement {
285 Off,
288 #[default]
291 Single,
292 Packed,
295 Unknown(u8),
297}
298
299impl From<AddressIncrement> for u8 {
300 fn from(value: AddressIncrement) -> u8 {
301 match value {
302 AddressIncrement::Off => 0b00,
303 AddressIncrement::Single => 0b01,
304 AddressIncrement::Packed => 0b10,
305 AddressIncrement::Unknown(bits) => bits,
306 }
307 }
308}
309
310impl From<u8> for AddressIncrement {
311 fn from(value: u8) -> Self {
312 match value {
313 0b00 => AddressIncrement::Off,
314 0b01 => AddressIncrement::Single,
315 0b10 => AddressIncrement::Packed,
316 bits => AddressIncrement::Unknown(bits),
317 }
318 }
319}
320
321#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
323pub enum BaseAddrFormat {
324 #[default]
326 Legacy,
327 ADIv5,
329 Unknown(u8),
331}
332
333impl From<BaseAddrFormat> for u8 {
334 fn from(value: BaseAddrFormat) -> u8 {
335 match value {
336 BaseAddrFormat::Legacy => 0,
337 BaseAddrFormat::ADIv5 => 1,
338 BaseAddrFormat::Unknown(bits) => bits,
339 }
340 }
341}
342
343impl From<u8> for BaseAddrFormat {
344 fn from(value: u8) -> Self {
345 match value {
346 0 => BaseAddrFormat::Legacy,
347 1 => BaseAddrFormat::ADIv5,
348 bits => BaseAddrFormat::Unknown(bits),
349 }
350 }
351}
352
353#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
355pub enum ApClass {
356 #[default]
358 Undefined,
359 ComAp,
361 MemAp,
363 Unknown(u8),
365}
366
367impl From<ApClass> for u8 {
368 fn from(value: ApClass) -> u8 {
369 match value {
370 ApClass::Undefined => 0b0000,
371 ApClass::ComAp => 0b0001,
372 ApClass::MemAp => 0b1000,
373 ApClass::Unknown(bits) => bits,
374 }
375 }
376}
377
378impl From<u8> for ApClass {
379 fn from(value: u8) -> Self {
380 match value {
381 0b0000 => ApClass::Undefined,
382 0b0001 => ApClass::ComAp,
383 0b1000 => ApClass::MemAp,
384 bits => ApClass::Unknown(bits),
385 }
386 }
387}
388
389#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
393pub enum ApType {
394 #[default]
396 JtagComAp,
397 AmbaAhb3,
399 AmbaApb2Apb3,
401 AmbaAxi3Axi4,
403 AmbaAhb5,
405 AmbaApb4Apb5,
407 AmbaAxi5,
409 AmbaAhb5Hprot,
411 Unknown(u8),
413}
414
415impl From<ApType> for u8 {
416 fn from(value: ApType) -> u8 {
417 match value {
418 ApType::JtagComAp => 0x0,
419 ApType::AmbaAhb3 => 0x1,
420 ApType::AmbaApb2Apb3 => 0x2,
421 ApType::AmbaAxi3Axi4 => 0x4,
422 ApType::AmbaAhb5 => 0x5,
423 ApType::AmbaApb4Apb5 => 0x6,
424 ApType::AmbaAxi5 => 0x7,
425 ApType::AmbaAhb5Hprot => 0x8,
426 ApType::Unknown(bits) => bits,
427 }
428 }
429}
430
431impl From<u8> for ApType {
432 fn from(value: u8) -> Self {
433 match value {
434 0x0 => ApType::JtagComAp,
435 0x1 => ApType::AmbaAhb3,
436 0x2 => ApType::AmbaApb2Apb3,
437 0x4 => ApType::AmbaAxi3Axi4,
438 0x5 => ApType::AmbaAhb5,
439 0x6 => ApType::AmbaApb4Apb5,
440 0x7 => ApType::AmbaAxi5,
441 0x8 => ApType::AmbaAhb5Hprot,
442 bits => ApType::Unknown(bits),
443 }
444 }
445}
446
447pub trait ApRegister:
449 Clone + TryFrom<u32, Error = RegisterParseError> + Into<u32> + Sized + std::fmt::Debug
450{
451 const ADDRESS: u64;
453
454 const NAME: &'static str;
456}