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}
137
138#[derive(Clone, Copy, Debug, Deserialize, Serialize, strum::IntoStaticStr)]
140#[strum(serialize_all = "lowercase")]
141pub enum RiscvGpr {
142 RA,
143 SP,
144 GP,
145 TP,
146 T0,
147 T1,
148 T2,
149 FP,
150 S1,
151 A0,
152 A1,
153 A2,
154 A3,
155 A4,
156 A5,
157 A6,
158 A7,
159 S2,
160 S3,
161 S4,
162 S5,
163 S6,
164 S7,
165 S8,
166 S9,
167 S10,
168 S11,
169 T3,
170 T4,
171 T5,
172 T6,
173}
174
175impl RiscvGpr {
176 pub fn name(self) -> &'static str {
178 self.into()
179 }
180}
181
182#[derive(Clone, Copy, Debug, Deserialize, Serialize, strum::IntoStaticStr)]
184#[strum(serialize_all = "lowercase")]
185#[non_exhaustive]
186pub enum RiscvCsr {
187 MSTATUS,
188 MISA,
189 MIE,
190 MTVEC,
191 MCOUNTINHIBIT,
192 MHPMEVENT3,
193 MHPMEVENT4,
194 MHPMEVENT5,
195 MHPMEVENT6,
196 MHPMEVENT7,
197 MHPMEVENT8,
198 MHPMEVENT9,
199 MHPMEVENT10,
200 MHPMEVENT11,
201 MHPMEVENT12,
202 MHPMEVENT13,
203 MHPMEVENT14,
204 MHPMEVENT15,
205 MHPMEVENT16,
206 MHPMEVENT17,
207 MHPMEVENT18,
208 MHPMEVENT19,
209 MHPMEVENT20,
210 MHPMEVENT21,
211 MHPMEVENT22,
212 MHPMEVENT23,
213 MHPMEVENT24,
214 MHPMEVENT25,
215 MHPMEVENT26,
216 MHPMEVENT27,
217 MHPMEVENT28,
218 MHPMEVENT29,
219 MHPMEVENT30,
220 MHPMEVENT31,
221 MSCRATCH,
222 MEPC,
223 MCAUSE,
224 MTVAL,
225 MIP,
226 PMPCFG0,
227 PMPCFG1,
228 PMPCFG2,
229 PMPCFG3,
230 PMPADDR0,
231 PMPADDR1,
232 PMPADDR2,
233 PMPADDR3,
234 PMPADDR4,
235 PMPADDR5,
236 PMPADDR6,
237 PMPADDR7,
238 PMPADDR8,
239 PMPADDR9,
240 PMPADDR10,
241 PMPADDR11,
242 PMPADDR12,
243 PMPADDR13,
244 PMPADDR14,
245 PMPADDR15,
246 SCONTEXT,
247 MSECCFG,
248 MSECCFGH,
249 TSELECT,
250 TDATA1,
251 TDATA2,
252 TDATA3,
253 MCONTEXT,
254 MSCONTEXT,
255 DCSR,
256 DPC,
257 DSCRATCH0,
258 DSCRATCH1,
259 MCYCLE,
260 MINSTRET,
261 MHPMCOUNTER3,
262 MHPMCOUNTER4,
263 MHPMCOUNTER5,
264 MHPMCOUNTER6,
265 MHPMCOUNTER7,
266 MHPMCOUNTER8,
267 MHPMCOUNTER9,
268 MHPMCOUNTER10,
269 MHPMCOUNTER11,
270 MHPMCOUNTER12,
271 MHPMCOUNTER13,
272 MHPMCOUNTER14,
273 MHPMCOUNTER15,
274 MHPMCOUNTER16,
275 MHPMCOUNTER17,
276 MHPMCOUNTER18,
277 MHPMCOUNTER19,
278 MHPMCOUNTER20,
279 MHPMCOUNTER21,
280 MHPMCOUNTER22,
281 MHPMCOUNTER23,
282 MHPMCOUNTER24,
283 MHPMCOUNTER25,
284 MHPMCOUNTER26,
285 MHPMCOUNTER27,
286 MHPMCOUNTER28,
287 MHPMCOUNTER29,
288 MHPMCOUNTER30,
289 MHPMCOUNTER31,
290 MCYCLEH,
291 MINSTRETH,
292 MHPMCOUNTER3H,
293 MHPMCOUNTER4H,
294 MHPMCOUNTER5H,
295 MHPMCOUNTER6H,
296 MHPMCOUNTER7H,
297 MHPMCOUNTER8H,
298 MHPMCOUNTER9H,
299 MHPMCOUNTER10H,
300 MHPMCOUNTER11H,
301 MHPMCOUNTER12H,
302 MHPMCOUNTER13H,
303 MHPMCOUNTER14H,
304 MHPMCOUNTER15H,
305 MHPMCOUNTER16H,
306 MHPMCOUNTER17H,
307 MHPMCOUNTER18H,
308 MHPMCOUNTER19H,
309 MHPMCOUNTER20H,
310 MHPMCOUNTER21H,
311 MHPMCOUNTER22H,
312 MHPMCOUNTER23H,
313 MHPMCOUNTER24H,
314 MHPMCOUNTER25H,
315 MHPMCOUNTER26H,
316 MHPMCOUNTER27H,
317 MHPMCOUNTER28H,
318 MHPMCOUNTER29H,
319 MHPMCOUNTER30H,
320 MHPMCOUNTER31H,
321 MVENDORID,
322 MARCHID,
323 MIMPID,
324 MHARTID,
325
326 #[strum(serialize = "csr_cpuctrl")]
328 CPUCTRL,
329 #[strum(serialize = "csr_secureseed")]
330 SECURESEED,
331}
332
333impl RiscvCsr {
334 pub fn name(self) -> &'static str {
336 self.into()
337 }
338}
339
340#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
342pub enum RiscvReg {
343 Gpr(RiscvGpr),
345 Csr(RiscvCsr),
347}
348
349impl RiscvReg {
350 pub fn name(self) -> &'static str {
352 match self {
353 Self::Gpr(gpr) => gpr.name(),
354 Self::Csr(csr) => csr.name(),
355 }
356 }
357}
358
359impl From<RiscvGpr> for RiscvReg {
360 fn from(gpr: RiscvGpr) -> Self {
361 Self::Gpr(gpr)
362 }
363}
364
365impl From<RiscvCsr> for RiscvReg {
366 fn from(csr: RiscvCsr) -> Self {
367 Self::Csr(csr)
368 }
369}