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.
6666static_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