@@ -62,7 +62,56 @@ pub struct Comparator {
6262 reserved : u32 ,
6363}
6464
65+ // DWT CTRL register fields
66+ const NUMCOMP_OFFSET : u32 = 28 ;
67+ const NOTRCPKT : u32 = 1 << 27 ;
68+ const NOEXTTRIG : u32 = 1 << 26 ;
69+ const NOCYCCNT : u32 = 1 << 25 ;
70+ const NOPRFCNT : u32 = 1 << 24 ;
71+ const CYCCNTENA : u32 = 1 << 0 ;
72+
6573impl DWT {
74+ /// Number of comparators implemented
75+ ///
76+ /// A value of zero indicates no comparator support.
77+ #[ inline]
78+ pub fn num_comp ( ) -> u8 {
79+ // NOTE(unsafe) atomic read with no side effects
80+ unsafe { ( ( * Self :: ptr ( ) ) . ctrl . read ( ) >> NUMCOMP_OFFSET ) as u8 }
81+ }
82+
83+ /// Returns `true` if the the implementation supports sampling and exception tracing
84+ #[ cfg( not( armv6m) ) ]
85+ #[ inline]
86+ pub fn has_exception_trace ( ) -> bool {
87+ // NOTE(unsafe) atomic read with no side effects
88+ unsafe { ( * Self :: ptr ( ) ) . ctrl . read ( ) & NOTRCPKT == 0 }
89+ }
90+
91+ /// Returns `true` if the implementation includes external match signals
92+ #[ cfg( not( armv6m) ) ]
93+ #[ inline]
94+ pub fn has_external_match ( ) -> bool {
95+ // NOTE(unsafe) atomic read with no side effects
96+ unsafe { ( * Self :: ptr ( ) ) . ctrl . read ( ) & NOEXTTRIG == 0 }
97+ }
98+
99+ /// Returns `true` if the implementation supports a cycle counter
100+ #[ cfg( not( armv6m) ) ]
101+ #[ inline]
102+ pub fn has_cycle_counter ( ) -> bool {
103+ // NOTE(unsafe) atomic read with no side effects
104+ unsafe { ( * Self :: ptr ( ) ) . ctrl . read ( ) & NOCYCCNT == 0 }
105+ }
106+
107+ /// Returns `true` if the implementation the profiling counters
108+ #[ cfg( not( armv6m) ) ]
109+ #[ inline]
110+ pub fn has_profiling_counter ( ) -> bool {
111+ // NOTE(unsafe) atomic read with no side effects
112+ unsafe { ( * Self :: ptr ( ) ) . ctrl . read ( ) & NOPRFCNT == 0 }
113+ }
114+
66115 /// Enables the cycle counter
67116 ///
68117 /// The global trace enable ([`DCB::enable_trace`]) should be set before
@@ -74,13 +123,39 @@ impl DWT {
74123 #[ cfg( not( armv6m) ) ]
75124 #[ inline]
76125 pub fn enable_cycle_counter ( & mut self ) {
77- unsafe { self . ctrl . modify ( |r| r | 1 ) }
126+ unsafe { self . ctrl . modify ( |r| r | CYCCNTENA ) }
127+ }
128+
129+ /// Disables the cycle counter
130+ #[ cfg( not( armv6m) ) ]
131+ #[ inline]
132+ pub fn disable_cycle_counter ( & mut self ) {
133+ unsafe { self . ctrl . modify ( |r| r & !CYCCNTENA ) }
134+ }
135+
136+ /// Returns `true` if the cycle counter is enabled
137+ #[ cfg( not( armv6m) ) ]
138+ #[ inline]
139+ pub fn cycle_counter_enabled ( ) -> bool {
140+ // NOTE(unsafe) atomic read with no side effects
141+ unsafe { ( * Self :: ptr ( ) ) . ctrl . read ( ) & CYCCNTENA != 0 }
78142 }
79143
80144 /// Returns the current clock cycle count
81145 #[ cfg( not( armv6m) ) ]
82146 #[ inline]
147+ #[ deprecated(
148+ since = "0.7.4" ,
149+ note = "Use `cycle_count` which follows the C-GETTER convention"
150+ ) ]
83151 pub fn get_cycle_count ( ) -> u32 {
152+ Self :: cycle_count ( )
153+ }
154+
155+ /// Returns the current clock cycle count
156+ #[ cfg( not( armv6m) ) ]
157+ #[ inline]
158+ pub fn cycle_count ( ) -> u32 {
84159 // NOTE(unsafe) atomic read with no side effects
85160 unsafe { ( * Self :: ptr ( ) ) . cyccnt . read ( ) }
86161 }
@@ -94,4 +169,93 @@ impl DWT {
94169 // NOTE(unsafe) atomic write to a stateless, write-only register
95170 unsafe { ( * Self :: ptr ( ) ) . lar . write ( 0xC5AC_CE55 ) }
96171 }
172+
173+ /// Get the CPI count
174+ ///
175+ /// Counts additional cycles required to execute multi-cycle instructions,
176+ /// except those recorded by [`lsu_count`], and counts any instruction fetch
177+ /// stalls.
178+ ///
179+ /// [`lsu_count`]: DWT::lsu_count
180+ #[ cfg( not( armv6m) ) ]
181+ #[ inline]
182+ pub fn cpi_count ( ) -> u8 {
183+ // NOTE(unsafe) atomic read with no side effects
184+ unsafe { ( * Self :: ptr ( ) ) . cpicnt . read ( ) as u8 }
185+ }
186+
187+ /// Set the CPI count
188+ #[ cfg( not( armv6m) ) ]
189+ #[ inline]
190+ pub fn set_cpi_count ( & mut self , count : u8 ) {
191+ unsafe { self . cpicnt . write ( count as u32 ) }
192+ }
193+
194+ /// Get the total cycles spent in exception processing
195+ #[ cfg( not( armv6m) ) ]
196+ #[ inline]
197+ pub fn exception_count ( ) -> u8 {
198+ // NOTE(unsafe) atomic read with no side effects
199+ unsafe { ( * Self :: ptr ( ) ) . exccnt . read ( ) as u8 }
200+ }
201+
202+ /// Set the exception count
203+ #[ cfg( not( armv6m) ) ]
204+ #[ inline]
205+ pub fn set_exception_count ( & mut self , count : u8 ) {
206+ unsafe { self . exccnt . write ( count as u32 ) }
207+ }
208+
209+ /// Get the total number of cycles that the processor is sleeping
210+ ///
211+ /// ARM recommends that this counter counts all cycles when the processor is sleeping,
212+ /// regardless of whether a WFI or WFE instruction, or the sleep-on-exit functionality,
213+ /// caused the entry to sleep mode.
214+ /// However, all sleep features are implementation defined and therefore when
215+ /// this counter counts is implementation defined.
216+ #[ cfg( not( armv6m) ) ]
217+ #[ inline]
218+ pub fn sleep_count ( ) -> u8 {
219+ // NOTE(unsafe) atomic read with no side effects
220+ unsafe { ( * Self :: ptr ( ) ) . sleepcnt . read ( ) as u8 }
221+ }
222+
223+ /// Set the sleep count
224+ #[ cfg( not( armv6m) ) ]
225+ #[ inline]
226+ pub fn set_sleep_count ( & mut self , count : u8 ) {
227+ unsafe { self . sleepcnt . write ( count as u32 ) }
228+ }
229+
230+ /// Get the additional cycles required to execute all load or store instructions
231+ #[ cfg( not( armv6m) ) ]
232+ #[ inline]
233+ pub fn lsu_count ( ) -> u8 {
234+ // NOTE(unsafe) atomic read with no side effects
235+ unsafe { ( * Self :: ptr ( ) ) . lsucnt . read ( ) as u8 }
236+ }
237+
238+ /// Set the lsu count
239+ #[ cfg( not( armv6m) ) ]
240+ #[ inline]
241+ pub fn set_lsu_count ( & mut self , count : u8 ) {
242+ unsafe { self . lsucnt . write ( count as u32 ) }
243+ }
244+
245+ /// Get the folded instruction count
246+ ///
247+ /// Increments on each instruction that takes 0 cycles.
248+ #[ cfg( not( armv6m) ) ]
249+ #[ inline]
250+ pub fn fold_count ( ) -> u8 {
251+ // NOTE(unsafe) atomic read with no side effects
252+ unsafe { ( * Self :: ptr ( ) ) . foldcnt . read ( ) as u8 }
253+ }
254+
255+ /// Set the folded instruction count
256+ #[ cfg( not( armv6m) ) ]
257+ #[ inline]
258+ pub fn set_fold_count ( & mut self , count : u8 ) {
259+ unsafe { self . foldcnt . write ( count as u32 ) }
260+ }
97261}
0 commit comments