Skip to main content

probe_rs/architecture/arm/
mod.rs

1//! All the interface bits for ARM.
2
3#[macro_use]
4pub mod ap;
5pub(crate) mod communication_interface;
6pub mod component;
7// TODO: Check if this should be public.
8pub mod core;
9pub mod dp;
10pub mod memory;
11pub mod sequences;
12pub mod swo;
13pub(crate) mod traits;
14
15pub use self::core::{Dump, armv6m, armv7ar, armv7m, armv8a, armv8m};
16use self::{
17    ap::AccessPortError,
18    dp::DebugPortError,
19    memory::romtable::RomTableError,
20    sequences::ArmDebugSequenceError,
21    {armv7ar::Armv7arError, armv8a::Armv8aError},
22};
23use crate::{
24    core::memory_mapped_registers::RegisterAddressOutOfBounds,
25    memory::{InvalidDataLengthError, MemoryNotAlignedError},
26    probe::DebugProbeError,
27};
28pub use communication_interface::{
29    ArmChipInfo, ArmCommunicationInterface, ArmDebugInterface, DapError, DapProbe, SwdSequence,
30};
31pub use swo::{SwoAccess, SwoConfig, SwoMode, SwoReader};
32pub use traits::*;
33
34/// A error that occurred while parsing a raw register value.
35#[derive(Debug, thiserror::Error)]
36#[error("Failed to parse register {name} from {value:#010x}")]
37pub struct RegisterParseError {
38    name: &'static str,
39    value: u32,
40}
41
42impl RegisterParseError {
43    /// Creates a new instance of error.
44    pub fn new(name: &'static str, value: u32) -> Self {
45        RegisterParseError { name, value }
46    }
47}
48
49/// ARM-specific errors
50#[derive(Debug, thiserror::Error, docsplay::Display)]
51pub enum ArmError {
52    /// The operation requires one of the following architectures: {0:?}
53    ArchitectureRequired(&'static [&'static str]),
54
55    /// A timeout occurred during an operation.
56    Timeout,
57
58    /// The address is too large for the 32 bit address space.
59    AddressOutOf32BitAddressSpace,
60
61    /// The current target device is not an ARM device.
62    NoArmTarget,
63
64    /// No target responded to the debug port. Check that the target is connected and powered, and that the SWD/JTAG wiring is correct.
65    NoTargetResponse {
66        /// The underlying communication error from the failed debug port read.
67        source: Box<ArmError>,
68    },
69
70    /// Error using access port {address:?}.
71    AccessPort {
72        /// Address of the access port
73        address: FullyQualifiedApAddress,
74        /// Source of the error.
75        source: AccessPortError,
76    },
77
78    /// An error occurred while using a debug port.
79    DebugPort(#[from] DebugPortError),
80
81    /// The core is not currently enabled.
82    CoreDisabled,
83
84    /// The core has to be halted for the operation, but was not.
85    CoreNotHalted,
86
87    /// Performing certain operations (e.g device unlock or Chip-Erase) can leave the device in a
88    /// state that requires a probe re-attach to resolve.
89    ReAttachRequired,
90
91    /// An operation could not be performed because it lacked the permission to do so: {0}
92    ///
93    /// This can for example happen when the core is locked and needs to be erased to be unlocked.
94    /// Then the correct permission needs to be given to automatically unlock the core to prevent
95    /// accidental erases.
96    #[ignore_extra_doc_attributes]
97    MissingPermissions(String),
98
99    /// An error occurred in the communication with an access port or debug port.
100    Dap(#[from] DapError),
101
102    /// The debug probe encountered an error.
103    Probe(#[from] DebugProbeError),
104
105    /// Failed to access address 0x{0.address:08x} as it is not aligned to the requirement of
106    /// {0.alignment} bytes for this platform and API call.
107    MemoryNotAligned(#[from] MemoryNotAlignedError),
108
109    /// A region outside of the AP address space was accessed.
110    OutOfBounds,
111
112    /// {0} bit is not a supported memory transfer width on the current core.
113    UnsupportedTransferWidth(usize),
114
115    /// The AP with address {0:?} does not exist.
116    ApDoesNotExist(FullyQualifiedApAddress),
117
118    /// The AP has the wrong version for the operation.
119    WrongApVersion,
120
121    /// The AP has the wrong type for the operation.
122    WrongApType,
123
124    /// Unable to create a breakpoint at address {0:#010X}. Hardware breakpoints are only supported
125    /// at addresses < 0x2000_0000.
126    UnsupportedBreakpointAddress(u32),
127
128    /// ARMv8a specific error occurred.
129    Armv8a(#[from] Armv8aError),
130
131    /// ARMv7-A/R specific error occurred.
132    Armv7ar(#[from] Armv7arError),
133
134    /// Error occurred in a debug sequence.
135    DebugSequence(#[from] ArmDebugSequenceError),
136
137    /// Tracing has not been configured.
138    TracingUnconfigured,
139
140    /// Error parsing a register.
141    RegisterParse(#[from] RegisterParseError),
142
143    /// Error reading ROM table.
144    RomTable(#[source] RomTableError),
145
146    /// Failed to erase chip.
147    ChipEraseFailed,
148
149    /// The operation requires the following extension(s): {0:?}.
150    ExtensionRequired(&'static [&'static str]),
151
152    /// An error occurred while calculating the address of a register.
153    RegisterAddressOutOfBounds(#[from] RegisterAddressOutOfBounds),
154
155    /// Some required functionality is not implemented: {0}
156    NotImplemented(&'static str),
157
158    /// Invalid data length error: {0}
159    InvalidDataLength(#[from] InvalidDataLengthError),
160
161    /// Another ARM error occurred: {0}
162    Other(String),
163}
164
165impl ArmError {
166    /// Constructs [`ArmError::AccessPort`] from the address and the source error.
167    pub fn from_access_port(err: AccessPortError, ap_address: &FullyQualifiedApAddress) -> Self {
168        ArmError::AccessPort {
169            address: ap_address.clone(),
170            source: err,
171        }
172    }
173
174    /// Constructs a [`ArmError::MemoryNotAligned`] from the address and the required alignment.
175    pub fn alignment_error(address: u64, alignment: usize) -> Self {
176        ArmError::MemoryNotAligned(MemoryNotAlignedError { address, alignment })
177    }
178}
179
180impl From<RomTableError> for ArmError {
181    fn from(value: RomTableError) -> Self {
182        match value {
183            RomTableError::Memory(err) => *err,
184            other => ArmError::RomTable(other),
185        }
186    }
187}
188
189/// Check if the address is a valid 32 bit address. This functions
190/// is ARM specific for ease of use, so that a specific error code can be returned.
191pub fn valid_32bit_arm_address(address: u64) -> Result<u32, ArmError> {
192    address
193        .try_into()
194        .map_err(|_| ArmError::AddressOutOf32BitAddressSpace)
195}