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}