probe_rs/architecture/arm/dp/
mod.rs

1//! Types and functions for interacting with debug ports.
2
3#[macro_use]
4mod register_generation;
5
6use super::{ArmError, DapAccess, DapError, RegisterParseError};
7use bitfield::bitfield;
8use jep106::JEP106Code;
9
10use crate::probe::DebugProbeError;
11use std::fmt::Display;
12
13/// Debug port address.
14#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Clone, Copy, Hash, Default)]
15pub enum DpAddress {
16    /// Access the single DP on the bus, assuming there is only one.
17    /// Will cause corruption if multiple are present.
18    #[default]
19    Default,
20    /// Select a particular DP on a SWDv2 multidrop bus. The contained `u32` is
21    /// the `TARGETSEL` value to select it.
22    Multidrop(u32),
23}
24
25/// A Debug port register address and its bank.
26#[derive(Debug, Eq, PartialEq, Clone, Copy)]
27pub struct DpRegisterAddress {
28    /// The register address.
29    pub address: u8,
30    /// The register bank.
31    pub bank: Option<u8>,
32}
33
34impl From<DpRegisterAddress> for u8 {
35    fn from(addr: DpRegisterAddress) -> Self {
36        ((addr.bank.unwrap_or(0) << 4) & 0xF0) | (addr.address & 0xF)
37    }
38}
39
40/// A trait to be implemented on Debug Port register types for typed device access.
41pub trait DpRegister:
42    Clone + TryFrom<u32, Error = RegisterParseError> + Into<u32> + Sized + std::fmt::Debug
43{
44    /// The version of the debug port that is required to read this register.
45    const VERSION: DebugPortVersion;
46
47    /// The address of the register.
48    const ADDRESS: DpRegisterAddress;
49
50    /// The name of the register as string.
51    const NAME: &'static str;
52}
53
54macro_rules! impl_dpregister {
55    ($t:tt, $v:expr, $addr:expr, $name:expr) => {
56        impl_dpregister!($t, $v, $addr, None, $name);
57    };
58    ($t:tt, $v:expr, $addr:expr, $bank:expr, $name:expr) => {
59        impl TryFrom<u32> for $t {
60            type Error = RegisterParseError;
61
62            fn try_from(raw: u32) -> Result<Self, Self::Error> {
63                // TODO: This is not super useful
64                Ok($t(raw))
65            }
66        }
67
68        impl From<$t> for u32 {
69            fn from(raw: $t) -> Self {
70                raw.0
71            }
72        }
73
74        impl DpRegister for $t {
75            const VERSION: DebugPortVersion = $v;
76            const ADDRESS: DpRegisterAddress = DpRegisterAddress {
77                address: $addr,
78                bank: $bank,
79            };
80            const NAME: &'static str = $name;
81        }
82    };
83}
84
85/// An error occurred when interacting with the debug port.
86#[derive(thiserror::Error, Debug)]
87pub enum DebugPortError {
88    /// The accessed register is not supported on this debug port.
89    #[error("Register {register} not supported by debug port version {version}")]
90    UnsupportedRegister {
91        /// The name of the register that was accessed.
92        register: &'static str,
93        /// The version of the operated debug port.
94        version: DebugPortVersion,
95    },
96    /// Error parsing a register value.
97    #[error("Error parsing register value.")]
98    RegisterParse(#[from] RegisterParseError),
99    /// An error with operating the debug probe occurred.
100    #[error("A Debug Probe Error occurred")]
101    DebugProbe(#[from] DebugProbeError),
102
103    /// A timeout occurred.
104    #[error("Timeout occurred")]
105    Timeout,
106
107    /// Powerup of the target device failed.
108    #[error("Target power-up failed.")]
109    TargetPowerUpFailed,
110
111    /// The debug port is not supported.
112    #[error("Debug port not supported: {0}")]
113    Unsupported(String),
114
115    /// An error occurred in the communication with an access port or debug port.
116    #[error("An error occurred in the communication with an access port or debug port.")]
117    Dap(#[from] DapError),
118}
119/// A typed interface to be implemented on drivers that can control a debug port.
120pub trait DpAccess {
121    /// Reads a debug port register.
122    ///
123    /// If the target device has multiple debug ports, this will change the active debug port if necessary.
124    /// In this case all pending operations will be run, and errors returned by this function can also
125    /// be from these operations.
126    fn read_dp_register<R: DpRegister>(&mut self, dp: DpAddress) -> Result<R, ArmError>;
127
128    /// Write a debug port register.
129    ///
130    /// If the target device has multiple debug ports, this will change the active debug port if necessary.
131    /// In this case all pending operations will be run, and errors returned by this function can also
132    /// be from these operations.
133    fn write_dp_register<R: DpRegister>(
134        &mut self,
135        dp: DpAddress,
136        register: R,
137    ) -> Result<(), ArmError>;
138}
139
140impl<T: ?Sized + DapAccess> DpAccess for T {
141    #[tracing::instrument(skip(self))]
142    fn read_dp_register<R: DpRegister>(&mut self, dp: DpAddress) -> Result<R, ArmError> {
143        tracing::debug!("Reading DP register {}", R::NAME);
144        let result = self.read_raw_dp_register(dp, R::ADDRESS)?.try_into()?;
145        tracing::debug!("Read    DP register {}, value=0x{:08x?}", R::NAME, result);
146        Ok(result)
147    }
148
149    #[tracing::instrument(skip(self))]
150    fn write_dp_register<R: DpRegister>(
151        &mut self,
152        dp: DpAddress,
153        register: R,
154    ) -> Result<(), ArmError> {
155        let value = register.into();
156        tracing::debug!("Writing DP register {}, value=0x{:08x}", R::NAME, value);
157        self.write_raw_dp_register(dp, R::ADDRESS, value)?;
158        Ok(())
159    }
160}
161
162bitfield! {
163    /// ABORT, Abort register (see ADI v5.2 B2.2.1)
164    ///
165    /// Only for write operations.
166    #[derive(Copy, Clone, Default)]
167    pub struct Abort(u32);
168    impl Debug;
169    /// To clear the CTRL/STAT.STICKYORUN overrun error bit to `0b0`, write `0b1` to this bit.
170    pub _, set_orunerrclr: 4;
171    /// To clear the CTRL/STAT.WDATAERR write data error bit to `0b0`, write `0b1` to this bit.
172    pub _, set_wderrclr: 3;
173    /// To clear the CTRL/STAT.STICKYERR sticky error bit to `0b0`, write `0b1` to this bit.
174    pub _, set_stkerrclr: 2;
175    /// To clear the CTRL/STAT.STICKYCMP sticky compare bit to `0b0`, write `0b1` to this bit. It is IMPLEMENTATION DEFINED whether the CTRL/STAT.STICKYCMP bit is implemented. See MINDP, Minimal DP extension on page B1-40.
176    pub _, set_stkcmpclr: 1;
177    /// To generate a DAP abort, which aborts the current AP transaction, write `0b1` to this bit. Do this write only if the debugger has received WAIT responses over an extended period. In DPv0, this bit is SBO.
178    pub _, set_dapabort: 0;
179}
180impl_dpregister!(Abort, DebugPortVersion::DPv1, 0x0, "ABORT");
181
182bitfield! {
183    /// CTRL/STAT, Control/Status register (see ADI v5.2 B2.2.2)
184    #[derive(Clone, Default)]
185    pub struct Ctrl(u32);
186    impl Debug;
187    /// System powerup acknowledge. Indicates the status of the CSYSPWRUPACK signal. See Power control requirements and operation on page B2-78.
188    pub csyspwrupack, _: 31;
189    /// System powerup request. This bit controls the CSYSPWRUPREQ signal. See Power control requirements and operation on page B2-78.
190    pub csyspwrupreq, set_csyspwrupreq: 30;
191    /// Debug powerup acknowledge. Indicates the status of the CDBGPWRUPACK signal. See Power control requirements and operation on page B2-78.
192    pub cdbgpwrupack, _: 29;
193    /// Debug powerup request. This bit controls the CDBGPWRUPREQ signal. See Power control requirements and operation on page B2-78.
194    pub cdbgpwrupreq, set_cdbgpwrupreq: 28;
195    /// Debug reset acknowledge. Indicates the status of the CDBGRSTACK signal. See Debug reset control behavior on page B2-81.
196    pub cdbgrstack, _: 27;
197    /// Debug reset request. This bit controls the CDBGRSTREQ signal. See Debug reset control request on page B2-82.
198    ///
199    /// After a powerup reset, this bit is `0b0`.
200    pub c_dbg_rst_req, set_c_dbg_rst_req: 26;
201    /// Error mode. Indicates the reset behavior of the CTRL/STAT.STICKYERR field.
202    ///
203    /// If true, CTRL/STAT.STICKYERR is cleared when a FAULT response is output.
204    ///
205    /// After a powerup reset, the value of this field is false.
206    ///
207    /// This bit only exists on DPv3 (see ADIv6 B2.2.3), it is RES0 on previous DP versions. Its
208    /// value should therefore be ignored and written as 0.
209    pub errmode, set_errmode: 24;
210    /// Transaction counter. See The transaction counter on page B1-43. After a powerup reset, the value of this field is UNKNOWN.
211    ///
212    /// It is IMPLEMENTATION DEFINED whether this field is implemented.
213    ///
214    /// TRNCNT is not supported in MINDP configuration. In MINDP configuration, the effect of writing a value other than zero to TRNCNT or TRNMODE is UNPREDICTABLE. See also MINDP, Minimal DP extension on page B1-40.
215    pub u16, trn_cnt, set_trn_cnt: 23, 12;
216    /// For pushed operations, the DP performs a byte-by-byte comparison of the word that is supplied in an AP write transaction with the current word at the target AP address. The MASKLANE field is used to select the bytes to be included in this comparison. For more information about pushed operations, see Pushed-compare and pushed-verify operations on page B1-44.
217    ///
218    /// Each of the four bits of the MASKLANE field corresponds to one of the four bytes of the words to be compared. Therefore, each bit is said to control one byte lane of the compare operation.
219    ///
220    /// Table B2-8 shows how the bits of MASKLANE control the comparison masking.
221    pub u8, mask_lane, set_mask_lane: 11, 8;
222    /// This bit is set to `0b1` if one of the following Write Data Error occurs:
223    ///
224    /// - A parity or framing error on the data phase of a write.
225    /// - A write that has been accepted by the DP is then discarded without being submitted to the AP. For more information, see Sticky flags and DP error responses on page B1-41.
226    ///
227    /// Access to and how to clear this field are DATA LINK DEFINED:
228    ///
229    /// **JTAG-DP, all implementations**
230    ///
231    /// - Access is reserved, RES0.
232    ///
233    /// **SW-DP, all implementations, and JTAG-DP, DPv1 and higher**
234    ///
235    /// - Access is RO/WI.
236    /// - To clear WDATAERR to `0b0`, write 0b1 to the ABORT.WDERRCLR field in the ABORT register. A single write of the ABORT register can be used to clear multiple flags if necessary.
237    ///
238    /// After clearing the WDATAERR flag, you must typically resend the corrupted data. After a powerup reset, WDATAERR is `0b0`.
239    pub w_data_err, _ : 7;
240    /// This bit is DATA LINK DEFINED
241    ///
242    /// - On JTAG-DP, the bit is reserved, RES0.\
243    /// - On SW-DP, access is RO/WI.
244    ///
245    /// If the response to the previous AP read or RDBUFF read was OK, the bit is set to 0b1. If the response was not OK, it is cleared to `0b0`.
246    ///
247    /// This flag always indicates the response to the last AP read access. See Protocol error response on page B4-114.
248    ///
249    /// After a powerup reset, this bit is `0b0`.
250    ///
251    /// **Note**
252    ///
253    /// This field is defined for DPv1 and higher only.
254    pub read_ok, _ : 6;
255    /// This bit is set to 0b1 if an error is returned by an AP transaction. See Sticky flags and DP error responses on page B1-41.
256    ///
257    /// Access to and how to clear this field are DATA LINK DEFINED:
258    ///
259    /// **JTAG-DP, all implementations**
260    ///
261    /// - Access is R/W1C.
262    /// - To clear STICKYERR to 0b0, write 0b1 to it, which signals the DP to clear the flag and set it to 0b0. A single write of the CTRL/STAT register can be used to clear multiple flags if necessary.
263    ///
264    /// STICKYERR can also be cleared using the ABORT.STKERRCLR field.
265    ///
266    /// **SW-DP, all implementations, and JTAG-DP, DPv1 and higher**
267    ///
268    /// - Access is RO/WI.
269    /// - To clear STICKYERR to 0b0, write 0b1 to the ABORT.STKERRCLR field in the ABORT register. A single write of the ABORT register can be used to clear multiple flags if necessary.
270    ///
271    /// After clearing CTRL/STAT.STICKYERR, you must find the location where the error that caused the flag to be set occurred.
272    ///
273    /// After a powerup reset, this bit is `0b0`.
274    pub sticky_err, _: 5;
275    /// This bit is set to 0b1 when a mismatch occurs during a pushed-compare operation or a match occurs during a pushed-verify operation. See Pushed-compare and pushed-verify operations on
276    /// page B1-44.
277    /// It is IMPLEMENTATION DEFINED whether this field is implemented. See MINDP, Minimal DP extension on page B1-40.
278    /// Access to and how to clear this field are DATA LINK DEFINED:
279    ///
280    /// **JTAG-DP, all implementations**
281    ///
282    /// - Access is R/W1C.
283    /// - To clear STICKYCMP to 0b0, write 0b1 to it, which signals the DP to clear the flag and set it to 0b0. A single write of the CTRL/STAT register can be used to clear multiple flags if necessary. STICKYCMP can also be cleared using the ABORT.STKERRCLR field.
284    ///
285    /// **SW-DP, all implementations, and JTAG-DP, DPv1 and higher**
286    ///
287    /// - Access is RO/WI.
288    /// B2 DP Reference Information B2.2 DP register descriptions
289    /// - To clear STICKYCMP to 0b0, write 0b1 to the ABORT.STKCMPCLR field in the ABORT register. A single write of the ABORT register can be used to clear multiple flags if necessary.
290    /// After clearing STICKYCMP, you must retrieve the value of the transaction counter to find the location where the error that caused the flag to be set occurred.
291    ///
292    /// After a powerup reset, this bit is `0b0`.
293    pub stick_cmp, _: 4;
294    /// This field sets the transfer mode for AP operations.
295    /// In normal operation, AP transactions are passed to the AP for processing, as described in _Using the AP to access debug resources_ on page A1-31.
296    /// In pushed-verify and pushed-compare operations, the DP compares the value that is supplied in an AP write transaction with the value held in the target AP address. The AP write transaction generates a read access to the debug memory system as described in Pushed-compare and pushed-verify operations on page B1-44.
297    ///
298    /// TRNMODE can have one of the following values:
299    ///
300    /// `0b00`: Normal operation.\
301    /// `0b01`: Pushed-verify mode.\
302    /// `0b10`: Pushed-compare mode.\
303    /// `0b11`: Reserved.
304    ///
305    /// After a powerup reset, the value of this field is UNKNOWN.
306    ///
307    /// **Note**
308    ///
309    /// It is IMPLEMENTATION DEFINED whether this field is implemented.
310    ///
311    /// TRNMODE is not supported in MINDP configuration. In MINDP configuration, the effect of writing a value other than zero to TRNCNT or TRNMODE is UNPREDICTABLE. See also MINDP, Minimal DP extension on page B1-40.
312    pub u8, trn_mode, _: 3, 2;
313    /// If overrun detection is enabled, this bit is set to 0b1 when an overrun occurs. See `bit[0]` of this register for details of enabling overrun detection.
314    /// Access to and how to clear this field are DATA LINK DEFINED:
315    ///
316    /// JTAG-DP, all implementations
317    /// - Access is R/W1C.
318    /// - To clear STICKYORUN to 0b0, write 0b1 to it, which signals the DP to clear the flag and set it to 0b0. A single write of the CTRL/STAT register can be used to clear multiple flags if necessary.
319    /// STICKYORUN can also be cleared using the ABORT.STKERRCLR field.
320    /// SW-DP, all implementations, and JTAG-DP, DPv1 and higher
321    /// - Access is RO/WI.
322    /// - To clear STICKYORUN to 0b0, write 0b1 to the ABORT.ORUNERRCLR field in the ABORT register.
323    ///
324    /// A single write of the ABORT register can be used to clear multiple flags if necessary.
325    /// After clearing STICKYORUN, you must find out which DP or AP transaction initiated the overrun that caused the flag to be set, and repeat the transactions for that DP or AP from the transaction pointed to by the transaction counter.
326    ///
327    /// After a powerup reset, this bit is 0b0.
328    pub sticky_orun, _: 1;
329    /// This bit can have one of the following values:
330    ///
331    /// `0b0`: Overrun detection is disabled.\
332    /// `0b1`: Overrun detection is enabled.
333    ///
334    /// For more information about overrun detection, see Sticky flags and DP error responses on page B1-41.
335    ///
336    /// After a powerup reset, this bit is 0b0.
337    pub orun_detect, set_orun_detect: 0;
338}
339impl_dpregister!(Ctrl, DebugPortVersion::DPv1, 0x4, "CTRL/STAT");
340
341bitfield! {
342    /// SELECT, AP Select register (see ADI v5.2 B2.2.9)
343    #[derive(Clone, Copy, PartialEq, Eq)]
344    pub struct SelectV1(u32);
345    impl Debug;
346    /// Selects the AP with the ID number APSEL. If there is no AP with the ID APSEL, all AP transactions return zero on reads and are ignored on writes. See Register maps, and accesses to reserved addresses on page B2-52.
347    /// After a powerup reset, the value of this field is UNKNOWN.
348    /// Note
349    /// Every Arm Debug Interface implementation must include at least one AP.
350    pub u8, ap_sel, set_ap_sel: 31, 24;
351    /// Selects the active four-word register bank on the current AP. See Using the AP to access debug resources on page A1-31.
352    /// After a powerup reset, the value of this field is UNKNOWN.
353    pub u8, ap_bank_sel, set_ap_bank_sel: 7, 4;
354    /// Debug Port address bank select.
355    /// The behavior of SELECT.DPBANKSEL depends on the DP version, as follows:
356    /// DPv0 In DPv0 the SELECT.DPBANKSEL field must be written as zero, otherwise accesses to DP register 0x4 are UNPREDICTABLE.
357    /// DPv1 In DPv1 the SELECT.DPBANKSEL field controls which DP register is selected at address 0x4, and Table B2-10 shows the permitted values of this field.
358    /// Table B2-10 DPBANKSEL DP register allocation in DPv1
359    /// DPBANKSEL DP register at address 0x4
360    /// * 0x0 CTRL/STAT
361    /// * 0x1 DLCR
362    /// All other values of SELECT.DPBANKSEL are reserved. If the field is set to a reserved value, accesses to DP register 0x4 are UNPREDICTABLE.
363    /// DPv2 In DPv2 the SELECT.DPBANKSEL field controls which DP register is selected at address 0x4, and Table B2-11 shows the permitted values of this field.
364    /// Table B2-11 DPBANKSEL DP register allocation in DPv2 DPBANKSEL DP register at address 0x4
365    /// * 0x0 CTRL/STAT
366    /// * 0x1 DLCR
367    /// * 0x2 TARGETID
368    /// * 0x3 DLPIDR
369    /// * 0x4 EVENTSTAT
370    /// All other values of SELECT.DPBANKSEL are reserved. If the field is set to a reserved value, accesses to DP register 0x4 are RES0.
371    /// After a powerup reset, this field is 0x0. Note
372    /// Some previous ADI revisions have described DPBANKSEL as a single-bit field called CTRSEL, defined only for SW-DP. From issue B of this document, DPBANKSEL is redefined. The new definition is backwards-compatible.
373    pub u8, dp_bank_sel, set_dp_bank_sel: 3, 0;
374}
375impl_dpregister!(SelectV1, DebugPortVersion::DPv1, 0x8, "SELECT");
376
377bitfield! {
378    /// SELECT, AP Select register (see ADI v5.2 B2.2.9)
379    #[derive(Clone, Copy, PartialEq, Eq)]
380    pub struct SelectV3(u32);
381    impl Debug;
382    /// Address output bits\[63:4\], formed by concatenating bits\[31:0\] of SELECT1 with bits\[31:4\] of SELECT.
383    /// The ADDR field selects a four-word bank of system locations to access.
384    /// - Bits\[3:2\] of the address, that are used to select a specific register in a bank, are provided with APACC transactions.
385    /// - Bits\[1:0\] are always 0b00.
386    ///
387    /// After a powerup reset or an SWD line reset, the value of this field is UNKNOWN
388    pub u32, addr, set_addr: 31, 4;
389    /// Debug Port address bank select.
390    pub u8, dp_bank_sel, set_dp_bank_sel: 3, 0;
391}
392impl_dpregister!(SelectV3, DebugPortVersion::DPv3, 0x8, "SELECT");
393
394bitfield! {
395    /// SELECT1, AP Select register (see ADI v5.2 B2.2.9)
396    #[derive(Clone, Copy, PartialEq, Eq)]
397    pub struct Select1(u32);
398    impl Debug;
399    /// Address output bits\[63:4\], formed by concatenating bits\[31:0\] of SELECT1 with bits\[31:4\] of SELECT.
400    /// The ADDR field selects a four-word bank of system locations to access.
401    /// - Bits\[3:2\] of the address, that are used to select a specific register in a bank, are provided with APACC transactions.
402    /// - Bits\[1:0\] are always 0b00.
403    ///
404    /// After a powerup reset or an SWD line reset, the value of this field is UNKNOWN
405    pub u32, addr, set_addr: 31, 0;
406}
407impl_dpregister!(Select1, DebugPortVersion::DPv3, 0x4, Some(0x5), "SELECT1");
408
409bitfield! {
410    /// DPIDR, Debug Port Identification register (see ADI v5.2 B2.2.5)
411    ///
412    /// DPIDR provides information about the Debug Port.
413    /// Only for read operations.
414    #[derive(Clone)]
415    pub struct DPIDR(u32);
416    impl Debug;
417    /// Revision code. The meaning of this field is IMPLEMENTATION DEFINED.
418    pub u8, revision, _: 31, 28;
419    /// Part Number for the Debug Port. This value is provided by the designer of the Debug Port and must not be changed.
420    pub u8, part_no, _: 27, 20;
421    /// Minimal Debug Port (MINDP) functions implemented:
422    ///
423    /// `0b0`: Transaction counter, Pushed-verify, and Pushed-find operations are implemented.\
424    /// `0b1`: Transaction counter, Pushed-verify, and Pushed-find operations are not implemented.
425    pub min, _: 16;
426    /// Version of the Debug Port architecture implemented. Permitted values are:
427    ///
428    /// `0x0`: Reserved. Implementations of DPv0 do not implement DPIDR.\
429    /// `0x1`: DPv1 is implemented.\
430    /// `0x2`: DPv2 is implemented.\
431    /// `0x3`: DPv3 is implemented.
432    ///
433    /// All remaining values are reserved.
434    pub u8, version, _: 15, 12;
435    /// Code that identifies the designer of the DP.
436    /// This field indicates the designer of the DP and not the implementer, except where the two are the same.
437    /// A JEDEC code takes the following form:
438    ///
439    /// - A sequence of zero or more numbers, all having the value `0x7F`.
440    /// - A following 8-bit number, that is not `0x7F`, and where `bit[7]` is an odd parity bit. For example, Arm Limited is assigned the code `0x7F 0x7F 0x7F 0x7F 0x3B`.
441    /// The encoding that is used in the DPIDR is as follows:
442    /// - The JEP106 continuation code, DPIDR `bits[11:8]`, is the number of times that `0x7F` appears
443    /// before the final number. For example, for Arm Limited this field is `0x4`.
444    /// - The JEP106 identification code, IDR `bits[7:1]`, equals `bits[6:0]` of the final number of the
445    /// JEDEC code. For example, for Arm Limited this field is `0x3B`.
446    pub designer, _: 11, 1;
447    /// The JEP106 continuation code (see [`DPIDR::version`]).
448    pub u8, jep_cc, _: 11, 8;
449    /// The JEP106 ID (see [`DPIDR::version`]).
450    pub u8, jep_id, _: 7, 1;
451}
452impl_dpregister!(DPIDR, DebugPortVersion::DPv1, 0x0, "DPIDR");
453
454bitfield! {
455    /// DPIDR1, Debug Port Identification register (see ADI v6 B2.2.7)
456    ///
457    /// DPIDR1 provides information about the Debug Port.
458    /// Only for read operations.
459    #[derive(Clone)]
460    pub struct DPIDR1(u32);
461    impl Debug;
462    /// Error reporting mode support.
463    ///
464    /// If true, CTRL/STAT.ERRMODE is implemented.
465    pub errmode, _: 7;
466    /// Address size.
467    ///
468    /// This field selects the size of the addresses in SELECT, SELECT1, BASEPTR0 and BASEPTR1.
469    /// Possible values are 12, 20, 32, 40, 48 and 52 bits.
470    pub u8, asize, _: 6, 0;
471}
472impl_dpregister!(DPIDR1, DebugPortVersion::DPv3, 0x0, Some(0x1), "DPIDR1");
473
474bitfield! {
475    /// TARGETID, Target Identification register (see ADI v5.2 B2.2.10)
476    ///
477    /// TARGETID provides information about the target when the host is connected to a single device.
478    #[derive(Clone)]
479    pub struct TARGETID(u32);
480    impl Debug;
481    /// Target revision.
482    pub u8, trevision, _: 31, 28;
483    /// IMPLEMENTATION DEFINED. The value is assigned by the designer of the part. The value must be unique to the part.
484    pub u16, tpartno, _: 27, 12;
485    /// IMPLEMENTATION DEFINED.
486    ///
487    /// This field indicates the designer of the part and not the implementer, except where the two are the same.
488    /// Designers must insert their JEDEC-assigned code here.
489    ///
490    /// **Note**
491    ///
492    /// The Arm JEP106 value is not shown for the TDESIGNER field. Arm might design a DP containing the TARGETID register, but typically, the designer of the part, referenced in the TPARTNO field, is another designer who creates a part around the licensed Arm IP. If the designer of the part is Arm, then the value of this field is `0x23B`.
493    ///
494    /// A JEP106 code takes the following form:
495    ///
496    /// - A sequence of zero or more numbers, all having the value `0x7F`.
497    /// - A following 8-bit number, that is not `0x7F`, and where `bit[7]` is an odd parity bit. For example, Arm Limited is assigned the code `0x7F 0x7F 0x7F 0x7F 0x3B`.
498    /// The encoding that is used in TARGETID is as follows:
499    /// - The JEP106 continuation code, TARGETID `bits[11:8]`, is the number of times that `0x7F`
500    /// appears before the final number. For example, for Arm Limited this field is `0x4`.
501    /// - The JEP106 identification code, TARGETID `bits[7:1]`, equals `bits[6:0]` of the final number of the JEDEC code.
502    pub u16, tdesigner, _: 11, 1;
503}
504impl_dpregister!(TARGETID, DebugPortVersion::DPv2, 0x4, Some(0x2), "TARGETID");
505
506bitfield! {
507    /// DLPIDR, Data Link Protocol Identification register (see ADI v5.2 B2.2.4)
508    ///
509    /// DLPIDR provides protocol version information.
510    ///
511    /// Only for read operations.
512    #[derive(Clone)]
513    pub struct DLPIDR(u32);
514    impl Debug;
515    /// IMPLEMENTATION DEFINED. Instance number for this device.
516    pub u8, tinstance, _: 31, 28;
517    /// Implemented SWD protocol version
518    pub u8, protsvn, _: 3, 0;
519}
520impl_dpregister!(DLPIDR, DebugPortVersion::DPv2, 0x4, Some(0x3), "DLPIDR");
521
522bitfield! {
523    /// BASEPTR0, Initial system address for the first component in the system (see ADI v6.0 B2.2.2)
524    ///
525    /// Only for read operations.
526    #[derive(Clone)]
527    pub struct BASEPTR0(u32);
528    impl Debug;
529    /// Pointer least significant bits (bits `[31:12]` of the full address).
530    pub u32, ptr, _: 31, 12;
531    /// True if `ptr` specifies a valid base address.
532    pub valid, _: 0;
533}
534impl_dpregister!(BASEPTR0, DebugPortVersion::DPv3, 0x0, Some(0x2), "BASEPTR0");
535
536bitfield! {
537    /// BASEPTR1, Initial system address for the first component in the system (see ADI v6.0 B2.2.2)
538    ///
539    /// Only for read operations.
540    #[derive(Clone)]
541    pub struct BASEPTR1(u32);
542    impl Debug;
543    /// Pointer most significant bits (bits `[63:32]` of the full address).
544    pub u32, ptr, _: 31, 0;
545}
546impl_dpregister!(BASEPTR1, DebugPortVersion::DPv3, 0x0, Some(0x3), "BASEPTR1");
547
548/// The ID of a debug port. Can be used to detect and select devices in a multidrop setup.
549#[derive(Debug)]
550pub struct DebugPortId {
551    /// The revision of the debug port (implementation defined). This is what the designer of the debug port chooses.
552    pub revision: u8,
553    /// The part number of the debug port (determined by the designer).
554    pub part_no: u8,
555    /// The version of this debug port. This is what the selected spec says.
556    pub version: DebugPortVersion,
557    /// Specifies if pushed-find operations are implemented or not.
558    pub min_dp_support: MinDpSupport,
559    /// The JEP106 code of the designer of this debug port.
560    pub designer: JEP106Code,
561}
562
563impl From<DPIDR> for DebugPortId {
564    fn from(dpidr: DPIDR) -> DebugPortId {
565        DebugPortId {
566            revision: dpidr.revision(),
567            part_no: dpidr.part_no(),
568            version: dpidr.version().into(),
569            min_dp_support: dpidr.min().into(),
570            designer: JEP106Code::new(dpidr.jep_cc(), dpidr.jep_id()),
571        }
572    }
573}
574
575/// RDBUFF, Read Buffer register (see ADI v5.2 B2.2.7)
576///
577/// The purpose and behavior of RDBUFF is DATA LINK DEFINED:
578///
579/// **JTAG-DP:** The Read Buffer is architecturally defined to provide a DP read operation that does not have any side effects. This definition allows a debugger to insert a DP read of RDBUFF at the end of a sequence of operations, to return the final AP Read Result and ACK values.
580///
581/// *SW-DP:** On an SW-DP, the Read Buffer presents data that was captured during the previous AP read, enabling repeatedly returning the value without generating a new AP access.
582///
583/// **Note**
584///
585/// After reading the DP Read Buffer, its contents are no longer valid. The result of a second read of the DP Read Buffer is UNKNOWN.
586///
587/// If you require the value from an AP register read, that read must be followed by one of:
588/// - A second AP register access, with the appropriate AP selected as the current AP.
589/// - A read of the DP Read Buffer.
590///
591/// The second access to either the AP or the DP stalls until the result of the original AP read is available.
592#[derive(Debug, Clone)]
593pub struct RdBuff(pub u32);
594impl_dpregister!(RdBuff, DebugPortVersion::DPv1, 0x0C, "RDBUFF");
595
596/// Specifies if pushed-find operations are implemented or not.
597#[derive(Debug, PartialEq, Eq)]
598pub enum MinDpSupport {
599    /// Pushed-find operations are **not** implemented.
600    NotImplemented,
601    /// Pushed-find operations are implemented.
602    Implemented,
603}
604
605impl From<bool> for MinDpSupport {
606    fn from(bit_set: bool) -> Self {
607        if bit_set {
608            MinDpSupport::Implemented
609        } else {
610            MinDpSupport::NotImplemented
611        }
612    }
613}
614
615/// The version of the debug port.
616#[derive(Debug, PartialEq, Eq, Copy, Clone)]
617pub enum DebugPortVersion {
618    /// Version 0 (not common)
619    DPv0,
620    /// Version 1 (most of the ARM cores feature this version)
621    DPv1,
622    /// Version 2 (**very** rare (only known example is the RP2040))
623    DPv2,
624    /// Version 3 (on ADIv6 devices)
625    DPv3,
626    /// Some unsupported value was encountered!
627    Unsupported(u8),
628}
629
630impl From<DebugPortVersion> for u8 {
631    fn from(version: DebugPortVersion) -> Self {
632        match version {
633            DebugPortVersion::DPv0 => 0,
634            DebugPortVersion::DPv1 => 1,
635            DebugPortVersion::DPv2 => 2,
636            DebugPortVersion::DPv3 => 3,
637            DebugPortVersion::Unsupported(val) => val,
638        }
639    }
640}
641
642impl PartialOrd for DebugPortVersion {
643    fn partial_cmp(&self, other: &DebugPortVersion) -> Option<std::cmp::Ordering> {
644        let self_value = u8::from(*self);
645        let other_value = u8::from(*other);
646
647        self_value.partial_cmp(&other_value)
648    }
649}
650
651impl Display for DebugPortVersion {
652    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
653        match self {
654            Self::DPv0 => write!(f, "DPv0"),
655            Self::DPv1 => write!(f, "DPv1"),
656            Self::DPv2 => write!(f, "DPv2"),
657            Self::DPv3 => write!(f, "DPv3"),
658            Self::Unsupported(version) => write!(f, "<unsupported Debugport Version {version}>"),
659        }
660    }
661}
662
663impl From<u8> for DebugPortVersion {
664    fn from(value: u8) -> Self {
665        match value {
666            0 => Self::DPv0,
667            1 => Self::DPv1,
668            2 => Self::DPv2,
669            3 => Self::DPv3,
670            value => Self::Unsupported(value),
671        }
672    }
673}