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