Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • devel
  • master
  • trustit
3 results

Target

Select target project
  • pln/klee-examples
  • grammers/klee-examples
2 results
Select Git revision
  • master
1 result
Show changes
......@@ -7,9 +7,9 @@ set print asm-demangle on
set backtrace limit 32
# detect unhandled exceptions, hard faults and panics
break DefaultHandler
break HardFault
break rust_begin_unwind
#break DefaultHandler
#break HardFault
#break rust_begin_unwind
# # run the next few lines so the panic message is printed immediately
# # the number needs to be adjusted for your panic handler
# commands $bpnum
......
This diff is collapsed.
[package]
name = "runner"
version = "0.1.0"
authors = ["Per Lindgren <per.lindgren@ltu.se>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
probe-rs = { version = "0.3.0" }
ktest = { path = "../ktest", version = "0.1.0" }
failure = "0.1.6"
[lib]
name = "runner"
\ No newline at end of file
# runner
KLEE test runner, in very early development.
Still the library provides sufficient capabilities to profile execution.
Tested only on the `stm32f401/f411`
## License
Non public release, all rights reserved Per Lindgren 2020.
This diff is collapsed.
File added
use failure::format_err;
use ktest::{read_ktest, KTEST};
use probe_rs::{
config::registry::{Registry, SelectionStrategy},
coresight::access_ports::AccessPortError,
coresight::memory::MI,
flash::download::{
download_file, download_file_with_progress_reporting, FileDownloadError, Format,
},
probe::{stlink, DebugProbe, DebugProbeError, DebugProbeType, MasterProbe, WireProtocol},
session::Session,
target::info::{self, ChipInfo},
};
// don't look at this, its just testing some stuff...
// le byte order
fn main() {
println!("read ktest file");
let ktest = read_ktest("resources/test000001.ktest").unwrap();
println!("ktest {:?}", ktest);
let mut probe = open_probe();
println!("probe connected");
let strategy = SelectionStrategy::ChipInfo(ChipInfo::read_from_rom_table(&mut probe).unwrap());
println!("strategy {:?}", strategy);
let strategy = SelectionStrategy::TargetIdentifier("stm32f411".into());
let registry = Registry::from_builtin_families();
let target = registry.get_target(strategy).unwrap();
println!("target {:?}", target);
let mut session = Session::new(target, probe);
let mm = session.target.memory_map.clone();
let path_str = "../target/thumbv7em-none-eabihf/debug/examples/f401_ktest";
// programming
// print!("flashing...");
// download_file(
// &mut session,
// std::path::Path::new(&path_str.to_string().as_str()),
// Format::Elf,
// &mm,
// )
// .map_err(|e| format_err!("failed to flash {}: {}", path_str, e))
// .unwrap();
// println!("... done");
// let data = session.probe.read32(0x0000_0000).unwrap();
// println!("stack 0x{:08x}", data);
// let data = session.probe.read32(0x0000_0004).unwrap();
// println!("reset 0x{:08x}", data);
// run_to_halt(&mut session);
// cycnt_enable(&mut session);
// cycnt_reset(&mut session);
// let cyccnt = cycnt_read(&mut session);
// println!("cyccnt {}", cyccnt);
// run_to_halt(&mut session);
// let cyccnt = cycnt_read(&mut session);
// println!("cyccnt {}", cyccnt);
// run_to_halt(&mut session);
// session
// .target
// .core
// .wait_for_core_halted(&mut session.probe)
// .unwrap();
// println!("Core stopped at address 0x{:08x}", cpu_info.pc);
// session
// .probe
// .write_block32(0x2000_0000, &[0x0123_4567, 0x89ab_cdef])
// .unwrap();
// let mut r = [0u32; 2];
// session.probe.read_block32(0x2000_0000, &mut r).unwrap();
// println!("0x2000_0000 = 0x{:08x}", r[0]);
// println!("0x2000_0004 = 0x{:08x}", r[1]);
// let cpu_info = session.target.core.step(&mut session.probe).unwrap();
// println!("Core stopped at address 0x{:08x}", cpu_info.pc);
reset_and_halt(&mut session);
run_to_halt(&mut session);
for (name, data) in ktest.objects {
set_symbolic(&mut session, &data);
run_to_halt(&mut session);
}
println!("done");
// session.target.core.run(&mut session.probe).unwrap();
// session
// .target
// .core
// .wait_for_core_halted(&mut session.probe)
// .unwrap();
// println!("Core stopped at address 0x{:08x}", cpu_info.pc);
// println!("breapoint reached");
}
// resets the target and run
fn reset_and_run(session: &mut Session) {
session.target.core.reset(&mut session.probe).unwrap();
}
// resets the target and halts
fn reset_and_halt(session: &mut Session) {
session
.target
.core
.reset_and_halt(&mut session.probe)
.unwrap();
}
fn read_bkpt(session: &mut Session) -> Option<u8> {
// try to read the program counter
let pc_value = session
.target
.core
.read_core_reg(&mut session.probe, session.target.core.registers().PC)
.unwrap();
let mut instr16 = [0u8; 2];
session.probe.read_block8(pc_value, &mut instr16).unwrap();
match instr16[1] {
0b10111110 => Some(instr16[0]),
_ => None,
}
}
fn step_from_bkpt(session: &mut Session) {
// try to read the program counter
let pc_value = session
.target
.core
.read_core_reg(&mut session.probe, session.target.core.registers().PC)
.unwrap();
// the bkpt() is a 16 bit instruction, increment pc by 16 bits
let new_pc_value = pc_value + 0x2;
session
.target
.core
.write_core_reg(
&mut session.probe,
session.target.core.registers().PC,
new_pc_value,
)
.unwrap();
}
fn run_to_halt(session: &mut Session) {
// Continue running
if read_bkpt(session).is_some() {
println!("Continue from breakpoint.");
step_from_bkpt(session);
} else {
println!("Continue");
}
session.target.core.run(&mut session.probe).unwrap();
println!("running");
match session.target.core.wait_for_core_halted(&mut session.probe) {
Ok(_) => {
print!("Hit breakpoint :",);
}
Err(DebugProbeError::Timeout) => {
print!("Timeout :");
}
Err(err) => panic!("internal error:{:?}", err),
}
let cpu_info = session.target.core.halt(&mut session.probe).unwrap();
println!("Core stopped at address 0x{:08x}", cpu_info.pc);
}
// index is the oject number
fn set_symbolic(session: &mut Session, data: &[u8]) {
let r0 = session
.target
.core
.read_core_reg(&mut session.probe, 0.into())
.unwrap();
println!("r0 0x{:08x}", r0);
println!("object {:?}", data);
// session.target.core.step(&mut session.probe).unwrap();
let r0 = session.probe.write_block8(r0, data).unwrap();
}
fn open_probe() -> MasterProbe {
let mut devs = stlink::tools::list_stlink_devices();
// just pick the first one
let device = devs.get(0).unwrap();
println!("device {:?}", device);
let mut link = stlink::STLink::new_from_probe_info(&device).unwrap();
link.attach(Some(WireProtocol::Swd)).unwrap();
MasterProbe::from_specific_probe(link)
}
const DWT_CTRL: u32 = 0xe000_1000;
const DWT_CYCCNT: u32 = 0xe000_1004;
fn cycnt_enable(session: &mut Session) {
session.probe.write32(DWT_CTRL, 0x1).unwrap();
}
fn cycnt_disable(session: &mut Session) {
session.probe.write32(DWT_CTRL, 0x0).unwrap();
}
fn cycnt_reset(session: &mut Session) {
// Reset cycle counter to 0
session.probe.write32(DWT_CYCCNT, 0x0).unwrap();
}
fn cycnt_read(session: &mut Session) -> u32 {
session.probe.read32(DWT_CYCCNT).unwrap()
}
use runner::*;
// Note, We use le (little-endian) byte order
fn main() {
let mut session = open_session();
reset_and_halt(&mut session);
run_to_halt(&mut session); // our first breakpoint
cycnt_enable(&mut session);
cycnt_reset(&mut session);
run_to_halt(&mut session); // our second breakpoint
let cycle_count = cycnt_read(&mut session);
println!("cycles {}", cycle_count);
}
// use std::collections::{HashMap, HashSet};
use runner::common::*;
fn main() {
let t1 = Task {
id: "T1".to_string(),
prio: 1,
deadline: 100,
inter_arrival: 100,
trace: Trace {
id: "T1".to_string(),
start: 0,
end: 10,
inner: vec![],
},
};
let t2 = Task {
id: "T2".to_string(),
prio: 2,
deadline: 200,
inter_arrival: 200,
trace: Trace {
id: "T2".to_string(),
start: 0,
end: 30,
inner: vec![
Trace {
id: "R1".to_string(),
start: 10,
end: 20,
inner: vec![Trace {
id: "R2".to_string(),
start: 12,
end: 16,
inner: vec![],
}],
},
Trace {
id: "R1".to_string(),
start: 22,
end: 28,
inner: vec![],
},
],
},
};
let t3 = Task {
id: "T3".to_string(),
prio: 3,
deadline: 50,
inter_arrival: 50,
trace: Trace {
id: "T3".to_string(),
start: 0,
end: 30,
inner: vec![Trace {
id: "R2".to_string(),
start: 10,
end: 20,
inner: vec![],
}],
},
};
// builds a vector of tasks t1, t2, t3
let tasks: Tasks = vec![t1, t2, t3];
println!("tasks {:?}", &tasks);
// println!("tot_util {}", tot_util(&tasks));
let (ip, tr) = pre_analysis(&tasks);
println!("ip: {:?}", ip);
println!("tr: {:?}", tr);
}
use std::collections::{HashMap, HashSet};
// common data structures
#[derive(Debug)]
pub struct Task {
pub id: String,
pub prio: u8,
pub deadline: u32,
pub inter_arrival: u32,
pub trace: Trace,
}
//#[derive(Debug, Clone)]
#[derive(Debug)]
pub struct Trace {
pub id: String,
pub start: u32,
pub end: u32,
pub inner: Vec<Trace>,
}
// uselful types
// Our task set
pub type Tasks = Vec<Task>;
// A map from Task/Resource identifiers to priority
pub type IdPrio = HashMap<String, u8>;
// A map from Task identifiers to a set of Resource identifiers
pub type TaskResources = HashMap<String, HashSet<String>>;
// Derives the above maps from a set of tasks
pub fn pre_analysis(tasks: &Tasks) -> (IdPrio, TaskResources) {
let mut ip = HashMap::new();
let mut tr: TaskResources = HashMap::new();
for t in tasks {
update_prio(t.prio, &t.trace, &mut ip);
for i in &t.trace.inner {
update_tr(t.id.clone(), i, &mut tr);
}
}
(ip, tr)
}
// helper functions
fn update_prio(prio: u8, trace: &Trace, hm: &mut IdPrio) {
if let Some(old_prio) = hm.get(&trace.id) {
if prio > *old_prio {
hm.insert(trace.id.clone(), prio);
}
} else {
hm.insert(trace.id.clone(), prio);
}
for cs in &trace.inner {
update_prio(prio, cs, hm);
}
}
fn update_tr(s: String, trace: &Trace, trmap: &mut TaskResources) {
if let Some(seen) = trmap.get_mut(&s) {
seen.insert(trace.id.clone());
} else {
let mut hs = HashSet::new();
hs.insert(trace.id.clone());
trmap.insert(s.clone(), hs);
}
for trace in &trace.inner {
update_tr(s.clone(), trace, trmap);
}
}
use ktest::{read_ktest, KTEST};
pub mod common;
use probe_rs::{
config::registry::{Registry, SelectionStrategy},
coresight::memory::MI,
flash::download::{
download_file, download_file_with_progress_reporting, FileDownloadError, Format,
},
probe::{stlink, DebugProbe, DebugProbeError, DebugProbeType, MasterProbe, WireProtocol},
session::Session,
target::info::{self, ChipInfo},
};
/// Returns first found stlink probe as MasterProbe
pub fn open_probe() -> MasterProbe {
let devs = stlink::tools::list_stlink_devices();
// just pick the first one
let device = devs.get(0).unwrap();
println!("device {:?}", device);
let mut link = stlink::STLink::new_from_probe_info(&device).unwrap();
link.attach(Some(WireProtocol::Swd)).unwrap();
MasterProbe::from_specific_probe(link)
}
/// Returns a Session from first found stlink probe
pub fn open_session() -> Session {
let mut probe = open_probe();
println!("probe connected");
let strategy = SelectionStrategy::ChipInfo(ChipInfo::read_from_rom_table(&mut probe).unwrap());
println!("strategy {:?}", strategy);
let strategy = SelectionStrategy::TargetIdentifier("stm32f411".into());
let registry = Registry::from_builtin_families();
let target = registry.get_target(strategy).unwrap();
println!("target {:?}", target);
Session::new(target, probe)
}
/// resets the target and run
pub fn reset_and_run(session: &mut Session) {
session.target.core.reset(&mut session.probe).unwrap();
}
/// resets the target and halts
pub fn reset_and_halt(session: &mut Session) {
session
.target
.core
.reset_and_halt(&mut session.probe)
.unwrap();
}
/// read current instruction and returns
/// Some(n) where n is the breakpoint numbr
/// None if its not a breakpoint instruction
pub fn read_bkpt(session: &mut Session) -> Option<u8> {
// try to read the program counter
let pc_value = session
.target
.core
.read_core_reg(&mut session.probe, session.target.core.registers().PC)
.unwrap();
let mut instr16 = [0u8; 2];
session.probe.read_block8(pc_value, &mut instr16).unwrap();
match instr16[1] {
0b10111110 => Some(instr16[0]), // 0b10111110 is the binary repr of `bkpt #n`
_ => None,
}
}
/// increments the pc by 2 (useful to step away from breakpoint)
pub fn increment_pc(session: &mut Session) {
// try to read the program counter
let pc_value = session
.target
.core
.read_core_reg(&mut session.probe, session.target.core.registers().PC)
.unwrap();
// the bkpt() is a 16 bit instruction, increment pc by 16 bits (i.e. 2 bytes)
let new_pc_value = pc_value + 0x2;
session
.target
.core
.write_core_reg(
&mut session.probe,
session.target.core.registers().PC,
new_pc_value,
)
.unwrap();
}
/// continue execution until target halted or Timeout reached
pub fn run_to_halt(session: &mut Session) {
// check if contineing from breakpoint
if read_bkpt(session).is_some() {
println!("Continue from breakpoint.");
increment_pc(session);
} else {
println!("Continue");
}
session.target.core.run(&mut session.probe).unwrap();
println!("running");
match session.target.core.wait_for_core_halted(&mut session.probe) {
Ok(_) => {
print!("Hit breakpoint :",);
}
Err(DebugProbeError::Timeout) => {
print!("Timeout :");
}
Err(err) => panic!("internal error:{:?}", err),
}
let cpu_info = session.target.core.halt(&mut session.probe).unwrap();
println!("Core stopped at address 0x{:08x}", cpu_info.pc);
}
/// set synbolic values at address of R0
fn set_symbolic(session: &mut Session, data: &[u8]) {
let r0 = session
.target
.core
.read_core_reg(&mut session.probe, 0.into())
.unwrap();
println!("r0 0x{:08x}", r0);
println!("object {:?}", data);
// session.target.core.step(&mut session.probe).unwrap();
let r0 = session.probe.write_block8(r0, data).unwrap();
}
/// DWT_CTRL control register
const DWT_CTRL: u32 = 0xe000_1000;
/// DWT_CTRL cycle counter register
const DWT_CYCCNT: u32 = 0xe000_1004;
/// enable the cycle counter
pub fn cycnt_enable(session: &mut Session) {
session.probe.write32(DWT_CTRL, 0x1).unwrap();
}
/// stop the cycle counter
pub fn cycnt_disable(session: &mut Session) {
session.probe.write32(DWT_CTRL, 0x0).unwrap();
}
/// reset the cyclecounter to 0
pub fn cycnt_reset(session: &mut Session) {
// Reset cycle counter to 0
session.probe.write32(DWT_CYCCNT, 0x0).unwrap();
}
/// read cycle counter into u32
pub fn cycnt_read(session: &mut Session) -> u32 {
session.probe.read32(DWT_CYCCNT).unwrap()
}