use crate::config::target::Target;
use crate::probe::{DebugProbeError, MasterProbe};
pub struct Session {
pub target: Target,
pub probe: MasterProbe,
hw_breakpoint_enabled: bool,
active_breakpoints: Vec<Breakpoint>,
}
impl Session {
pub fn new(target: Target, probe: MasterProbe) -> Self {
Self {
target,
probe,
hw_breakpoint_enabled: false,
active_breakpoints: Vec::new(),
}
}
pub fn set_hw_breakpoint(&mut self, address: u32) -> Result<(), DebugProbeError> {
log::debug!("Trying to set HW breakpoint at address {:#08x}", address);
let num_hw_breakpoints =
self.target
.core
.get_available_breakpoint_units(&mut self.probe)? as usize;
log::debug!("{} HW breakpoints are supported.", num_hw_breakpoints);
if num_hw_breakpoints <= self.active_breakpoints.len() {
log::warn!("Maximum number of breakpoints ({}) reached, unable to set additional HW breakpoint.", num_hw_breakpoints);
return Err(DebugProbeError::UnknownError);
}
if !self.hw_breakpoint_enabled {
self.target.core.enable_breakpoints(&mut self.probe, true)?;
self.hw_breakpoint_enabled = true;
}
let bp_unit = self.find_free_breakpoint_unit();
log::debug!("Using comparator {} of breakpoint unit", bp_unit);
self.target
.core
.set_breakpoint(&mut self.probe, bp_unit, address)?;
self.active_breakpoints.push(Breakpoint {
address,
register_hw: bp_unit,
});
Ok(())
}
pub fn clear_hw_breakpoint(&mut self, address: u32) -> Result<(), DebugProbeError> {
let bp_position = self
.active_breakpoints
.iter()
.position(|bp| bp.address == address);
match bp_position {
Some(bp_position) => {
let bp = &self.active_breakpoints[bp_position];
self.target
.core
.clear_breakpoint(&mut self.probe, bp.register_hw)?;
self.active_breakpoints.swap_remove(bp_position);
Ok(())
}
None => Err(DebugProbeError::UnknownError),
}
}
fn find_free_breakpoint_unit(&self) -> usize {
let mut used_bp: Vec<_> = self
.active_breakpoints
.iter()
.map(|bp| bp.register_hw)
.collect();
used_bp.sort();
let mut free_bp = 0;
for bp in used_bp {
if bp == free_bp {
free_bp += 1;
} else {
return free_bp;
}
}
free_bp
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct BreakpointId(usize);
impl BreakpointId {
pub fn new(id: usize) -> Self {
BreakpointId(id)
}
}
struct Breakpoint {
address: u32,
register_hw: usize,
}
unsafe impl Send for Session {}