Skip to content

Commit

Permalink
fix cyccnt extension based on cortex-m change
Browse files Browse the repository at this point in the history
fire just before overflow instead and don't reset cyccnt

latest cortex-m changes

make `new` falible

remove debug code
  • Loading branch information
TDHolmes committed Dec 29, 2021
1 parent 79ec62c commit 26c2fed
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 12 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ codegen-units = 1
debug = true
lto = true
opt-level = 'z'

[patch.crates-io]
cortex-m = { git = 'https://github.com/rust-embedded/cortex-m', package = 'cortex-m', branch = 'master' }
2 changes: 1 addition & 1 deletion embedded-profiling-examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ default = ["panic_persist"]
usb = ["usb-device", "usbd-serial"]
panic_persist = ["panic-persist"]
panic_halt = ["panic-halt"]
extended = ["ep-systick/extended", "embedded-profiling/container-u64"]
extended = ["ep-systick/extended", "ep-dwt/extended", "embedded-profiling/container-u64"]

[[bin]]
name = "delay_usb_dwt"
Expand Down
2 changes: 1 addition & 1 deletion embedded-profiling-examples/src/bin/delay_usb_dwt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ fn main() -> ! {
// initialize our profiling timer & structure
log::debug!("initializing our tracing stuff");
let dwt_profiler = cortex_m::singleton!(: ep_dwt::DwtProfiler<CORE_FREQ> =
ep_dwt::DwtProfiler::new(&mut core.DCB, core.DWT, CORE_FREQ))
ep_dwt::DwtProfiler::new(&mut core.DCB, core.DWT, CORE_FREQ).unwrap())
.unwrap();
unsafe {
ep::set_profiler(dwt_profiler).unwrap();
Expand Down
44 changes: 34 additions & 10 deletions ep-dwt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
//! let mut core = CorePeripherals::take().unwrap();
//! // (...)
//! let dwt_profiler = cortex_m::singleton!(: ep_dwt::DwtProfiler::<CORE_FREQ> =
//! ep_dwt::DwtProfiler::<CORE_FREQ>::new(&mut core.DCB, core.DWT, CORE_FREQ))
//! ep_dwt::DwtProfiler::<CORE_FREQ>::new(&mut core.DCB, core.DWT, CORE_FREQ).unwrap())
//! .unwrap();
//! unsafe {
//! embedded_profiling::set_profiler(dwt_profiler).unwrap();
Expand Down Expand Up @@ -65,6 +65,16 @@ static ROLLOVER_COUNT: AtomicU32 = AtomicU32::new(0);
// For extended mode to work, we really need a u64 container. Double check this.
static_assertions::assert_type_eq_all!(EPContainer, u64);

#[derive(Debug)]
/// Things that can go wrong when configuring the [`DWT`] hardware
pub enum DwtProfilerError {
/// [`cortex_m::peripheral::DWT::has_cycle_counter()`] reported that this hardware
/// does not support cycle count hardware
CycleCounterUnsupported,
/// We failed to configure cycle count compare for the `extended` feature
CycleCounterInvalidSettings,
}

/// DWT trace unit implementing [`EmbeddedProfiler`].
///
/// The frequency of the [`DWT`] is encoded using the parameter `FREQ`.
Expand All @@ -80,23 +90,37 @@ impl<const FREQ: u32> DwtProfiler<FREQ> {
///
/// # Panics
/// asserts that the compile time constant `FREQ` matches the runtime provided `sysclk`
pub fn new(dcb: &mut DCB, mut dwt: DWT, sysclk: u32) -> Self {
pub fn new(dcb: &mut DCB, mut dwt: DWT, sysclk: u32) -> Result<Self, DwtProfilerError> {
assert!(FREQ == sysclk);

// check if our HW supports it
if !dwt.has_cycle_counter() {
return Err(DwtProfilerError::CycleCounterUnsupported);
}

// Enable the DWT block
dcb.enable_trace();
#[cfg(feature = "extended")]
// Enable DebugMonitor exceptions to fire to track overflows
unsafe {
dcb.demcr.modify(|f| f | 1 << 16);
}
DWT::unlock();

// reset cycle count and enable it to run
unsafe { dwt.cyccnt.write(0) };
dwt.enable_cycle_counter();

Self { dwt }
#[cfg(feature = "extended")]
{
use cortex_m::peripheral::dwt::{ComparatorFunction, CycleCountSettings, EmitOption};

// Enable DebugMonitor exceptions to fire to track overflows
dcb.enable_debug_monitor();
dwt.c[0]
.configure(ComparatorFunction::CycleCount(CycleCountSettings {
emit: EmitOption::WatchpointDebugEvent,
compare: 4294967295, // just before overflow
}))
.map_err(|_conf_err| DwtProfilerError::CycleCounterInvalidSettings)?
}

Ok(Self { dwt })
}
}

Expand All @@ -107,8 +131,8 @@ impl<const FREQ: u32> EmbeddedProfiler for DwtProfiler<FREQ> {
let mut count = EPContainer::from(self.dwt.cyccnt.read());
#[cfg(feature = "extended")]
{
count += EPContainer::from(ROLLOVER_COUNT.load(Ordering::Relaxed))
* EPContainer::from(u32::MAX);
let rollover: EPContainer = ROLLOVER_COUNT.load(Ordering::Relaxed).into();
count += rollover * (0x1_0000_0000 as EPContainer);
}

// convert count and return the instant
Expand Down

0 comments on commit 26c2fed

Please sign in to comment.