Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add methods needed for cycle count comparisons #367

Merged
merged 12 commits into from
Dec 29, 2021
17 changes: 17 additions & 0 deletions src/peripheral/dcb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::peripheral::DCB;
use core::ptr;

const DCB_DEMCR_TRCENA: u32 = 1 << 24;
const DCB_DEMCR_MON_EN: u32 = 1 << 16;

/// Register block
#[repr(C)]
Expand Down Expand Up @@ -46,6 +47,22 @@ impl DCB {
}
}

/// Enables the [`DebugMonitor`](crate::peripheral::scb::Exception::DebugMonitor) exception
#[inline]
pub fn enable_debug_monitor(&mut self) {
unsafe {
self.demcr.modify(|w| w | DCB_DEMCR_MON_EN);
}
}

/// Disables the [`DebugMonitor`](crate::peripheral::scb::Exception::DebugMonitor) exception
#[inline]
pub fn disable_debug_monitor(&mut self) {
unsafe {
self.demcr.modify(|w| w & !DCB_DEMCR_MON_EN);
}
}

/// Is there a debugger attached? (see note)
///
/// Note: This function is [reported not to
Expand Down
117 changes: 94 additions & 23 deletions src/peripheral/dwt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,17 @@ bitfield! {
#[repr(C)]
#[derive(Copy, Clone)]
/// Comparator FUNCTIONn register.
///
/// See C1.8.17 "Comparator Function registers, DWT_FUNCTIONn"
pub struct Function(u32);
u8, function, set_function: 3, 0;
emitrange, set_emitrange: 5;
cycmatch, set_cycmatch: 7;
datavmatch, set_datavmatch: 8;
lnk1ena, set_lnk1ena: 9;
u8, datavsize, set_datavsize: 11, 10;
u8, datavaddr0, set_datavaddr0: 15, 12;
u8, datavaddr1, set_datavaddr1: 19, 16;
matched, _: 24;
}

Expand Down Expand Up @@ -114,10 +120,13 @@ impl DWT {
}

/// Returns `true` if the implementation supports a cycle counter
#[cfg(not(armv6m))]
#[inline]
pub fn has_cycle_counter(&self) -> bool {
!self.ctrl.read().nocyccnt()
#[cfg(not(armv6m))]
return !self.ctrl.read().nocyccnt();

#[cfg(armv6m)]
return false;
}

/// Returns `true` if the implementation the profiling counters
Expand Down Expand Up @@ -318,15 +327,15 @@ impl DWT {
/// Whether the comparator should match on read, write or read/write operations.
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum AccessType {
/// Generate packet only when matched adress is read from.
/// Generate packet only when matched address is read from.
ReadOnly,
/// Generate packet only when matched adress is written to.
/// Generate packet only when matched address is written to.
WriteOnly,
/// Generate packet when matched adress is both read from and written to.
/// Generate packet when matched address is both read from and written to.
ReadWrite,
}

/// The sequence of packet(s) that should be emitted on comparator match.
/// The sequence of packet(s) or events that should be emitted/generated on comparator match.
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum EmitOption {
TDHolmes marked this conversation as resolved.
Show resolved Hide resolved
/// Emit only trace data value packet.
Expand All @@ -341,6 +350,14 @@ pub enum EmitOption {
AddressData,
/// Emit trace PC value and data value packets.
PCData,
/// Generate a watchpoint debug event. Either halts execution or fires a `DebugMonitor` exception.
///
/// See more in section "Watchpoint debug event generation" page C1-729.
WatchpointDebugEvent,
/// Generate a `CMPMATCH[N]` event.
///
/// See more in section "CMPMATCH[N] event generation" page C1-730.
CompareMatchEvent,
}

/// Settings for address matching
Expand All @@ -356,12 +373,27 @@ pub struct ComparatorAddressSettings {
pub access_type: AccessType,
}

/// Settings for cycle count matching
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub struct CycleCountSettings {
TDHolmes marked this conversation as resolved.
Show resolved Hide resolved
/// The function selection used.
/// See Table C1-15 for DWT cycle count comparison functions.
pub emit: EmitOption,
/// The cycle count value to compare against.
pub compare: u32,
}

/// The available functions of a DWT comparator.
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[non_exhaustive]
pub enum ComparatorFunction {
/// Compare accessed memory addresses.
Address(ComparatorAddressSettings),
/// Compare cycle count & target value.
///
/// **NOTE**: only supported by comparator 0 and if the HW supports the cycle counter.
/// Check [`DWT::has_cycle_counter`] for support. See C1.8.1 for more details.
CycleCount(CycleCountSettings),
TDHolmes marked this conversation as resolved.
Show resolved Hide resolved
}

/// Possible error values returned on [Comparator::configure].
Expand All @@ -377,46 +409,85 @@ impl Comparator {
#[allow(clippy::missing_inline_in_public_items)]
pub fn configure(&self, settings: ComparatorFunction) -> Result<(), DwtError> {
match settings {
ComparatorFunction::Address(settings) => unsafe {
ComparatorFunction::Address(settings) => {
// FUNCTION, EMITRANGE
// See Table C1-14
let (function, emit_range) = match (&settings.access_type, &settings.emit) {
(AccessType::ReadOnly, EmitOption::Data) => (0b1100, false),
(AccessType::ReadOnly, EmitOption::Address) => (0b1100, true),
(AccessType::ReadOnly, EmitOption::AddressData) => (0b1110, true),
(AccessType::ReadOnly, EmitOption::PCData) => (0b1110, false),
(AccessType::ReadOnly, EmitOption::WatchpointDebugEvent) => (0b0101, false),
(AccessType::ReadOnly, EmitOption::CompareMatchEvent) => (0b1001, false),
TDHolmes marked this conversation as resolved.
Show resolved Hide resolved

(AccessType::WriteOnly, EmitOption::Data) => (0b1101, false),
(AccessType::WriteOnly, EmitOption::Address) => (0b1101, true),
(AccessType::WriteOnly, EmitOption::AddressData) => (0b1111, true),
(AccessType::WriteOnly, EmitOption::PCData) => (0b1111, false),
(AccessType::WriteOnly, EmitOption::WatchpointDebugEvent) => (0b0110, false),
(AccessType::WriteOnly, EmitOption::CompareMatchEvent) => (0b1010, false),

(AccessType::ReadWrite, EmitOption::Data) => (0b0010, false),
(AccessType::ReadWrite, EmitOption::Address) => (0b0001, true),
(AccessType::ReadWrite, EmitOption::AddressData) => (0b0010, true),
(AccessType::ReadWrite, EmitOption::PCData) => (0b0011, false),
(AccessType::ReadWrite, EmitOption::WatchpointDebugEvent) => (0b0111, false),
(AccessType::ReadWrite, EmitOption::CompareMatchEvent) => (0b1011, false),

(AccessType::ReadWrite, EmitOption::PC) => (0b0001, false),
(_, EmitOption::PC) => return Err(DwtError::InvalidFunction),
};

self.function.modify(|mut r| {
r.set_function(function);
r.set_emitrange(emit_range);

// don't compare data value
r.set_datavmatch(false);

// don't compare cycle counter value
// NOTE: only needed for comparator 0, but is SBZP.
r.set_cycmatch(false);

r
});
unsafe {
self.function.modify(|mut r| {
r.set_function(function);
r.set_emitrange(emit_range);
// don't compare data value
r.set_datavmatch(false);
// don't compare cycle counter value
// NOTE: only needed for comparator 0, but is SBZP.
r.set_cycmatch(false);
TDHolmes marked this conversation as resolved.
Show resolved Hide resolved
// SBZ as needed, see Page 784/C1-724
r.set_datavsize(0);
r.set_datavaddr0(0);
r.set_datavaddr1(0);

r
});

self.comp.write(settings.address);
self.mask.write(settings.mask);
}
}
ComparatorFunction::CycleCount(settings) => {
TDHolmes marked this conversation as resolved.
Show resolved Hide resolved
let function = match &settings.emit {
EmitOption::PCData => 0b0001,
EmitOption::WatchpointDebugEvent => 0b0100,
EmitOption::CompareMatchEvent => 0b1000,
_ => return Err(DwtError::InvalidFunction),
};

self.comp.write(settings.address);
self.mask.write(settings.mask);
},
unsafe {
self.function.modify(|mut r| {
r.set_function(function);
// emit_range is N/A for cycle count compare
r.set_emitrange(false);
// don't compare data
r.set_datavmatch(false);
// compare cyccnt
r.set_cycmatch(true);
// SBZ as needed, see Page 784/C1-724
r.set_datavsize(0);
r.set_datavaddr0(0);
r.set_datavaddr1(0);

r
});

self.comp.write(settings.compare);
self.mask.write(0); // SBZ, see Page 784/C1-724
}
}
}

Ok(())
Expand Down