pub struct ArmDebugInterface<T> {
pub version: u64,
/* private fields */
}Fields§
§version: u64Implementations§
Source§impl<T, U> ArmDebugInterface<T>
impl<T, U> ArmDebugInterface<T>
Sourcepub fn new(taps: Taps<T>) -> Self
pub fn new(taps: Taps<T>) -> Self
Examples found in repository?
152fn main() {
153 let args = Args::parse();
154 let cable = cable::new_from_string(&args.cable, args.baud).expect("cable");
155 let jtag = JtagSM::new(cable);
156 let mut taps = Taps::new(jtag);
157 taps.detect();
158
159 // IDCODE instruction
160 let ir = vec![14];
161 taps.select_tap(args.tap_index, &ir);
162 let dr = taps.read_dr(32);
163 let idcode = u32::from_le_bytes(dr.try_into().unwrap());
164 assert_eq!(idcode & 0xfff, 0x477);
165
166 let adi = Rc::new(RefCell::new(ArmDebugInterface::new(taps)));
167 let mut mem = MemAP::new(adi.clone(), args.ap_num);
168
169 let baseaddr = args.addr.map(|x| parse_int(&x)).unwrap_or(Ok(0)).expect("bad address");
170 parse_rom_table(&mut mem, baseaddr).expect("rom table");
171}More examples
40fn main() {
41 let args = Args::parse();
42 let cable = cable::new_from_string(&args.cable, args.baud).expect("cable");
43 let jtag = JtagSM::new(cable);
44 let mut taps = Taps::new(jtag);
45 taps.detect();
46
47 // IDCODE instruction
48 let ir = vec![14];
49 taps.select_tap(args.tap_index, &ir);
50 let dr = taps.read_dr(32);
51 let idcode = u32::from_le_bytes(dr.try_into().unwrap());
52
53 // Verify ARM ID code
54 if idcode != 0x4ba00477 {
55 eprintln!("Warning: unexpected idcode {:x}", idcode);
56 }
57
58 let adi = Rc::new(RefCell::new(ArmDebugInterface::new(taps)));
59 let mut mem = MemAP::new(adi.clone(), args.ap_num);
60
61 let addr = parse_int(&args.addr).expect("failed to parse address");
62
63 if let Some(value) = args.write {
64 let value = parse_int(&value).expect("failed to parse value");
65 mem.write(addr, value).expect("write");
66 println!("Success");
67 } else {
68 let val = mem.read(addr).expect("read");
69 println!("0x{:x} = 0x{:x}", addr, val);
70 }
71}43fn main() {
44 let args = Args::parse();
45 let cable = cable::new_from_string(&args.cable, args.baud).expect("cable");
46 let jtag = JtagSM::new(cable);
47 let mut taps = Taps::new(jtag);
48 taps.detect();
49
50 // IDCODE instruction
51 let ir = vec![14];
52 taps.select_tap(0, &ir);
53 //let dr = taps.read_dr(32);
54 //let idcode = u32::from_le_bytes(dr.try_into().unwrap());
55 //assert_eq!(idcode, 0x6ba00477);
56
57 let adi = Rc::new(RefCell::new(ArmDebugInterface::new(taps)));
58 let mut mem = MemAP::new(adi.clone(), args.ap_num);
59
60 let cpu_base = parse_int(&args.cpu_base).expect("invalid cpu base");
61 let edprsr = mem.read(cpu_base + 0x314).expect("read edprsr");
62 println!("edprsr {:x}", edprsr);
63 assert!(edprsr & 1 == 1);
64
65 // Clear OS lock
66 let oslar = mem.read(cpu_base + 0x300).expect("read oslar");
67 println!("oslar {:x}", oslar);
68 mem.write(cpu_base + 0x300, 0).expect("write oslar");
69
70 // Clear software lock lock
71 let oslar = mem.read(cpu_base + 0xfb4).expect("read oslar");
72 println!("swlck {:x}", oslar);
73 mem.write(cpu_base + 0xfb0, 0xC5ACCE55).expect("write oslar");
74 let oslar = mem.read(cpu_base + 0xfb4).expect("read oslar");
75 println!("swlck {:x}", oslar);
76 assert_eq!(oslar & 2, 0);
77
78 // Enable halting debug
79 let mut edscr = mem.read(cpu_base + 0x088).expect("read edscr");
80 println!("edscr {:x}", edscr);
81 edscr |= 1 << 14;
82 mem.write(cpu_base + 0x088, edscr).expect("write edscr");
83 let edscr = mem.read(cpu_base + 0x088).expect("read edscr");
84 println!("edscr {:x}", edscr);
85
86 //// Unlock CTI
87 let cti_base = parse_int(&args.cti_base).expect("invalid cti base");
88 let ctilsr = mem.read(cti_base + 0xfb4).expect("read cti");
89 println!("ctilsr {:x}", ctilsr);
90 mem.write(cti_base + 0xfb0, 0xC5ACCE55).expect("write cti");
91 let ctilsr = mem.read(cti_base + 0xfb4).expect("read cti");
92 println!("ctilsr {:x}", ctilsr);
93
94 //// Enable CTI
95 let mut cti = mem.read(cti_base).expect("read cti");
96 println!("cti {:x}", cti);
97 cti |= 1;
98 mem.write(cti_base, cti).expect("write cti");
99 let cti = mem.read(cti_base).expect("read cti");
100 println!("cti {:x}", cti);
101 assert_eq!(cti & 1, 1);
102
103 let mut v8 = ARMv8::new(mem, cpu_base, cti_base);
104
105 if let Some(cmd) = args.command {
106 match cmd.as_str() {
107 "halt" => v8.cpu_halt().expect("halt"),
108 "resume" => v8.cpu_resume().expect("resume"),
109 _ => eprintln!("Unknown command"),
110 }
111 }
112
113 let edscr = v8.read_cpu(0x088).expect("read edscr");
114 println!("edscr {:x}", edscr);
115}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 // IDCODE instruction
71 let ir = vec![14];
72 taps.select_tap(0, &ir);
73 //let dr = taps.read_dr(32);
74 //let idcode = u32::from_le_bytes(dr.try_into().unwrap());
75 //assert_eq!(idcode, 0x6ba00477);
76
77 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 //println!("edprsr {:x}", edprsr);
83 assert!(edprsr & 1 == 1);
84
85 // Clear OS lock
86 mem.write(cpu_base + 0x300, 0).expect("write oslar");
87
88 // Clear software lock lock
89 mem.write(cpu_base + 0xfb0, 0xC5ACCE55).expect("write oslar");
90 let oslar = mem.read(cpu_base + 0xfb4).expect("read oslar");
91 //println!("swlck {:x}", oslar);
92 assert_eq!(oslar & 2, 0);
93
94 // Enable halting debug
95 let mut edscr = mem.read(cpu_base + 0x088).expect("read edscr");
96 //println!("edscr {:x}", edscr);
97 edscr |= 1 << 14;
98 mem.write(cpu_base + 0x088, edscr).expect("write edscr");
99
100 //// Unlock CTI
101 let cti_base = parse_int(&args.cti_base).expect("invalid cti base");
102 mem.write(cti_base + 0xfb0, 0xC5ACCE55).expect("write cti");
103
104 //// Enable CTI
105 let mut cti = mem.read(cti_base).expect("read cti");
106 //println!("cti {:x}", cti);
107 cti |= 1;
108 mem.write(cti_base, cti).expect("write cti");
109 let cti = mem.read(cti_base).expect("read cti");
110 //println!("cti {:x}", cti);
111 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 // Must be in halt state
120 cpu_halt(&mut mem, cti_base);
121 // enable single step
122 mem.write(cpu_base + 0x024, 1 << 2).expect("write edecr");
123
124 // pull these writes out of the loop for performance
125 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 // resume the CPU so it can run one instruction
143 mem.write_nocheck(cti_base + 0x01c, 2).expect("write ctiouten");
144 }
145}64fn main() {
65 let args = Args::parse();
66 let cable = cable::new_from_string(&args.cable, args.baud).expect("cable");
67 let jtag = JtagSM::new(cable);
68 let mut taps = Taps::new(jtag);
69 taps.detect();
70
71 // IDCODE instruction
72 let ir = vec![14];
73 taps.select_tap(0, &ir);
74 //let dr = taps.read_dr(32);
75 //let idcode = u32::from_le_bytes(dr.try_into().unwrap());
76 //assert_eq!(idcode, 0x6ba00477);
77
78 let adi = Rc::new(RefCell::new(ArmDebugInterface::new(taps)));
79 let mut mem = MemAP::new(adi.clone(), args.ap_num);
80
81 let cpu_base = parse_int(&args.cpu_base).expect("invalid cpu base");
82 let edprsr = mem.read(cpu_base + 0x314).expect("read edprsr");
83 //println!("edprsr {:x}", edprsr);
84 assert!(edprsr & 1 == 1);
85
86 // Clear OS lock
87 mem.write(cpu_base + 0x300, 0).expect("write oslar");
88
89 // Clear software lock lock
90 mem.write(cpu_base + 0xfb0, 0xC5ACCE55).expect("write oslar");
91 let oslar = mem.read(cpu_base + 0xfb4).expect("read oslar");
92 //println!("swlck {:x}", oslar);
93 assert_eq!(oslar & 2, 0);
94
95 // Enable halting debug
96 let mut edscr = mem.read(cpu_base + 0x088).expect("read edscr");
97 println!("edscr {:x}", edscr);
98 edscr |= 1 << 14;
99 // Make sure memory access mode is disabled
100 edscr &= !(1 << 20);
101 mem.write(cpu_base + 0x088, edscr).expect("write edscr");
102
103 //// Unlock CTI
104 let cti_base = parse_int(&args.cti_base).expect("invalid cti base");
105 mem.write(cti_base + 0xfb0, 0xC5ACCE55).expect("write cti");
106
107 //// Enable CTI
108 let mut cti = mem.read(cti_base).expect("read cti");
109 //println!("cti {:x}", cti);
110 cti |= 1;
111 mem.write(cti_base, cti).expect("write cti");
112 let cti = mem.read(cti_base).expect("read cti");
113 //println!("cti {:x}", cti);
114 assert_eq!(cti & 1, 1);
115
116 // Must be in halt state
117 cpu_halt(&mut mem, cti_base);
118 // enable single step
119 mem.write(cpu_base + 0x024, 1 << 2).expect("write edecr");
120 // clear sticky error bit
121 mem.write(cpu_base + 0x090, 1 << 2).expect("write edrcr");
122
123 let mut v8 = ARMv8::new(mem, cpu_base, cti_base);
124
125 // Read out any data that may already be in the DBGDTR so it doesn't overflow
126 loop {
127 let edscr = v8.read_cpu(0x088).expect("read edscr");
128 if edscr & (1 << 29) == 0 {
129 break;
130 }
131 println!("bit 29");
132 v8.read_cpu(0x08c).expect("read edscr");
133 }
134
135 // Same for the CPU direction, read DBGGTR_EL0 from the CPU
136 loop {
137 let edscr = v8.read_cpu(0x088).expect("read edscr");
138 if edscr & (1 << 30) == 0 {
139 break;
140 }
141 println!("bit 30");
142 // mrs x0, dbgdtr_el0
143 v8.run_instr(0xd5330400).expect("write EDITR");
144 }
145
146 // pull these writes out of the loop for performance
147 v8.mem.write(cti_base + 0x140, 0).expect("write ctigate");
148 v8.mem.write(cti_base + 0x0a4, 2).expect("write ctiouten");
149
150 let start = Instant::now();
151 let mut count = 0;
152 loop {
153
154 // Save x0
155 let orig_x0 = v8.get_reg(0).expect("get x0");
156
157 // mrs x0, dlr_el0
158 v8.run_instr(0xd53b4520).expect("write EDITR");
159
160 let dlr = v8.get_reg(0).expect("get x0");
161 println!("dlr {:016x}", dlr);
162
163 // Restore x0
164 v8.set_reg(0, orig_x0).expect("set x0");
165
166 count += 1;
167 if count % 100 == 0 {
168 let delta = start.elapsed().as_millis();
169 eprintln!("IPS {}", count * 1000 / delta);
170 }
171
172 // resume the CPU so it can run one instruction
173 v8.mem.write(cti_base + 0x01c, 2).expect("write ctiouten");
174 }
175}pub fn queue_read_adi_nobank(&mut self, port: Port, reg: u32) -> bool
pub fn finish_read(&mut self) -> Result<u32, u8>
Sourcepub fn read_adi_nobank(&mut self, port: Port, reg: u32) -> Result<u32, u8>
pub fn read_adi_nobank(&mut self, port: Port, reg: u32) -> Result<u32, u8>
Read register reg from port. This function assumes that the correct bank is already
selected. You probably want read_adi unless you know what you’re doing.
pub fn read_adi_retry( &mut self, apsel: u32, port: Port, reg: u32, ) -> Result<u32, u8>
Sourcepub fn write_adi_nobank(
&mut self,
port: Port,
reg: u32,
val: u32,
check: bool,
) -> Result<(), u8>
pub fn write_adi_nobank( &mut self, port: Port, reg: u32, val: u32, check: bool, ) -> Result<(), u8>
Write val to register reg on port. This function assumes that the correct bank is already
selected. If check is true then the return code of the write will be verified, however
this comes at a performance penalty. You probably want write_adi unless you know what
you’re doing.
Sourcepub fn bank_select(&mut self, apsel: u32, apbank: u32, dpbank: u32)
pub fn bank_select(&mut self, apsel: u32, apbank: u32, dpbank: u32)
Select the given access port and banks on the access port and debug port.
Sourcepub fn read_adi(&mut self, apsel: u32, port: Port, reg: u32) -> Result<u32, u8>
pub fn read_adi(&mut self, apsel: u32, port: Port, reg: u32) -> Result<u32, u8>
Read register reg from AP apsel and port.
Sourcepub fn queue_read_adi(&mut self, apsel: u32, port: Port, reg: u32) -> bool
pub fn queue_read_adi(&mut self, apsel: u32, port: Port, reg: u32) -> bool
Read register reg from AP apsel and port.
Sourcepub fn write_adi(
&mut self,
apsel: u32,
port: Port,
reg: u32,
val: u32,
) -> Result<(), u8>
pub fn write_adi( &mut self, apsel: u32, port: Port, reg: u32, val: u32, ) -> Result<(), u8>
Write val to register reg of AP apsel and port.
Sourcepub fn write_adi_nocheck(
&mut self,
apsel: u32,
port: Port,
reg: u32,
val: u32,
) -> Result<(), u8>
pub fn write_adi_nocheck( &mut self, apsel: u32, port: Port, reg: u32, val: u32, ) -> Result<(), u8>
Write val to register reg of AP apsel and port without checking for success. This
is slightly faster than write_adi, especially when doing a sequence of writes.
Sourcepub fn read_adi_pipelined(
&mut self,
apsel: u32,
port: Port,
reg: &[u32],
) -> Vec<Result<u32, u8>>
pub fn read_adi_pipelined( &mut self, apsel: u32, port: Port, reg: &[u32], ) -> Vec<Result<u32, u8>>
Read multiple registers. reg is an array of register values to access. The result is
returned in the corresponding index of the returned Vec. This function makes more
efficient use of the JTAG bus when there are multiple reads to perform.
Sourcepub fn write_adi_pipelined(
&mut self,
apsel: u32,
port: Port,
reg: &[(u32, u32)],
) -> Result<(), u8>
pub fn write_adi_pipelined( &mut self, apsel: u32, port: Port, reg: &[(u32, u32)], ) -> Result<(), u8>
Write multiple registers. Each item of reg is a tuple consisting of the register address
and the value to write. This function makes more efficient use of the JTAG bus when there
are multiple reads to perform.