Skip to content

Commit 26c2fed

Browse files
committed
fix cyccnt extension based on cortex-m change
fire just before overflow instead and don't reset cyccnt latest cortex-m changes make `new` falible remove debug code
1 parent 79ec62c commit 26c2fed

File tree

4 files changed

+39
-12
lines changed

4 files changed

+39
-12
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@ codegen-units = 1
1313
debug = true
1414
lto = true
1515
opt-level = 'z'
16+
17+
[patch.crates-io]
18+
cortex-m = { git = 'https://github.com/rust-embedded/cortex-m', package = 'cortex-m', branch = 'master' }

embedded-profiling-examples/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ default = ["panic_persist"]
3131
usb = ["usb-device", "usbd-serial"]
3232
panic_persist = ["panic-persist"]
3333
panic_halt = ["panic-halt"]
34-
extended = ["ep-systick/extended", "embedded-profiling/container-u64"]
34+
extended = ["ep-systick/extended", "ep-dwt/extended", "embedded-profiling/container-u64"]
3535

3636
[[bin]]
3737
name = "delay_usb_dwt"

embedded-profiling-examples/src/bin/delay_usb_dwt.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ fn main() -> ! {
8181
// initialize our profiling timer & structure
8282
log::debug!("initializing our tracing stuff");
8383
let dwt_profiler = cortex_m::singleton!(: ep_dwt::DwtProfiler<CORE_FREQ> =
84-
ep_dwt::DwtProfiler::new(&mut core.DCB, core.DWT, CORE_FREQ))
84+
ep_dwt::DwtProfiler::new(&mut core.DCB, core.DWT, CORE_FREQ).unwrap())
8585
.unwrap();
8686
unsafe {
8787
ep::set_profiler(dwt_profiler).unwrap();

ep-dwt/src/lib.rs

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
//! let mut core = CorePeripherals::take().unwrap();
2121
//! // (...)
2222
//! let dwt_profiler = cortex_m::singleton!(: ep_dwt::DwtProfiler::<CORE_FREQ> =
23-
//! ep_dwt::DwtProfiler::<CORE_FREQ>::new(&mut core.DCB, core.DWT, CORE_FREQ))
23+
//! ep_dwt::DwtProfiler::<CORE_FREQ>::new(&mut core.DCB, core.DWT, CORE_FREQ).unwrap())
2424
//! .unwrap();
2525
//! unsafe {
2626
//! embedded_profiling::set_profiler(dwt_profiler).unwrap();
@@ -65,6 +65,16 @@ static ROLLOVER_COUNT: AtomicU32 = AtomicU32::new(0);
6565
// For extended mode to work, we really need a u64 container. Double check this.
6666
static_assertions::assert_type_eq_all!(EPContainer, u64);
6767

68+
#[derive(Debug)]
69+
/// Things that can go wrong when configuring the [`DWT`] hardware
70+
pub enum DwtProfilerError {
71+
/// [`cortex_m::peripheral::DWT::has_cycle_counter()`] reported that this hardware
72+
/// does not support cycle count hardware
73+
CycleCounterUnsupported,
74+
/// We failed to configure cycle count compare for the `extended` feature
75+
CycleCounterInvalidSettings,
76+
}
77+
6878
/// DWT trace unit implementing [`EmbeddedProfiler`].
6979
///
7080
/// The frequency of the [`DWT`] is encoded using the parameter `FREQ`.
@@ -80,23 +90,37 @@ impl<const FREQ: u32> DwtProfiler<FREQ> {
8090
///
8191
/// # Panics
8292
/// asserts that the compile time constant `FREQ` matches the runtime provided `sysclk`
83-
pub fn new(dcb: &mut DCB, mut dwt: DWT, sysclk: u32) -> Self {
93+
pub fn new(dcb: &mut DCB, mut dwt: DWT, sysclk: u32) -> Result<Self, DwtProfilerError> {
8494
assert!(FREQ == sysclk);
8595

96+
// check if our HW supports it
97+
if !dwt.has_cycle_counter() {
98+
return Err(DwtProfilerError::CycleCounterUnsupported);
99+
}
100+
86101
// Enable the DWT block
87102
dcb.enable_trace();
88-
#[cfg(feature = "extended")]
89-
// Enable DebugMonitor exceptions to fire to track overflows
90-
unsafe {
91-
dcb.demcr.modify(|f| f | 1 << 16);
92-
}
93103
DWT::unlock();
94104

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

99-
Self { dwt }
109+
#[cfg(feature = "extended")]
110+
{
111+
use cortex_m::peripheral::dwt::{ComparatorFunction, CycleCountSettings, EmitOption};
112+
113+
// Enable DebugMonitor exceptions to fire to track overflows
114+
dcb.enable_debug_monitor();
115+
dwt.c[0]
116+
.configure(ComparatorFunction::CycleCount(CycleCountSettings {
117+
emit: EmitOption::WatchpointDebugEvent,
118+
compare: 4294967295, // just before overflow
119+
}))
120+
.map_err(|_conf_err| DwtProfilerError::CycleCounterInvalidSettings)?
121+
}
122+
123+
Ok(Self { dwt })
100124
}
101125
}
102126

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

114138
// convert count and return the instant

0 commit comments

Comments
 (0)