probe_rs/architecture/arm/ap/
generic_ap.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//! Generic access port

use crate::architecture::arm::communication_interface::RegisterParseError;

/// Describes the class of an access port defined in the [`ARM Debug Interface v5.2`](https://developer.arm.com/documentation/ihi0031/f/?lang=en) specification.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ApClass {
    /// This describes a custom AP that is vendor defined and not defined by ARM
    #[default]
    Undefined = 0b0000,
    /// The standard ARM COM-AP defined in the [`ARM Debug Interface v5.2`](https://developer.arm.com/documentation/ihi0031/f/?lang=en) specification.
    ComAp = 0b0001,
    /// The standard ARM MEM-AP defined  in the [`ARM Debug Interface v5.2`](https://developer.arm.com/documentation/ihi0031/f/?lang=en) specification
    MemAp = 0b1000,
}

impl ApClass {
    /// Tries to create an `ApClass` from a given `u8`.
    pub fn from_u8(value: u8) -> Option<Self> {
        match value {
            0b0000 => Some(ApClass::Undefined),
            0b0001 => Some(ApClass::ComAp),
            0b1000 => Some(ApClass::MemAp),
            _ => None,
        }
    }
}

/// The type of AP defined in the [`ARM Debug Interface v5.2`](https://developer.arm.com/documentation/ihi0031/f/?lang=en) specification.
/// You can find the details in the table C1-2 on page C1-146.
/// The different types correspond to the different access/memory buses of ARM cores.
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ApType {
    /// This is the most basic AP that is included in most MCUs and uses SWD or JTAG as an access bus.
    #[default]
    JtagComAp = 0x0,
    /// A AMBA based AHB3 AP (see E1.5).
    AmbaAhb3 = 0x1,
    /// A AMBA based APB2 and APB3 AP (see E1.8).
    AmbaApb2Apb3 = 0x2,
    /// A AMBA based AXI3 and AXI4 AP (see E1.2).
    AmbaAxi3Axi4 = 0x4,
    /// A AMBA based AHB5 AP (see E1.6).
    AmbaAhb5 = 0x5,
    /// A AMBA based APB4 and APB5 AP (see E1.9).
    AmbaApb4Apb5 = 0x6,
    /// A AMBA based AXI5 AP (see E1.4).
    AmbaAxi5 = 0x7,
    /// A AMBA based AHB5 AP with enhanced HPROT (see E1.7).
    AmbaAhb5Hprot = 0x8,
}

impl ApType {
    /// Tries to create an `ApType` from a given `u8`.
    pub fn from_u8(value: u8) -> Option<Self> {
        match value {
            0x0 => Some(ApType::JtagComAp),
            0x1 => Some(ApType::AmbaAhb3),
            0x2 => Some(ApType::AmbaApb2Apb3),
            0x4 => Some(ApType::AmbaAxi3Axi4),
            0x5 => Some(ApType::AmbaAhb5),
            0x6 => Some(ApType::AmbaApb4Apb5),
            0x7 => Some(ApType::AmbaAxi5),
            0x8 => Some(ApType::AmbaAhb5Hprot),
            _ => None,
        }
    }
}

define_ap_register!(
    /// Identification Register
    ///
    /// The identification register is used to identify
    /// an AP.
    ///
    /// It has to be present on every AP.
    name: IDR,
    address: 0x0FC,
    fields: [
        /// The revision of this access point.
        REVISION: u8,
        /// The JEP106 code of the designer of this access point.
        DESIGNER: jep106::JEP106Code,
        /// The class of this access point.
        CLASS: ApClass,
        #[doc(hidden)]
        _RES0: u8,
        /// The variant of this access port.
        VARIANT: u8,
        /// The type of this access port.
        TYPE: ApType,
    ],
    from: value => Ok(IDR {
        REVISION: ((value >> 28) & 0x0F) as u8,
        DESIGNER: {
            let designer = ((value >> 17) & 0x7FF) as u16;
            let cc = (designer >> 7) as u8;
            let id = (designer & 0x7f) as u8;

            jep106::JEP106Code::new(cc, id)
        },
        CLASS: ApClass::from_u8(((value >> 13) & 0x0F) as u8).ok_or_else(|| RegisterParseError::new("IDR", value))?,
        _RES0: 0,
        VARIANT: ((value >> 4) & 0x0F) as u8,
        TYPE: ApType::from_u8((value & 0x0F) as u8).ok_or_else(|| RegisterParseError::new("IDR", value))?
    }),
    to: value => (u32::from(value.REVISION) << 28)
        | (((u32::from(value.DESIGNER.cc) << 7) | u32::from(value.DESIGNER.id)) << 17)
        | ((value.CLASS as u32) << 13)
        | (u32::from(value.VARIANT) << 4)
        | (value.TYPE as u32)
);