armv8_single_step_pcsr/
armv8-single-step-pcsr.rs1use std::cell::RefCell;
2use std::rc::Rc;
3use std::ops::DerefMut;
4use std::num::ParseIntError;
5use std::time::Instant;
6
7use jtag_taps::cable::{self, Cable};
8use jtag_taps::statemachine::JtagSM;
9use jtag_taps::taps::Taps;
10
11use jtag_adi::{ArmDebugInterface, MemAP};
12
13use clap::Parser;
14
15#[derive(Parser, Debug)]
16#[command(author, version, about, long_about = None)]
17struct Args {
18 #[arg(short, long)]
19 cable: String,
20 #[arg(short, long)]
21 baud: u32,
22 #[arg(short, long, default_value_t = 0)]
23 tap_index: usize,
25 #[arg(short, long, default_value_t = 0)]
26 ap_num: u32,
28 #[arg(long)]
29 cpu_base: String,
30 #[arg(long)]
31 cti_base: String,
32 command: Option<String>,
33}
34
35fn cpu_halt<T,U>(mem: &mut MemAP<T>, cti_base: u32)
36 where T: DerefMut<Target=U>,
37 U: Cable + ?Sized
38{
39 mem.write(cti_base + 0x140, 0).expect("write ctigate");
41
42 mem.write(cti_base + 0x0a0, 1).expect("write ctiouten");
44
45 mem.write(cti_base + 0x01c, 1).expect("write ctiouten");
47
48 mem.write(cti_base + 0x010, 3).expect("write ctiouten");
50 while mem.read(cti_base + 0x134).unwrap() != 0 {}
52}
53
54fn parse_int(x: &str) -> Result<u32, ParseIntError> {
55 if x.starts_with("0x") {
56 let len = x.len();
57 u32::from_str_radix(&x[2..len], 16)
58 } else {
59 str::parse(&x)
60 }
61}
62
63fn main() {
64 let args = Args::parse();
65 let cable = cable::new_from_string(&args.cable, args.baud).expect("cable");
66 let jtag = JtagSM::new(cable);
67 let mut taps = Taps::new(jtag);
68 taps.detect();
69
70 let ir = vec![14];
72 taps.select_tap(0, &ir);
73 let adi = Rc::new(RefCell::new(ArmDebugInterface::new(taps)));
78 let mut mem = MemAP::new(adi.clone(), args.ap_num);
79
80 let cpu_base = parse_int(&args.cpu_base).expect("invalid cpu base");
81 let edprsr = mem.read(cpu_base + 0x314).expect("read edprsr");
82 assert!(edprsr & 1 == 1);
84
85 mem.write(cpu_base + 0x300, 0).expect("write oslar");
87
88 mem.write(cpu_base + 0xfb0, 0xC5ACCE55).expect("write oslar");
90 let oslar = mem.read(cpu_base + 0xfb4).expect("read oslar");
91 assert_eq!(oslar & 2, 0);
93
94 let mut edscr = mem.read(cpu_base + 0x088).expect("read edscr");
96 edscr |= 1 << 14;
98 mem.write(cpu_base + 0x088, edscr).expect("write edscr");
99
100 let cti_base = parse_int(&args.cti_base).expect("invalid cti base");
102 mem.write(cti_base + 0xfb0, 0xC5ACCE55).expect("write cti");
103
104 let mut cti = mem.read(cti_base).expect("read cti");
106 cti |= 1;
108 mem.write(cti_base, cti).expect("write cti");
109 let cti = mem.read(cti_base).expect("read cti");
110 assert_eq!(cti & 1, 1);
112
113 let eddevid = mem.read(cpu_base + 0xfc8).expect("read edscr");
114 if eddevid & 7 == 0 {
115 eprintln!("CPU must support EDPCSR!");
116 return;
117 }
118
119 cpu_halt(&mut mem, cti_base);
121 mem.write(cpu_base + 0x024, 1 << 2).expect("write edecr");
123
124 mem.write_nocheck(cti_base + 0x140, 0).expect("write ctigate");
126 mem.write_nocheck(cti_base + 0x0a4, 2).expect("write ctiouten");
127
128 let start = Instant::now();
129 let mut count = 0;
130 loop {
131 mem.queue_read(cpu_base + 0x0ac).expect("read edpcsr");
132 mem.queue_read(cpu_base + 0x0a0).expect("read edpcsr");
133 let pc_hi = mem.finish_read().expect("read edpcsr");
134 let pc_lo = mem.finish_read().expect("read edpcsr");
135 println!("pc {:x}{:x}", pc_hi, pc_lo);
136 count += 1;
137 if count % 1000 == 0 {
138 let delta = start.elapsed().as_millis();
139 eprintln!("IPS {}", count * 1000 / delta);
140 }
141
142 mem.write_nocheck(cti_base + 0x01c, 2).expect("write ctiouten");
144 }
145}