pyGdbToolkit 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyGdbToolkit/__init__.py +55 -0
- pyGdbToolkit/arch/__init__.py +79 -0
- pyGdbToolkit/arch/arm/__init__.py +17 -0
- pyGdbToolkit/arch/arm/coresight.py +427 -0
- pyGdbToolkit/arch/arm/cortex_m.py +504 -0
- pyGdbToolkit/arch/arm/fault.py +629 -0
- pyGdbToolkit/arch/arm/models.py +60 -0
- pyGdbToolkit/arch/arm/mpu.py +556 -0
- pyGdbToolkit/arch/arm/probe.py +10 -0
- pyGdbToolkit/arch/arm/providers/__init__.py +16 -0
- pyGdbToolkit/arch/arm/providers/base.py +77 -0
- pyGdbToolkit/arch/arm/providers/manufacturers/__init__.py +4 -0
- pyGdbToolkit/arch/arm/providers/manufacturers/stm32.py +680 -0
- pyGdbToolkit/arch/arm/sau.py +253 -0
- pyGdbToolkit/arch/arm/security.py +816 -0
- pyGdbToolkit/arch/arm/session_state.py +96 -0
- pyGdbToolkit/arch/arm/target.py +32 -0
- pyGdbToolkit/arch/base.py +143 -0
- pyGdbToolkit/arch/diagnostics.py +300 -0
- pyGdbToolkit/arch/registry.py +43 -0
- pyGdbToolkit/cmd_faultinfo.py +99 -0
- pyGdbToolkit/cmd_lscpu.py +116 -0
- pyGdbToolkit/cmd_profile.py +1402 -0
- pyGdbToolkit/cmd_rtos.py +298 -0
- pyGdbToolkit/cmd_secscan.py +466 -0
- pyGdbToolkit/cmd_svd.py +1208 -0
- pyGdbToolkit/diagnostic_runtime.py +52 -0
- pyGdbToolkit/rtos/__init__.py +8 -0
- pyGdbToolkit/rtos/camelot.py +513 -0
- pyGdbToolkit/session.py +233 -0
- pyGdbToolkit/svd.py +1194 -0
- pyGdbToolkit/target_memory.py +190 -0
- pygdbtoolkit-0.1.0.dist-info/METADATA +586 -0
- pygdbtoolkit-0.1.0.dist-info/RECORD +36 -0
- pygdbtoolkit-0.1.0.dist-info/WHEEL +5 -0
- pygdbtoolkit-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 H2Lab Development Team
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
"""Cortex-M core descriptions, CPUID decoding, and SCB inspection."""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from enum import IntEnum, StrEnum, unique
|
|
10
|
+
|
|
11
|
+
from ...target_memory import TargetMemory, TargetReadError
|
|
12
|
+
from ..base import Architecture, ProbeResult, RegisterValue, SystemRegisterSet, TargetDescription
|
|
13
|
+
from .mpu import MpuDescription, PMSA_V7_MPU, PMSA_V8_MPU, PMSA_V8_PXN_MPU
|
|
14
|
+
from .sau import ARMV8_M_SAU, SauDescription
|
|
15
|
+
from .target import ArmProfile, ArmTargetDescription
|
|
16
|
+
|
|
17
|
+
SCB_BASE_ADDRESS = 0xE000ED00
|
|
18
|
+
CPUID_ADDRESS = SCB_BASE_ADDRESS
|
|
19
|
+
ARM_IMPLEMENTER = 0x41
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@unique
|
|
23
|
+
class CortexMPart(IntEnum):
|
|
24
|
+
"""Architected Cortex-M CPUID part numbers."""
|
|
25
|
+
|
|
26
|
+
M0 = 0xC20
|
|
27
|
+
M1 = 0xC21
|
|
28
|
+
M3 = 0xC23
|
|
29
|
+
M4 = 0xC24
|
|
30
|
+
M7 = 0xC27
|
|
31
|
+
M0_PLUS = 0xC60
|
|
32
|
+
M23 = 0xD20
|
|
33
|
+
M33 = 0xD21
|
|
34
|
+
M55 = 0xD22
|
|
35
|
+
M85 = 0xD23
|
|
36
|
+
M35P = 0xD31
|
|
37
|
+
M52 = 0xD32
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@unique
|
|
41
|
+
class CortexMArchitecture(StrEnum):
|
|
42
|
+
"""Cortex-M architecture versions represented by the core catalog."""
|
|
43
|
+
|
|
44
|
+
ARMV6_M = "Armv6-M"
|
|
45
|
+
ARMV7_M = "Armv7-M"
|
|
46
|
+
ARMV7E_M = "Armv7E-M"
|
|
47
|
+
ARMV8_M_BASELINE = "Armv8-M Baseline"
|
|
48
|
+
ARMV8_M_MAINLINE = "Armv8-M Mainline"
|
|
49
|
+
ARMV8_1_M_MAINLINE = "Armv8.1-M Mainline"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@unique
|
|
53
|
+
class CortexMFeature(StrEnum):
|
|
54
|
+
"""Architectural feature categories used to describe Cortex-M cores."""
|
|
55
|
+
|
|
56
|
+
CONFIGURABLE_FAULTS = "configurable-faults"
|
|
57
|
+
DSP_EXTENSION = "dsp-extension"
|
|
58
|
+
SECURITY_EXTENSION = "security-extension"
|
|
59
|
+
CACHE_CONTROL = "cache-control"
|
|
60
|
+
AHB_SLAVE_CONTROL = "ahb-slave-control"
|
|
61
|
+
RAS_FAULT_STATUS = "ras-fault-status"
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@unique
|
|
65
|
+
class ScbRegister(IntEnum):
|
|
66
|
+
"""System Control Block register offsets from ``SCB_BASE_ADDRESS``."""
|
|
67
|
+
|
|
68
|
+
CPUID = 0x000
|
|
69
|
+
ICSR = 0x004
|
|
70
|
+
VTOR = 0x008
|
|
71
|
+
AIRCR = 0x00C
|
|
72
|
+
SCR = 0x010
|
|
73
|
+
CCR = 0x014
|
|
74
|
+
SHPR1 = 0x018
|
|
75
|
+
SHPR2 = 0x01C
|
|
76
|
+
SHPR3 = 0x020
|
|
77
|
+
SHCSR = 0x024
|
|
78
|
+
CFSR = 0x028
|
|
79
|
+
HFSR = 0x02C
|
|
80
|
+
DFSR = 0x030
|
|
81
|
+
MMFAR = 0x034
|
|
82
|
+
BFAR = 0x038
|
|
83
|
+
AFSR = 0x03C
|
|
84
|
+
ID_PFR0 = 0x040
|
|
85
|
+
ID_PFR1 = 0x044
|
|
86
|
+
ID_DFR0 = 0x048
|
|
87
|
+
ID_AFR0 = 0x04C
|
|
88
|
+
ID_MMFR0 = 0x050
|
|
89
|
+
ID_MMFR1 = 0x054
|
|
90
|
+
ID_MMFR2 = 0x058
|
|
91
|
+
ID_MMFR3 = 0x05C
|
|
92
|
+
ID_ISAR0 = 0x060
|
|
93
|
+
ID_ISAR1 = 0x064
|
|
94
|
+
ID_ISAR2 = 0x068
|
|
95
|
+
ID_ISAR3 = 0x06C
|
|
96
|
+
ID_ISAR4 = 0x070
|
|
97
|
+
ID_ISAR5 = 0x074
|
|
98
|
+
CLIDR = 0x078
|
|
99
|
+
CTR = 0x07C
|
|
100
|
+
CCSIDR = 0x080
|
|
101
|
+
CSSELR = 0x084
|
|
102
|
+
CPACR = 0x088
|
|
103
|
+
NSACR = 0x08C
|
|
104
|
+
SFSR = 0x0E4
|
|
105
|
+
SFAR = 0x0E8
|
|
106
|
+
RFSR = 0x204
|
|
107
|
+
AHBSCR = 0x2A0
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@dataclass(frozen=True)
|
|
111
|
+
class CortexMCoreDescription:
|
|
112
|
+
"""Immutable architectural description for one Cortex-M CPUID part."""
|
|
113
|
+
|
|
114
|
+
part: CortexMPart
|
|
115
|
+
core_name: str
|
|
116
|
+
architecture_version: CortexMArchitecture
|
|
117
|
+
features: frozenset[CortexMFeature]
|
|
118
|
+
scb_registers: tuple[ScbRegister, ...]
|
|
119
|
+
mpu: MpuDescription | None
|
|
120
|
+
sau: SauDescription | None = None
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@dataclass(frozen=True)
|
|
124
|
+
class CortexMTargetDescription(ArmTargetDescription):
|
|
125
|
+
"""Decoded Cortex-M target identity from its architected CPUID register."""
|
|
126
|
+
|
|
127
|
+
raw_cpuid: int
|
|
128
|
+
implementer: int
|
|
129
|
+
variant: int
|
|
130
|
+
cpuid_architecture: int
|
|
131
|
+
part_number: int
|
|
132
|
+
patch: int
|
|
133
|
+
core: CortexMCoreDescription | None
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def rnp_revision(self) -> str:
|
|
137
|
+
"""Return the standard Arm rNp revision notation."""
|
|
138
|
+
return f"r{self.variant}p{self.patch}"
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def implementer_name(self) -> str:
|
|
142
|
+
"""Return the output-compatible CPUID implementer display name."""
|
|
143
|
+
if self.implementer == ARM_IMPLEMENTER:
|
|
144
|
+
return "Arm"
|
|
145
|
+
return f"Unknown (0x{self.implementer:02X})"
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
_BASELINE_SCB = (
|
|
149
|
+
ScbRegister.CPUID,
|
|
150
|
+
ScbRegister.ICSR,
|
|
151
|
+
ScbRegister.AIRCR,
|
|
152
|
+
ScbRegister.SCR,
|
|
153
|
+
ScbRegister.CCR,
|
|
154
|
+
ScbRegister.SHPR2,
|
|
155
|
+
ScbRegister.SHPR3,
|
|
156
|
+
ScbRegister.SHCSR,
|
|
157
|
+
)
|
|
158
|
+
_BASELINE_WITH_VTOR_SCB = _BASELINE_SCB[:2] + (ScbRegister.VTOR,) + _BASELINE_SCB[2:]
|
|
159
|
+
_BASELINE_SECURITY_SCB = _BASELINE_WITH_VTOR_SCB + (
|
|
160
|
+
ScbRegister.SFSR,
|
|
161
|
+
ScbRegister.SFAR,
|
|
162
|
+
)
|
|
163
|
+
_MAINLINE_SCB = (
|
|
164
|
+
ScbRegister.CPUID,
|
|
165
|
+
ScbRegister.ICSR,
|
|
166
|
+
ScbRegister.VTOR,
|
|
167
|
+
ScbRegister.AIRCR,
|
|
168
|
+
ScbRegister.SCR,
|
|
169
|
+
ScbRegister.CCR,
|
|
170
|
+
ScbRegister.SHPR1,
|
|
171
|
+
ScbRegister.SHPR2,
|
|
172
|
+
ScbRegister.SHPR3,
|
|
173
|
+
ScbRegister.SHCSR,
|
|
174
|
+
ScbRegister.CFSR,
|
|
175
|
+
ScbRegister.HFSR,
|
|
176
|
+
ScbRegister.DFSR,
|
|
177
|
+
ScbRegister.MMFAR,
|
|
178
|
+
ScbRegister.BFAR,
|
|
179
|
+
ScbRegister.AFSR,
|
|
180
|
+
ScbRegister.ID_PFR0,
|
|
181
|
+
ScbRegister.ID_PFR1,
|
|
182
|
+
ScbRegister.ID_DFR0,
|
|
183
|
+
ScbRegister.ID_AFR0,
|
|
184
|
+
ScbRegister.ID_MMFR0,
|
|
185
|
+
ScbRegister.ID_MMFR1,
|
|
186
|
+
ScbRegister.ID_MMFR2,
|
|
187
|
+
ScbRegister.ID_MMFR3,
|
|
188
|
+
ScbRegister.ID_ISAR0,
|
|
189
|
+
ScbRegister.ID_ISAR1,
|
|
190
|
+
ScbRegister.ID_ISAR2,
|
|
191
|
+
ScbRegister.ID_ISAR3,
|
|
192
|
+
ScbRegister.ID_ISAR4,
|
|
193
|
+
ScbRegister.CPACR,
|
|
194
|
+
)
|
|
195
|
+
_MAINLINE_WITH_CACHE_SCB = _MAINLINE_SCB + (
|
|
196
|
+
ScbRegister.CLIDR,
|
|
197
|
+
ScbRegister.CTR,
|
|
198
|
+
ScbRegister.CCSIDR,
|
|
199
|
+
ScbRegister.CSSELR,
|
|
200
|
+
ScbRegister.AHBSCR,
|
|
201
|
+
)
|
|
202
|
+
_MAINLINE_WITH_CACHES_SCB = _MAINLINE_SCB + (
|
|
203
|
+
ScbRegister.CLIDR,
|
|
204
|
+
ScbRegister.CTR,
|
|
205
|
+
ScbRegister.CCSIDR,
|
|
206
|
+
ScbRegister.CSSELR,
|
|
207
|
+
)
|
|
208
|
+
_V8_MAINLINE_CORE_SCB = _MAINLINE_SCB[:-1] + (
|
|
209
|
+
ScbRegister.ID_ISAR5,
|
|
210
|
+
ScbRegister.CPACR,
|
|
211
|
+
)
|
|
212
|
+
_V8_MAINLINE_SCB = _V8_MAINLINE_CORE_SCB + (
|
|
213
|
+
ScbRegister.NSACR,
|
|
214
|
+
ScbRegister.SFSR,
|
|
215
|
+
ScbRegister.SFAR,
|
|
216
|
+
)
|
|
217
|
+
_V8_1_MAINLINE_SCB = _V8_MAINLINE_CORE_SCB + (
|
|
218
|
+
ScbRegister.CLIDR,
|
|
219
|
+
ScbRegister.CTR,
|
|
220
|
+
ScbRegister.CCSIDR,
|
|
221
|
+
ScbRegister.CSSELR,
|
|
222
|
+
ScbRegister.NSACR,
|
|
223
|
+
ScbRegister.SFSR,
|
|
224
|
+
ScbRegister.SFAR,
|
|
225
|
+
ScbRegister.RFSR,
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
CORTEX_M_CORES: dict[CortexMPart, CortexMCoreDescription] = {
|
|
229
|
+
CortexMPart.M0: CortexMCoreDescription(
|
|
230
|
+
CortexMPart.M0,
|
|
231
|
+
"Cortex-M0",
|
|
232
|
+
CortexMArchitecture.ARMV6_M,
|
|
233
|
+
frozenset(),
|
|
234
|
+
_BASELINE_SCB,
|
|
235
|
+
None,
|
|
236
|
+
),
|
|
237
|
+
CortexMPart.M1: CortexMCoreDescription(
|
|
238
|
+
CortexMPart.M1,
|
|
239
|
+
"Cortex-M1",
|
|
240
|
+
CortexMArchitecture.ARMV6_M,
|
|
241
|
+
frozenset(),
|
|
242
|
+
_BASELINE_SCB,
|
|
243
|
+
None,
|
|
244
|
+
),
|
|
245
|
+
CortexMPart.M0_PLUS: CortexMCoreDescription(
|
|
246
|
+
CortexMPart.M0_PLUS,
|
|
247
|
+
"Cortex-M0+",
|
|
248
|
+
CortexMArchitecture.ARMV6_M,
|
|
249
|
+
frozenset(),
|
|
250
|
+
_BASELINE_WITH_VTOR_SCB,
|
|
251
|
+
None,
|
|
252
|
+
),
|
|
253
|
+
CortexMPart.M3: CortexMCoreDescription(
|
|
254
|
+
CortexMPart.M3,
|
|
255
|
+
"Cortex-M3",
|
|
256
|
+
CortexMArchitecture.ARMV7_M,
|
|
257
|
+
frozenset({CortexMFeature.CONFIGURABLE_FAULTS}),
|
|
258
|
+
_MAINLINE_SCB,
|
|
259
|
+
PMSA_V7_MPU,
|
|
260
|
+
),
|
|
261
|
+
CortexMPart.M4: CortexMCoreDescription(
|
|
262
|
+
CortexMPart.M4,
|
|
263
|
+
"Cortex-M4",
|
|
264
|
+
CortexMArchitecture.ARMV7E_M,
|
|
265
|
+
frozenset({CortexMFeature.CONFIGURABLE_FAULTS, CortexMFeature.DSP_EXTENSION}),
|
|
266
|
+
_MAINLINE_SCB,
|
|
267
|
+
PMSA_V7_MPU,
|
|
268
|
+
),
|
|
269
|
+
CortexMPart.M7: CortexMCoreDescription(
|
|
270
|
+
CortexMPart.M7,
|
|
271
|
+
"Cortex-M7",
|
|
272
|
+
CortexMArchitecture.ARMV7E_M,
|
|
273
|
+
frozenset(
|
|
274
|
+
{
|
|
275
|
+
CortexMFeature.CONFIGURABLE_FAULTS,
|
|
276
|
+
CortexMFeature.DSP_EXTENSION,
|
|
277
|
+
CortexMFeature.CACHE_CONTROL,
|
|
278
|
+
CortexMFeature.AHB_SLAVE_CONTROL,
|
|
279
|
+
}
|
|
280
|
+
),
|
|
281
|
+
_MAINLINE_WITH_CACHE_SCB,
|
|
282
|
+
PMSA_V7_MPU,
|
|
283
|
+
),
|
|
284
|
+
CortexMPart.M23: CortexMCoreDescription(
|
|
285
|
+
CortexMPart.M23,
|
|
286
|
+
"Cortex-M23",
|
|
287
|
+
CortexMArchitecture.ARMV8_M_BASELINE,
|
|
288
|
+
frozenset({CortexMFeature.SECURITY_EXTENSION}),
|
|
289
|
+
_BASELINE_SECURITY_SCB,
|
|
290
|
+
PMSA_V8_MPU,
|
|
291
|
+
ARMV8_M_SAU,
|
|
292
|
+
),
|
|
293
|
+
CortexMPart.M33: CortexMCoreDescription(
|
|
294
|
+
CortexMPart.M33,
|
|
295
|
+
"Cortex-M33",
|
|
296
|
+
CortexMArchitecture.ARMV8_M_MAINLINE,
|
|
297
|
+
frozenset({CortexMFeature.CONFIGURABLE_FAULTS, CortexMFeature.SECURITY_EXTENSION}),
|
|
298
|
+
_V8_MAINLINE_SCB,
|
|
299
|
+
PMSA_V8_MPU,
|
|
300
|
+
ARMV8_M_SAU,
|
|
301
|
+
),
|
|
302
|
+
CortexMPart.M35P: CortexMCoreDescription(
|
|
303
|
+
CortexMPart.M35P,
|
|
304
|
+
"Cortex-M35P",
|
|
305
|
+
CortexMArchitecture.ARMV8_M_MAINLINE,
|
|
306
|
+
frozenset({CortexMFeature.CONFIGURABLE_FAULTS, CortexMFeature.SECURITY_EXTENSION}),
|
|
307
|
+
_V8_MAINLINE_SCB,
|
|
308
|
+
PMSA_V8_MPU,
|
|
309
|
+
ARMV8_M_SAU,
|
|
310
|
+
),
|
|
311
|
+
CortexMPart.M52: CortexMCoreDescription(
|
|
312
|
+
CortexMPart.M52,
|
|
313
|
+
"Cortex-M52",
|
|
314
|
+
CortexMArchitecture.ARMV8_1_M_MAINLINE,
|
|
315
|
+
frozenset(
|
|
316
|
+
{
|
|
317
|
+
CortexMFeature.CONFIGURABLE_FAULTS,
|
|
318
|
+
CortexMFeature.SECURITY_EXTENSION,
|
|
319
|
+
CortexMFeature.CACHE_CONTROL,
|
|
320
|
+
CortexMFeature.RAS_FAULT_STATUS,
|
|
321
|
+
}
|
|
322
|
+
),
|
|
323
|
+
_V8_1_MAINLINE_SCB,
|
|
324
|
+
PMSA_V8_PXN_MPU,
|
|
325
|
+
ARMV8_M_SAU,
|
|
326
|
+
),
|
|
327
|
+
CortexMPart.M55: CortexMCoreDescription(
|
|
328
|
+
CortexMPart.M55,
|
|
329
|
+
"Cortex-M55",
|
|
330
|
+
CortexMArchitecture.ARMV8_1_M_MAINLINE,
|
|
331
|
+
frozenset(
|
|
332
|
+
{
|
|
333
|
+
CortexMFeature.CONFIGURABLE_FAULTS,
|
|
334
|
+
CortexMFeature.SECURITY_EXTENSION,
|
|
335
|
+
CortexMFeature.CACHE_CONTROL,
|
|
336
|
+
CortexMFeature.RAS_FAULT_STATUS,
|
|
337
|
+
}
|
|
338
|
+
),
|
|
339
|
+
_V8_1_MAINLINE_SCB,
|
|
340
|
+
PMSA_V8_PXN_MPU,
|
|
341
|
+
ARMV8_M_SAU,
|
|
342
|
+
),
|
|
343
|
+
CortexMPart.M85: CortexMCoreDescription(
|
|
344
|
+
CortexMPart.M85,
|
|
345
|
+
"Cortex-M85",
|
|
346
|
+
CortexMArchitecture.ARMV8_1_M_MAINLINE,
|
|
347
|
+
frozenset(
|
|
348
|
+
{
|
|
349
|
+
CortexMFeature.CONFIGURABLE_FAULTS,
|
|
350
|
+
CortexMFeature.SECURITY_EXTENSION,
|
|
351
|
+
CortexMFeature.CACHE_CONTROL,
|
|
352
|
+
CortexMFeature.RAS_FAULT_STATUS,
|
|
353
|
+
}
|
|
354
|
+
),
|
|
355
|
+
_V8_1_MAINLINE_SCB,
|
|
356
|
+
PMSA_V8_PXN_MPU,
|
|
357
|
+
ARMV8_M_SAU,
|
|
358
|
+
),
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def decode_cpuid(raw: int) -> CortexMTargetDescription:
|
|
363
|
+
"""Decode an architected Cortex-M CPUID register value.
|
|
364
|
+
|
|
365
|
+
Parameters
|
|
366
|
+
----------
|
|
367
|
+
raw
|
|
368
|
+
The unsigned 32-bit CPUID value from the System Control Block.
|
|
369
|
+
|
|
370
|
+
Returns
|
|
371
|
+
-------
|
|
372
|
+
CortexMTargetDescription
|
|
373
|
+
Core identity, revision, and a registered core description when known.
|
|
374
|
+
|
|
375
|
+
Raises
|
|
376
|
+
------
|
|
377
|
+
ValueError
|
|
378
|
+
If ``raw`` is outside the unsigned 32-bit CPUID range.
|
|
379
|
+
"""
|
|
380
|
+
if not 0 <= raw <= 0xFFFFFFFF:
|
|
381
|
+
raise ValueError("CPUID must be an unsigned 32-bit value")
|
|
382
|
+
|
|
383
|
+
implementer = raw >> 24
|
|
384
|
+
variant = (raw >> 20) & 0xF
|
|
385
|
+
cpuid_architecture = (raw >> 16) & 0xF
|
|
386
|
+
part_number = (raw >> 4) & 0xFFF
|
|
387
|
+
patch = raw & 0xF
|
|
388
|
+
part = _cortex_m_part(part_number)
|
|
389
|
+
core = CORTEX_M_CORES.get(part) if part is not None else None
|
|
390
|
+
core_name = core.core_name if core is not None else f"Unknown Cortex-M part 0x{part_number:03X}"
|
|
391
|
+
return CortexMTargetDescription(
|
|
392
|
+
architecture=Architecture.ARM,
|
|
393
|
+
family="Arm",
|
|
394
|
+
core_name=core_name,
|
|
395
|
+
revision=f"r{variant}p{patch}",
|
|
396
|
+
profile=ArmProfile.CORTEX_M,
|
|
397
|
+
raw_cpuid=raw,
|
|
398
|
+
implementer=implementer,
|
|
399
|
+
variant=variant,
|
|
400
|
+
cpuid_architecture=cpuid_architecture,
|
|
401
|
+
part_number=part_number,
|
|
402
|
+
patch=patch,
|
|
403
|
+
core=core,
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def read_scb(
|
|
408
|
+
reader: TargetMemory,
|
|
409
|
+
target: CortexMTargetDescription,
|
|
410
|
+
*,
|
|
411
|
+
cpuid_value: int | None = None,
|
|
412
|
+
) -> SystemRegisterSet:
|
|
413
|
+
"""Read the SCB registers applicable to a known Cortex-M core.
|
|
414
|
+
|
|
415
|
+
Parameters
|
|
416
|
+
----------
|
|
417
|
+
reader
|
|
418
|
+
Target-memory reader used for 32-bit SCB accesses.
|
|
419
|
+
target
|
|
420
|
+
Cortex-M description returned by :func:`decode_cpuid`.
|
|
421
|
+
cpuid_value
|
|
422
|
+
Optional already-read CPUID value used to avoid a duplicate target read.
|
|
423
|
+
|
|
424
|
+
Returns
|
|
425
|
+
-------
|
|
426
|
+
SystemRegisterSet
|
|
427
|
+
An ``SCB`` block containing available values and individual read errors.
|
|
428
|
+
"""
|
|
429
|
+
if target.core is None:
|
|
430
|
+
return SystemRegisterSet(Architecture.ARM, "SCB", ())
|
|
431
|
+
|
|
432
|
+
register_values: list[RegisterValue] = []
|
|
433
|
+
for register in target.core.scb_registers:
|
|
434
|
+
address = SCB_BASE_ADDRESS + register.value
|
|
435
|
+
if register is ScbRegister.CPUID and cpuid_value is not None:
|
|
436
|
+
register_values.append(RegisterValue.known(register.name, address, 32, cpuid_value))
|
|
437
|
+
continue
|
|
438
|
+
try:
|
|
439
|
+
value = reader.read_uint32(address)
|
|
440
|
+
except TargetReadError as error:
|
|
441
|
+
register_values.append(
|
|
442
|
+
RegisterValue.unavailable(register.name, address, 32, str(error))
|
|
443
|
+
)
|
|
444
|
+
else:
|
|
445
|
+
register_values.append(RegisterValue.known(register.name, address, 32, value))
|
|
446
|
+
return SystemRegisterSet(Architecture.ARM, "SCB", tuple(register_values))
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def inspect_cortex_m(reader: TargetMemory) -> tuple[CortexMTargetDescription, SystemRegisterSet]:
|
|
450
|
+
"""Read CPUID then inspect the SCB register set selected by its core part.
|
|
451
|
+
|
|
452
|
+
Parameters
|
|
453
|
+
----------
|
|
454
|
+
reader
|
|
455
|
+
Target-memory reader used for CPUID and SCB accesses.
|
|
456
|
+
|
|
457
|
+
Returns
|
|
458
|
+
-------
|
|
459
|
+
tuple[CortexMTargetDescription, SystemRegisterSet]
|
|
460
|
+
Decoded target description and its known-core SCB register results.
|
|
461
|
+
"""
|
|
462
|
+
raw_cpuid = reader.read_uint32(CPUID_ADDRESS)
|
|
463
|
+
target = decode_cpuid(raw_cpuid)
|
|
464
|
+
return target, read_scb(reader, target, cpuid_value=raw_cpuid)
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
class CortexMProbe:
|
|
468
|
+
"""Registry adapter for recognized Cortex-M CPUID parts."""
|
|
469
|
+
|
|
470
|
+
architecture = Architecture.ARM
|
|
471
|
+
|
|
472
|
+
def probe(self, reader: TargetMemory) -> ProbeResult:
|
|
473
|
+
"""Recognize a known Cortex-M part from CPUID."""
|
|
474
|
+
try:
|
|
475
|
+
target = decode_cpuid(reader.read_uint32(CPUID_ADDRESS))
|
|
476
|
+
except TargetReadError as error:
|
|
477
|
+
return ProbeResult.unavailable(
|
|
478
|
+
f"could not read Cortex-M CPUID: {error}", access_error=True
|
|
479
|
+
)
|
|
480
|
+
if target.implementer != ARM_IMPLEMENTER or target.cpuid_architecture not in (0xC, 0xF):
|
|
481
|
+
return ProbeResult.unavailable("CPUID does not identify an Arm Cortex-M architecture")
|
|
482
|
+
if target.core is None:
|
|
483
|
+
return ProbeResult.unavailable(
|
|
484
|
+
f"unrecognized Cortex-M CPUID part 0x{target.part_number:03X}"
|
|
485
|
+
)
|
|
486
|
+
return ProbeResult.detected(target)
|
|
487
|
+
|
|
488
|
+
def read_system_registers(
|
|
489
|
+
self,
|
|
490
|
+
reader: TargetMemory,
|
|
491
|
+
target: TargetDescription,
|
|
492
|
+
) -> SystemRegisterSet:
|
|
493
|
+
"""Read SCB registers for a target returned by this probe."""
|
|
494
|
+
if not isinstance(target, CortexMTargetDescription):
|
|
495
|
+
raise ValueError("CortexMProbe requires a CortexMTargetDescription")
|
|
496
|
+
return read_scb(reader, target)
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
def _cortex_m_part(part_number: int) -> CortexMPart | None:
|
|
500
|
+
"""Convert a raw 12-bit part number to its enum member when known."""
|
|
501
|
+
try:
|
|
502
|
+
return CortexMPart(part_number)
|
|
503
|
+
except ValueError:
|
|
504
|
+
return None
|