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