1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use color_eyre::eyre::Result;
use field_offset::offset_of;
use object::read::{File as ElfFile, Object, ObjectSymbol};
use probe_rs::{
flashing::{download_file, Format},
MemoryInterface, Session,
};
use probe_rs_rtt::{Rtt, ScanRegion};
use std::{
fs,
path::Path,
sync::{Arc, Mutex},
time::Duration,
};
#[derive(Debug, thiserror::Error)]
pub enum RttError {
#[error("Missing symbol {0}")]
MissingSymbol(&'static str),
}
#[repr(C)]
struct RttHeader {
id: [u8; 16],
max_up_channels: u32,
max_down_channels: u32,
}
#[repr(C)]
struct RttChannel {
name: u32,
buffer: u32,
size: u32,
write: u32,
read: u32,
flags: u32,
}
pub fn download_firmware(session: &Arc<Mutex<Session>>, elf_path: &Path) -> Result<()> {
let mut mutex_guard = session.lock().unwrap();
log::info!("Loading FW to target");
download_file(&mut mutex_guard, &elf_path, Format::Elf)?;
log::info!("Download complete!");
let file_contents = fs::read(elf_path)?;
let elf_file = ElfFile::parse(&file_contents[..])?;
let main = elf_file
.symbols()
.find(|s| s.name().unwrap() == "main")
.ok_or(RttError::MissingSymbol("main"))?;
let mut core = mutex_guard.core(0).unwrap();
let _ = core.reset_and_halt(Duration::from_millis(100))?;
let main = (main.address() as u32) & !0x01;
core.set_hw_breakpoint(main)?;
log::debug!("Inserting breakpoint at main() @ 0x{:x}", main);
core.run()?;
core.wait_for_core_halted(Duration::from_secs(1))?;
log::debug!("Core halted at main()");
Ok(())
}
#[derive(Debug)]
pub enum RttMode {
NonBlocking = 1,
Blocking = 2,
}
pub fn configure_rtt_mode(
session: Arc<Mutex<Session>>,
rtt_addr: u64,
channel_idx: usize,
mode: RttMode,
) -> Result<()> {
const CHANNEL_SIZE: usize = std::mem::size_of::<RttChannel>();
const HEADER_SIZE: usize = std::mem::size_of::<RttHeader>();
let mut session_lock = session.lock().unwrap();
let mut core = session_lock.core(0)?;
let mode_flags_addr = rtt_addr as usize
+ HEADER_SIZE
+ CHANNEL_SIZE * channel_idx
+ offset_of!(RttChannel => flags).get_byte_offset();
log::info!("Setting mode to {:?}", mode);
core.write_word_32(mode_flags_addr as u32, mode as u32)?;
Ok(())
}
pub fn run_core(session: Arc<Mutex<Session>>) -> Result<()> {
let mut session_lock = session.lock().unwrap();
let mut core = session_lock.core(0)?;
log::info!("Clearing breakpoints and entering run state");
core.clear_all_hw_breakpoints()?;
core.run()?;
Ok(())
}
pub fn disable_cdebugen(session: Arc<Mutex<Session>>) -> Result<()> {
let mut session_lock = session.lock().unwrap();
let mut core = session_lock.core(0)?;
let dhcsr_addr = 0xE000EDF0;
let dhcsr_val = [0xA05F << 16];
core.write_32(dhcsr_addr, &dhcsr_val)?;
log::info!("Disabled debugging");
Ok(())
}
pub fn attach_rtt(session: Arc<Mutex<Session>>, elf_file: &ElfFile) -> Result<Rtt> {
let segger_rtt = elf_file
.symbols()
.find(|s| s.name().unwrap() == "_SEGGER_RTT")
.ok_or(RttError::MissingSymbol("_SEGGER_RTT"))?;
log::info!("Attaching RTT to address 0x{:x}", segger_rtt.address());
let scan_region = ScanRegion::Exact(segger_rtt.address() as u32);
Ok(Rtt::attach_region(session, &scan_region)?)
}