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
use color_eyre::eyre::Result;
use object::read::{File as ElfFile, Object, ObjectSymbol};
use postform_decoder::{Decoder, ElfMetadata, LogLevel};
use probe_rs::{
flashing::{download_file, Format},
MemoryInterface, Session,
};
use probe_rs_rtt::{Rtt, ScanRegion};
use std::{
fs,
path::PathBuf,
sync::{Arc, Mutex},
time::Duration,
};
use termion::color;
#[derive(Debug, thiserror::Error)]
pub enum RttError {
#[error("Missing symbol {0}")]
MissingSymbol(&'static str),
}
pub fn download_firmware(session: &Arc<Mutex<Session>>, elf_path: &PathBuf) -> Result<()> {
let mut mutex_guard = session.lock().unwrap();
println!("Loading FW to target");
download_file(&mut mutex_guard, &elf_path, Format::Elf)?;
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(10))?;
core.set_hw_breakpoint(main.address() as u32)?;
core.run()?;
core.wait_for_core_halted(Duration::from_secs(1))?;
println!("Download complete!");
Ok(())
}
#[derive(Debug)]
pub enum RttMode {
NonBlocking = 1,
Blocking = 2,
}
pub fn configure_rtt_mode(
session: &Arc<Mutex<Session>>,
rtt_addr: u64,
mode: RttMode,
) -> Result<()> {
let mut session_lock = session.lock().unwrap();
let mut core = session_lock.core(0)?;
let mode_flags_addr = rtt_addr as u32 + 44u32;
println!("Setting mode to {:?}", mode);
core.write_word_32(mode_flags_addr, mode as u32)?;
Ok(())
}
pub fn run_core(session: Arc<Mutex<Session>>) -> Result<()> {
let mut mutex_guard = session.lock().unwrap();
let mut core = mutex_guard.core(0)?;
core.clear_all_hw_breakpoints()?;
core.run()?;
Ok(())
}
fn color_for_level(level: LogLevel) -> String {
match level {
LogLevel::Debug => String::from(color::Green.fg_str()),
LogLevel::Info => String::from(color::Yellow.fg_str()),
LogLevel::Warning => color::Rgb(255u8, 0xA5u8, 0u8).fg_string(),
LogLevel::Error => String::from(color::Red.fg_str()),
LogLevel::Unknown => color::Rgb(255u8, 0u8, 0u8).fg_string(),
}
}
pub fn handle_log(elf_metadata: &ElfMetadata, buffer: &[u8]) {
let mut decoder = Decoder::new(&elf_metadata);
match decoder.decode(buffer) {
Ok(log) => {
println!(
"{timestamp:<12.6} {color}{level:<11}{reset_color}: {msg}",
timestamp = log.timestamp,
color = color_for_level(log.level),
level = log.level.to_string(),
reset_color = color::Fg(color::Reset),
msg = log.message
);
println!(
"{color}└── File: {file_name}, Line number: {line_number}{reset}",
color = color::Fg(color::LightBlack),
file_name = log.file_name,
line_number = log.line_number,
reset = color::Fg(color::Reset)
);
}
Err(error) => {
println!(
"{color}Error parsing log:{reset_color} {error}.",
color = color::Fg(color::Red),
error = error,
reset_color = color::Fg(color::Reset)
);
}
}
}
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"))?;
println!("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)?)
}