probe_rs_target/chip.rs
1use std::collections::HashMap;
2
3use super::memory::MemoryRegion;
4use crate::{
5 CoreType,
6 serialize::{hex_option, hex_u_int},
7};
8use serde::{Deserialize, Serialize};
9
10/// Represents a DAP scan chain element.
11#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
12pub struct ScanChainElement {
13 /// Unique name of the DAP
14 pub name: Option<String>,
15 /// Specifies the IR length of the DAP (default value: 4).
16 pub ir_len: Option<u8>,
17}
18
19impl ScanChainElement {
20 /// Returns the IR length, or 4 if not specified.
21 pub fn ir_len(&self) -> u8 {
22 self.ir_len.unwrap_or(4)
23 }
24}
25
26/// Configuration for JTAG tunneling.
27///
28/// This JTAG tunnel wraps JTAG IR and DR accesses as DR access to a specific instruction. For
29/// example, this can be used to access a Risc-V core in an FPGA using the same JTAG cable that
30/// configures the FPGA.
31#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
32pub struct RiscvJtagTunnel {
33 /// JTAG instruction used to tunnel
34 pub ir_id: u32,
35
36 /// Width of tunneled JTAG instruction register
37 pub ir_width: u32,
38}
39
40/// Configuration for JTAG probes.
41#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
42pub struct Jtag {
43 /// Describes the scan chain
44 ///
45 /// ref: `<https://open-cmsis-pack.github.io/Open-CMSIS-Pack-Spec/main/html/sdf_pg.html#sdf_element_scanchain>`
46 #[serde(default)]
47 pub scan_chain: Option<Vec<ScanChainElement>>,
48
49 /// When set to `true`, the scan chain described in `scan_chain` is used as-is, bypassing
50 /// the JTAG auto-detection (DR/IR scan). This is required for targets whose JTAG TAP does
51 /// not respond to the standard IDCODE scan (e.g., some RISC-V cores during early power-up).
52 ///
53 /// When `false` (the default), `scan_chain` is treated as a hint for IR-length disambiguation
54 /// during the normal auto-detection scan.
55 #[serde(default)]
56 pub force_scan_chain: bool,
57
58 /// Describes JTAG tunnel for Risc-V
59 #[serde(default)]
60 pub riscv_tunnel: Option<RiscvJtagTunnel>,
61}
62
63/// A single chip variant.
64///
65/// This describes an exact chip variant, including the cores, flash and memory size. For example,
66/// the `nRF52832` chip has two variants, `nRF52832_xxAA` and `nRF52832_xxBB`. For this case,
67/// the struct will correspond to one of the variants, e.g. `nRF52832_xxAA`.
68#[derive(Debug, Clone, Serialize, Deserialize)]
69#[serde(deny_unknown_fields)]
70pub struct Chip {
71 /// This is the name of the chip in base form.
72 /// E.g. `nRF52832`.
73 pub name: String,
74 /// The `PART` register of the chip.
75 /// This value can be determined via the `cli info` command.
76 pub part: Option<u16>,
77 /// An URL to the SVD file for this chip.
78 pub svd: Option<String>,
79 /// Documentation URLs associated with this chip.
80 #[serde(default)]
81 pub documentation: HashMap<String, String>,
82 /// The package variants available for this chip.
83 ///
84 /// If empty, the chip is assumed to have only one package variant.
85 #[serde(default)]
86 pub package_variants: Vec<String>,
87 /// The cores available on the chip.
88 #[serde(default)]
89 pub cores: Vec<Core>,
90 /// The memory regions available on the chip.
91 pub memory_map: Vec<MemoryRegion>,
92 /// Names of all flash algorithms available for this chip.
93 ///
94 /// This can be used to look up the flash algorithm in the
95 /// [`ChipFamily::flash_algorithms`] field.
96 ///
97 /// [`ChipFamily::flash_algorithms`]: crate::ChipFamily::flash_algorithms
98 #[serde(default)]
99 pub flash_algorithms: Vec<String>,
100 /// Specific memory ranges to search for a dynamic RTT header for code
101 /// running on this chip.
102 ///
103 /// This need not be specified for most chips because the default is
104 /// to search all RAM regions specified in `memory_map`. However,
105 /// that behavior isn't appropriate for some chips, such as those which
106 /// have a very large amount of RAM that would be time-consuming to
107 /// scan exhaustively.
108 ///
109 /// If specified then this is a list of zero or more address ranges to
110 /// scan. Each address range must be enclosed in exactly one RAM region
111 /// from `memory_map`. An empty list disables automatic scanning
112 /// altogether, in which case RTT will be enabled only when using an
113 /// executable image that includes the `_SEGGER_RTT` symbol pointing
114 /// to the exact address of the RTT header.
115 pub rtt_scan_ranges: Option<Vec<std::ops::Range<u64>>>,
116 /// JTAG-specific options
117 #[serde(default)]
118 pub jtag: Option<Jtag>,
119 /// The default binary format for this chip
120 // TODO: rename to default_platform
121 #[serde(default)]
122 pub default_binary_format: Option<String>,
123}
124
125impl Chip {
126 /// Create a generic chip with the given name, a single core,
127 /// and no flash algorithm or memory map. Used to create
128 /// generic targets.
129 pub fn generic_arm(name: &str, core_type: CoreType) -> Self {
130 Chip {
131 name: name.to_string(),
132 part: None,
133 svd: None,
134 documentation: HashMap::new(),
135 package_variants: vec![],
136 cores: vec![Core {
137 name: "main".to_string(),
138 core_type,
139 core_access_options: CoreAccessOptions::Arm(ArmCoreAccessOptions::default()),
140 }],
141 memory_map: vec![],
142 flash_algorithms: vec![],
143 rtt_scan_ranges: None,
144 jtag: None,
145 default_binary_format: None,
146 }
147 }
148
149 /// Returns the package variants for this chip.
150 pub fn package_variants(&self) -> impl Iterator<Item = &String> {
151 std::slice::from_ref(&self.name)
152 .iter()
153 .chain(self.package_variants.iter())
154 }
155}
156
157/// An individual core inside a chip
158#[derive(Debug, Clone, Serialize, Deserialize)]
159pub struct Core {
160 /// The core name.
161 pub name: String,
162
163 /// The core type.
164 /// E.g. `M0` or `M4`.
165 #[serde(rename = "type")]
166 pub core_type: CoreType,
167
168 /// The AP number to access the core
169 pub core_access_options: CoreAccessOptions,
170}
171
172/// The data required to access a core
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub enum CoreAccessOptions {
175 /// ARM specific options
176 Arm(ArmCoreAccessOptions),
177 /// RISC-V specific options
178 Riscv(RiscvCoreAccessOptions),
179 /// Xtensa specific options
180 Xtensa(XtensaCoreAccessOptions),
181}
182
183/// An address for AP accesses
184#[derive(Debug, Clone, Serialize, Deserialize)]
185pub enum ApAddress {
186 /// References an address for an APv1 access, which is part of the ADIv5 specification.
187 #[serde(rename = "v1")]
188 V1(u8),
189 /// References an address for an APv2 access, which is part of the ADIv6 specification.
190 ///
191 /// # Note
192 /// This represents a base address within the root DP memory space.
193 #[serde(rename = "v2")]
194 #[serde(serialize_with = "hex_u_int")]
195 V2(u64),
196}
197
198impl Default for ApAddress {
199 fn default() -> Self {
200 ApAddress::V1(0)
201 }
202}
203
204/// The data required to access an ARM core
205#[derive(Debug, Clone, Serialize, Deserialize, Default)]
206#[serde(deny_unknown_fields)]
207pub struct ArmCoreAccessOptions {
208 /// The access port number to access the core
209 pub ap: ApAddress,
210 /// The TARGETSEL value used to access the core
211 #[serde(serialize_with = "hex_option")]
212 pub targetsel: Option<u32>,
213 /// The base address of the debug registers for the core.
214 /// Required for Cortex-A, optional for Cortex-M
215 #[serde(serialize_with = "hex_option")]
216 pub debug_base: Option<u64>,
217 /// The base address of the cross trigger interface (CTI) for the core.
218 /// Required in ARMv8-A
219 #[serde(serialize_with = "hex_option")]
220 pub cti_base: Option<u64>,
221
222 /// The JTAG TAP index of the core's debug module
223 pub jtag_tap: Option<usize>,
224}
225
226/// The data required to access a Risc-V core
227#[derive(Debug, Clone, Serialize, Deserialize)]
228pub struct RiscvCoreAccessOptions {
229 /// The hart id
230 pub hart_id: Option<u32>,
231
232 /// The JTAG TAP index of the core's debug module
233 pub jtag_tap: Option<usize>,
234
235 /// CoreSight/mem-AP to use as DTM. This is the method used for RP235x
236 #[serde(default)]
237 pub mem_ap: Option<ApAddress>,
238}
239
240/// The data required to access an Xtensa core
241#[derive(Debug, Clone, Serialize, Deserialize)]
242pub struct XtensaCoreAccessOptions {
243 /// The JTAG TAP index of the core's debug module
244 pub jtag_tap: Option<usize>,
245}