Skip to main content

ArmDebugInterface

Struct ArmDebugInterface 

Source
pub struct ArmDebugInterface<T> {
    pub version: u64,
    /* private fields */
}

Fields§

§version: u64

Implementations§

Source§

impl<T, U> ArmDebugInterface<T>
where T: DerefMut<Target = U>, U: Cable + ?Sized,

Source

pub fn new(taps: Taps<T>) -> Self

Examples found in repository?
examples/parse-rom-table.rs (line 166)
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
Hide additional examples
examples/peekpoke.rs (line 58)
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}
examples/armv8-halt.rs (line 57)
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}
examples/armv8-single-step-pcsr.rs (line 77)
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}
examples/armv8-single-step.rs (line 78)
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}
Source

pub fn queue_read_adi_nobank(&mut self, port: Port, reg: u32) -> bool

Source

pub fn finish_read(&mut self) -> Result<u32, u8>

Source

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.

Source

pub fn read_adi_retry( &mut self, apsel: u32, port: Port, reg: u32, ) -> Result<u32, u8>

Source

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.

Source

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.

Source

pub fn read_adi(&mut self, apsel: u32, port: Port, reg: u32) -> Result<u32, u8>

Read register reg from AP apsel and port.

Source

pub fn queue_read_adi(&mut self, apsel: u32, port: Port, reg: u32) -> bool

Read register reg from AP apsel and port.

Source

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.

Source

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.

Source

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.

Source

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.

Auto Trait Implementations§

§

impl<T> Freeze for ArmDebugInterface<T>
where T: Freeze,

§

impl<T> RefUnwindSafe for ArmDebugInterface<T>
where T: RefUnwindSafe,

§

impl<T> Send for ArmDebugInterface<T>
where T: Send,

§

impl<T> Sync for ArmDebugInterface<T>
where T: Sync,

§

impl<T> Unpin for ArmDebugInterface<T>
where T: Unpin,

§

impl<T> UnsafeUnpin for ArmDebugInterface<T>
where T: UnsafeUnpin,

§

impl<T> UnwindSafe for ArmDebugInterface<T>
where T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.