1use anyhow::Result;
6use clap::Args;
7use serde::{Deserialize, Serialize};
8use thiserror::Error;
9
10use std::path::PathBuf;
11use std::time::Duration;
12
13use crate::app::TransportWrapper;
14use crate::debug::openocd::OpenOcd;
15use crate::dif::lc_ctrl::LcCtrlReg;
16use crate::impl_serializable_error;
17
18#[derive(Debug, Args, Clone)]
19pub struct JtagParams {
20 #[arg(long, default_value = "openocd")]
22 pub openocd: PathBuf,
23
24 #[arg(long, default_value = "1000")]
25 pub adapter_speed_khz: u64,
26
27 #[arg(long, default_value = "false")]
28 pub log_stdio: bool,
29}
30
31impl JtagParams {
32 pub fn create<'t>(&self, transport: &'t TransportWrapper) -> Result<Box<dyn JtagChain + 't>> {
33 let jtag = transport.jtag(self)?;
34 Ok(jtag)
35 }
36}
37
38#[derive(Error, Debug, Deserialize, Serialize)]
40pub enum JtagError {
41 #[error("Operation not valid on selected JTAG TAP: {0:?}")]
42 Tap(JtagTap),
43 #[error("JTAG timeout")]
44 Timeout,
45 #[error("JTAG busy")]
46 Busy,
47 #[error("Generic error {0}")]
48 Generic(String),
49}
50impl_serializable_error!(JtagError);
51
52pub trait JtagChain {
58 fn connect(self: Box<Self>, tap: JtagTap) -> Result<Box<dyn Jtag>>;
60
61 fn into_raw(self: Box<Self>) -> Result<OpenOcd>;
63}
64
65pub trait Jtag {
67 fn into_raw(self: Box<Self>) -> Result<OpenOcd>;
69
70 fn as_raw(&mut self) -> Result<&mut OpenOcd>;
72
73 fn disconnect(self: Box<Self>) -> Result<()>;
75 fn tap(&self) -> JtagTap;
77
78 fn read_lc_ctrl_reg(&mut self, reg: &LcCtrlReg) -> Result<u32>;
80
81 fn write_lc_ctrl_reg(&mut self, reg: &LcCtrlReg, value: u32) -> Result<()>;
83
84 fn read_memory(&mut self, addr: u32, buf: &mut [u8]) -> Result<usize>;
91 fn read_memory32(&mut self, addr: u32, buf: &mut [u32]) -> Result<usize>;
92
93 fn write_memory(&mut self, addr: u32, buf: &[u8]) -> Result<()>;
95 fn write_memory32(&mut self, addr: u32, buf: &[u32]) -> Result<()>;
96
97 fn halt(&mut self) -> Result<()>;
99
100 fn wait_halt(&mut self, timeout: Duration) -> Result<()>;
102
103 fn resume(&mut self) -> Result<()>;
105 fn resume_at(&mut self, addr: u32) -> Result<()>;
107
108 fn step(&mut self) -> Result<()>;
110 fn step_at(&mut self, addr: u32) -> Result<()>;
112
113 fn reset(&mut self, run: bool) -> Result<()>;
117
118 fn read_riscv_reg(&mut self, reg: &RiscvReg) -> Result<u32>;
120 fn write_riscv_reg(&mut self, reg: &RiscvReg, val: u32) -> Result<()>;
121
122 fn set_breakpoint(&mut self, addr: u32, hw: bool) -> Result<()>;
124 fn remove_breakpoint(&mut self, addr: u32) -> Result<()>;
125 fn remove_all_breakpoints(&mut self) -> Result<()>;
126}
127
128#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq)]
130pub enum JtagTap {
131 RiscvTap,
133 LcTap,
135}
136
137#[derive(Clone, Copy, Debug, Deserialize, Serialize, strum::IntoStaticStr)]
139#[strum(serialize_all = "lowercase")]
140pub enum RiscvGpr {
141 RA,
142 SP,
143 GP,
144 TP,
145 T0,
146 T1,
147 T2,
148 FP,
149 S1,
150 A0,
151 A1,
152 A2,
153 A3,
154 A4,
155 A5,
156 A6,
157 A7,
158 S2,
159 S3,
160 S4,
161 S5,
162 S6,
163 S7,
164 S8,
165 S9,
166 S10,
167 S11,
168 T3,
169 T4,
170 T5,
171 T6,
172}
173
174impl RiscvGpr {
175 pub fn name(self) -> &'static str {
177 self.into()
178 }
179}
180
181#[derive(Clone, Copy, Debug, Deserialize, Serialize, strum::IntoStaticStr)]
183#[strum(serialize_all = "lowercase")]
184#[non_exhaustive]
185pub enum RiscvCsr {
186 MSTATUS,
187 MISA,
188 MIE,
189 MTVEC,
190 MCOUNTINHIBIT,
191 MHPMEVENT3,
192 MHPMEVENT4,
193 MHPMEVENT5,
194 MHPMEVENT6,
195 MHPMEVENT7,
196 MHPMEVENT8,
197 MHPMEVENT9,
198 MHPMEVENT10,
199 MHPMEVENT11,
200 MHPMEVENT12,
201 MHPMEVENT13,
202 MHPMEVENT14,
203 MHPMEVENT15,
204 MHPMEVENT16,
205 MHPMEVENT17,
206 MHPMEVENT18,
207 MHPMEVENT19,
208 MHPMEVENT20,
209 MHPMEVENT21,
210 MHPMEVENT22,
211 MHPMEVENT23,
212 MHPMEVENT24,
213 MHPMEVENT25,
214 MHPMEVENT26,
215 MHPMEVENT27,
216 MHPMEVENT28,
217 MHPMEVENT29,
218 MHPMEVENT30,
219 MHPMEVENT31,
220 MSCRATCH,
221 MEPC,
222 MCAUSE,
223 MTVAL,
224 MIP,
225 PMPCFG0,
226 PMPCFG1,
227 PMPCFG2,
228 PMPCFG3,
229 PMPADDR0,
230 PMPADDR1,
231 PMPADDR2,
232 PMPADDR3,
233 PMPADDR4,
234 PMPADDR5,
235 PMPADDR6,
236 PMPADDR7,
237 PMPADDR8,
238 PMPADDR9,
239 PMPADDR10,
240 PMPADDR11,
241 PMPADDR12,
242 PMPADDR13,
243 PMPADDR14,
244 PMPADDR15,
245 SCONTEXT,
246 MSECCFG,
247 MSECCFGH,
248 TSELECT,
249 TDATA1,
250 TDATA2,
251 TDATA3,
252 MCONTEXT,
253 MSCONTEXT,
254 DCSR,
255 DPC,
256 DSCRATCH0,
257 DSCRATCH1,
258 MCYCLE,
259 MINSTRET,
260 MHPMCOUNTER3,
261 MHPMCOUNTER4,
262 MHPMCOUNTER5,
263 MHPMCOUNTER6,
264 MHPMCOUNTER7,
265 MHPMCOUNTER8,
266 MHPMCOUNTER9,
267 MHPMCOUNTER10,
268 MHPMCOUNTER11,
269 MHPMCOUNTER12,
270 MHPMCOUNTER13,
271 MHPMCOUNTER14,
272 MHPMCOUNTER15,
273 MHPMCOUNTER16,
274 MHPMCOUNTER17,
275 MHPMCOUNTER18,
276 MHPMCOUNTER19,
277 MHPMCOUNTER20,
278 MHPMCOUNTER21,
279 MHPMCOUNTER22,
280 MHPMCOUNTER23,
281 MHPMCOUNTER24,
282 MHPMCOUNTER25,
283 MHPMCOUNTER26,
284 MHPMCOUNTER27,
285 MHPMCOUNTER28,
286 MHPMCOUNTER29,
287 MHPMCOUNTER30,
288 MHPMCOUNTER31,
289 MCYCLEH,
290 MINSTRETH,
291 MHPMCOUNTER3H,
292 MHPMCOUNTER4H,
293 MHPMCOUNTER5H,
294 MHPMCOUNTER6H,
295 MHPMCOUNTER7H,
296 MHPMCOUNTER8H,
297 MHPMCOUNTER9H,
298 MHPMCOUNTER10H,
299 MHPMCOUNTER11H,
300 MHPMCOUNTER12H,
301 MHPMCOUNTER13H,
302 MHPMCOUNTER14H,
303 MHPMCOUNTER15H,
304 MHPMCOUNTER16H,
305 MHPMCOUNTER17H,
306 MHPMCOUNTER18H,
307 MHPMCOUNTER19H,
308 MHPMCOUNTER20H,
309 MHPMCOUNTER21H,
310 MHPMCOUNTER22H,
311 MHPMCOUNTER23H,
312 MHPMCOUNTER24H,
313 MHPMCOUNTER25H,
314 MHPMCOUNTER26H,
315 MHPMCOUNTER27H,
316 MHPMCOUNTER28H,
317 MHPMCOUNTER29H,
318 MHPMCOUNTER30H,
319 MHPMCOUNTER31H,
320 MVENDORID,
321 MARCHID,
322 MIMPID,
323 MHARTID,
324
325 #[strum(serialize = "csr_cpuctrl")]
327 CPUCTRL,
328 #[strum(serialize = "csr_secureseed")]
329 SECURESEED,
330}
331
332impl RiscvCsr {
333 pub fn name(self) -> &'static str {
335 self.into()
336 }
337}
338
339#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
341pub enum RiscvReg {
342 Gpr(RiscvGpr),
344 Csr(RiscvCsr),
346}
347
348impl RiscvReg {
349 pub fn name(self) -> &'static str {
351 match self {
352 Self::Gpr(gpr) => gpr.name(),
353 Self::Csr(csr) => csr.name(),
354 }
355 }
356}
357
358impl From<RiscvGpr> for RiscvReg {
359 fn from(gpr: RiscvGpr) -> Self {
360 Self::Gpr(gpr)
361 }
362}
363
364impl From<RiscvCsr> for RiscvReg {
365 fn from(csr: RiscvCsr) -> Self {
366 Self::Csr(csr)
367 }
368}