1use std::cell::RefCell;
6use std::ops::DerefMut;
7use std::rc::Rc;
8
9use jtag_taps::cable::Cable;
10use jtag_taps::taps::Taps;
11
12pub mod armv8;
13
14#[derive(Clone,Copy)]
16pub enum Port {
17 Abort = 8, DP = 10,
19 AP = 11,
20}
21
22pub enum DPReg {
24 Abort = 0, CtrlStat = 1,
26 Select = 2,
27 Rdbuff = 3,
28}
29
30pub struct ArmDebugInterface<T> {
31 taps: Taps<T>,
32 lastbank: u32,
33 lastir: Vec<u8>,
34 good_ack: u64,
35 pub version: u64,
36}
37
38impl<T, U> ArmDebugInterface<T>
39where
40 T: DerefMut<Target = U>,
41 U: Cable + ?Sized,
42{
43 pub fn new(taps: Taps<T>) -> Self {
44 let mut adi = Self {
45 taps,
46 lastbank: 0xff,
47 lastir: vec![],
48 good_ack: 2,
49 version: 5,
50 };
51
52 let _ = adi.write_adi_nobank(Port::DP, DPReg::Select as u32, 0, false);
55
56 if let Err(4) = adi.write_adi_nobank(Port::DP, DPReg::Abort as u32, 1, true) {
58 adi.good_ack = 4;
60 let val = adi.read_adi_nobank(Port::DP, DPReg::Abort as u32).expect("abort");
61 let version = (val >> 12) & 0xf;
62 assert_eq!(version, 3);
63
64 adi.version = 6;
66 adi.write_adi_nobank(Port::Abort, 0, 1, true).expect("abort");
67 }
68
69 adi.write_adi_nobank(
71 Port::DP,
72 DPReg::CtrlStat as u32,
73 1 << 30 | 1 << 28 | 1 << 24 | 1 << 5 | 1 << 1,
74 true,
75 )
76 .expect("clear errors");
77
78 adi
79 }
80
81 fn write_ir(&mut self, ir: &[u8]) {
82 if self.lastir != ir {
83 self.taps.write_ir(ir);
84 self.lastir = ir.to_vec();
85 }
86 }
87
88 fn parse_ack(mut dr: Vec<u8>, good_ack: u64) -> Result<u32, u8> {
89 dr.push(0);
90 dr.push(0);
91 dr.push(0);
92 let val = u64::from_le_bytes(dr.try_into().unwrap());
93 let val = val & ((1 << 35) - 1);
94
95 let ack = val & 7;
96 if ack != good_ack {
97 return Err(ack as u8);
98 }
99
100 Ok((val >> 3) as u32)
101 }
102
103 pub fn queue_read_adi_nobank(&mut self, port: Port, reg: u32) -> bool {
104 let ir = [port as u8];
105 self.write_ir(&ir);
106 let mut buf = (reg << 1 | 1).to_le_bytes().to_vec();
107 buf.push(0);
108
109 self.taps.write_dr(&buf, 3);
110 self.taps.queue_dr_read(35)
111 }
112
113 pub fn finish_read(&mut self) -> Result<u32, u8> {
114 let mut dr = self.taps.finish_dr_read(35);
115
116 dr.push(0);
117 dr.push(0);
118 dr.push(0);
119 let val = u64::from_le_bytes(dr.try_into().unwrap());
120 let val = val & ((1 << 35) - 1);
121
122 let ack = val & 7;
123 if ack != self.good_ack {
124 return Err(ack as u8);
125 }
126
127 let val = (val >> 3) as u32;
128 Ok(val)
129 }
130
131 pub fn read_adi_nobank(&mut self, port: Port, reg: u32) -> Result<u32, u8> {
134 let result = self.queue_read_adi_nobank(port, reg);
135 assert!(result);
136 self.finish_read()
137 }
138
139 pub fn read_adi_retry(&mut self, apsel: u32, port: Port, mut reg: u32) -> Result<u32, u8> {
140 let bank = reg >> 2;
141 reg &= 3;
142 self.bank_select(apsel, bank as u32, 0);
143 loop {
144 match self.read_adi_nobank(port, reg) {
145 Ok(x) => { return Ok(x); }
146 Err(1) => continue,
147 Err(e) => { return Err(e); }
148 }
149 };
150 }
151
152
153
154 pub fn write_adi_nobank(
159 &mut self,
160 port: Port,
161 reg: u32,
162 val: u32,
163 check: bool,
164 ) -> Result<(), u8> {
165 let ir = [port as u8];
166
167 let mut val = val as u64;
168 val <<= 3;
169 val |= (reg << 1) as u64;
170
171 let bytes = val.to_le_bytes();
172 loop {
173 self.write_ir(&ir);
174 self.taps.write_dr(&bytes[0..5], 3);
175 if !check {
176 return Ok(());
177 } else {
178 let mut dr = self.taps.read_dr(35);
179
180 dr.push(0);
181 dr.push(0);
182 dr.push(0);
183 let val = u64::from_le_bytes(dr.try_into().unwrap());
184 let val = val & ((1 << 35) - 1);
185
186 let ack = val & 7;
187 if ack == self.good_ack {
188 return Ok(());
189 }
190 if ack == 1 {
191 continue;
192 }
193 return Err(ack as u8);
194 }
195 }
196 }
197
198 pub fn bank_select(&mut self, apsel: u32, apbank: u32, dpbank: u32) {
200 let val = (apsel << 24) | (apbank << 4) | dpbank;
201 if val != self.lastbank {
202 self.write_adi_nobank(Port::DP, DPReg::Select as u32, val, true)
203 .expect("bank sel");
204 self.lastbank = val;
205 }
206 }
207
208 pub fn read_adi(&mut self, apsel: u32, port: Port, mut reg: u32) -> Result<u32, u8> {
210 let bank = reg >> 2;
211 reg &= 3;
212 self.bank_select(apsel, bank as u32, 0);
213 self.read_adi_nobank(port, reg)
214 }
215
216 pub fn queue_read_adi(&mut self, apsel: u32, port: Port, mut reg: u32) -> bool {
218 let bank = reg >> 2;
219 reg &= 3;
220 self.bank_select(apsel, bank as u32, 0);
221 self.queue_read_adi_nobank(port, reg)
222 }
223
224 pub fn write_adi(&mut self, apsel: u32, port: Port, mut reg: u32, val: u32) -> Result<(), u8> {
226 let bank = reg >> 2;
227 reg &= 3;
228 self.bank_select(apsel, bank as u32, 0);
229 self.write_adi_nobank(port, reg, val, true)
230 }
231
232 pub fn write_adi_nocheck(
235 &mut self,
236 apsel: u32,
237 port: Port,
238 mut reg: u32,
239 val: u32,
240 ) -> Result<(), u8> {
241 let bank = reg >> 2;
242 reg &= 3;
243 self.bank_select(apsel, bank as u32, bank as u32);
244 self.write_adi_nobank(port, reg, val, false)
245 }
246
247 pub fn read_adi_pipelined(
251 &mut self,
252 apsel: u32,
253 port: Port,
254 reg: &[u32],
255 ) -> Vec<Result<u32, u8>> {
256 let bank = reg[0] >> 2;
257 self.bank_select(apsel, bank as u32, 0);
258
259 let ir = [port as u8];
260 self.write_ir(&ir);
261 let mut buf = ((reg[0] & 3) << 1 | 1).to_le_bytes().to_vec();
262 buf.push(0);
263
264 self.taps.write_dr(&buf, 3);
265
266 let mut count = 0;
267 let mut queue_full = false;
268 for r in ®[1..] {
269 assert_eq!(r >> 2, reg[0] >> 2);
271 let mut buf = ((r & 3) << 1 | 1).to_le_bytes().to_vec();
272 buf.push(0);
273
274 if !self.taps.queue_dr_read_write(&buf, 3) {
275 queue_full = true;
276 break;
277 }
278 count += 1;
279 }
280
281 if !queue_full {
282 if self.taps.queue_dr_read(35) {
283 count += 1;
284 }
285 }
286
287 let mut data = vec![];
288 for _ in 0..count {
289 data.push(Self::parse_ack(self.taps.finish_dr_read(35), self.good_ack));
290 }
291
292 data
293 }
294
295 pub fn write_adi_pipelined(
299 &mut self,
300 apsel: u32,
301 port: Port,
302 reg: &[(u32, u32)],
303 ) -> Result<(), u8> {
304 let bank = reg[0].0 >> 2;
305 self.bank_select(apsel, bank as u32, 0);
306
307 let ir = [port as u8];
308 self.write_ir(&ir);
309
310 for (r, val) in reg {
311 assert_eq!(r >> 2, reg[0].0 >> 2);
313
314 let mut val = *val as u64;
315 val <<= 3;
316 val |= ((r & 3) << 1) as u64;
317
318 let bytes = val.to_le_bytes();
319 self.taps.write_dr(&bytes[0..5], 3);
320 }
321 Ok(())
322 }
323}
324
325#[allow(clippy::upper_case_acronyms)]
326enum MemAPReg {
327 CSW = 0,
328 TAR = 1,
329 DRW = 3,
330 }
335
336pub struct MemAP<T> {
338 adi: Rc<RefCell<ArmDebugInterface<T>>>,
339 base: u32,
340 csw: u32,
341 tar: u32,
342}
343
344impl<T, U> MemAP<T>
345where
346 T: DerefMut<Target = U>,
347 U: Cable + ?Sized,
348{
349 pub fn new(adi: Rc<RefCell<ArmDebugInterface<T>>>, mut base: u32) -> Self {
350 if adi.borrow().version == 6 {
351 base += 0xd00;
352 }
353 base = base >> 2;
354 let csw = adi
355 .borrow_mut()
356 .read_adi_retry(0, Port::AP, MemAPReg::CSW as u32 + base)
357 .expect("read csw");
358 let tar = adi
359 .borrow_mut()
360 .read_adi_retry(0, Port::AP, MemAPReg::TAR as u32 + base)
361 .expect("read tar");
362 Self { adi, base, csw, tar }
363 }
364
365 pub fn write_csw(&mut self, csw: u32) -> Result<(), u8> {
368 if csw != self.csw {
369 self.adi
370 .borrow_mut()
371 .write_adi(0, Port::AP, MemAPReg::CSW as u32 + self.base, csw)?;
372 self.csw = csw;
373 }
374 Ok(())
375 }
376
377 pub fn read(&mut self, addr: u32) -> Result<u32, u8> {
379 self.write_csw(self.csw & !(1 << 4))?;
381 if self.tar != addr {
382 self.adi
383 .borrow_mut()
384 .write_adi(0, Port::AP, MemAPReg::TAR as u32 + self.base, addr)?;
385 self.tar = addr;
386 }
387 let val = self
388 .adi
389 .borrow_mut()
390 .read_adi_retry(0, Port::AP, MemAPReg::DRW as u32 + self.base)?;
391 let stat = self
392 .adi
393 .borrow_mut()
394 .read_adi_retry(0, Port::DP, DPReg::CtrlStat as u32)?;
395 if stat & 5 != 0 {
396 return Err(5);
397 }
398 Ok(val)
399 }
400
401 pub fn queue_read(&mut self, addr: u32) -> Result<bool, u8> {
402 self.write_csw(self.csw & !(1 << 4))?;
404 if self.tar != addr {
405 self.adi
406 .borrow_mut()
407 .write_adi_nocheck(0, Port::AP, MemAPReg::TAR as u32 + self.base, addr)?;
408 self.tar = addr;
409 }
410
411 let val = self
412 .adi
413 .borrow_mut()
414 .queue_read_adi(0, Port::AP, MemAPReg::DRW as u32 + self.base);
415 if !val {
416 return Ok(false);
417 }
418 Ok(true)
419 }
420
421 pub fn finish_read(&mut self) -> Result<u32, u8> {
422 let val = self.adi.borrow_mut().finish_read()?;
423 Ok(val)
424 }
425
426 pub fn write(&mut self, addr: u32, value: u32) -> Result<(), u8> {
428 self.write_csw(self.csw & !(1 << 4))?;
430 if self.tar != addr {
431 self.adi
432 .borrow_mut()
433 .write_adi(0, Port::AP, MemAPReg::TAR as u32 + self.base, addr)?;
434 self.tar = addr;
435 }
436 self.adi
437 .borrow_mut()
438 .write_adi(0, Port::AP, MemAPReg::DRW as u32 + self.base, value)?;
439 if let Ok(_) = std::env::var("YOLO_MODE") {
440 return Ok(())
441 }
442 let stat = self
443 .adi
444 .borrow_mut()
445 .read_adi_retry(0, Port::DP, DPReg::CtrlStat as u32)?;
446 if stat & 5 != 0 {
447 return Err(5);
448 }
449 Ok(())
450 }
451
452 pub fn write_nocheck(&mut self, addr: u32, value: u32) -> Result<(), u8> {
454 self.write_csw(self.csw & !(1 << 4))?;
456 if self.tar != addr {
457 self.adi
458 .borrow_mut()
459 .write_adi_nocheck(0, Port::AP, MemAPReg::TAR as u32 + self.base, addr)?;
460 self.tar = addr;
461 }
462 self.adi
463 .borrow_mut()
464 .write_adi_nocheck(0, Port::AP, MemAPReg::DRW as u32 + self.base, value)?;
465 Ok(())
466 }
467
468 pub fn read_multi(
473 &mut self,
474 addr: u32,
475 count: usize,
476 auto_increment: bool,
477 check_status: bool,
478 ) -> Result<Vec<u32>, u8> {
479 if auto_increment {
481 self.write_csw(self.csw | (1 << 4))?;
482 } else {
483 self.write_csw(self.csw & !(1 << 4))?;
484 }
485
486 if self.tar != addr {
487 self.adi
488 .borrow_mut()
489 .write_adi(0, Port::AP, MemAPReg::TAR as u32 + self.base, addr)?;
490 self.tar = addr;
491 if auto_increment {
492 self.tar += 4 * count as u32;
493 }
494 }
495
496 let reg = vec![MemAPReg::DRW as u32 + self.base; count];
497 let val = self
498 .adi
499 .borrow_mut()
500 .read_adi_pipelined(0, Port::AP, ®);
501
502 let mut result = vec![];
504 for item in val {
505 match item {
506 Ok(x) => result.push(x),
507 Err(1) => continue,
508 Err(e) => return Err(e),
509 }
510 }
511
512 if check_status {
513 let stat =
514 self.adi
515 .borrow_mut()
516 .read_adi_retry(0, Port::DP, DPReg::CtrlStat as u32)?;
517 if stat & 5 != 0 {
518 return Err(5);
519 }
520 }
521 Ok(result)
522 }
523
524 pub fn read_block(
528 &mut self,
529 addr: u32,
530 count: usize,
531 check_status: bool,
532 ) -> Result<Vec<u32>, u8> {
533 self.read_multi(addr, count, true, check_status)
534 }
535
536
537 pub fn write_block(&mut self, addr: u32, data: &[u32], check_status: bool) -> Result<(), u8> {
541 self.write_csw(self.csw | (1 << 4))?;
543
544 if self.tar != addr {
545 self.adi
546 .borrow_mut()
547 .write_adi(0, Port::AP, MemAPReg::TAR as u32 + self.base, addr)?;
548 self.tar = addr + 4 * data.len() as u32;
549 }
550
551 let reg: Vec<(u32, u32)> = data.iter().map(|x| (MemAPReg::DRW as u32 + self.base, *x)).collect();
552 self.adi
553 .borrow_mut()
554 .write_adi_pipelined(0, Port::AP, ®)?;
555
556 if check_status {
557 let stat =
558 self.adi
559 .borrow_mut()
560 .read_adi_retry(0, Port::DP, DPReg::CtrlStat as u32)?;
561 if stat & 5 != 0 {
562 return Err(5);
563 }
564 }
565 Ok(())
566 }
567}