@@ -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,7 +123,22 @@ 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
@@ -94,4 +158,93 @@ impl DWT {
94158 // NOTE(unsafe) atomic write to a stateless, write-only register
95159 unsafe { ( * Self :: ptr ( ) ) . lar . write ( 0xC5AC_CE55 ) }
96160 }
161+
162+ /// Get the CPI count
163+ ///
164+ /// Counts additional cycles required to execute multi-cycle instructions,
165+ /// except those recorded by [`lsu_count`], and counts any instruction fetch
166+ /// stalls.
167+ ///
168+ /// [`lsu_count`]: DWT::lsu_count
169+ #[ cfg( not( armv6m) ) ]
170+ #[ inline]
171+ pub fn cpi_count ( ) -> u8 {
172+ // NOTE(unsafe) atomic read with no side effects
173+ unsafe { ( * Self :: ptr ( ) ) . cpicnt . read ( ) as u8 }
174+ }
175+
176+ /// Set the CPI count
177+ #[ cfg( not( armv6m) ) ]
178+ #[ inline]
179+ pub fn set_cpi_count ( & mut self , count : u8 ) {
180+ unsafe { self . cpicnt . write ( count as u32 ) }
181+ }
182+
183+ /// Get the total cycles spent in exception processing
184+ #[ cfg( not( armv6m) ) ]
185+ #[ inline]
186+ pub fn exception_count ( ) -> u8 {
187+ // NOTE(unsafe) atomic read with no side effects
188+ unsafe { ( * Self :: ptr ( ) ) . exccnt . read ( ) as u8 }
189+ }
190+
191+ /// Set the exception count
192+ #[ cfg( not( armv6m) ) ]
193+ #[ inline]
194+ pub fn set_exception_count ( & mut self , count : u8 ) {
195+ unsafe { self . exccnt . write ( count as u32 ) }
196+ }
197+
198+ /// Get the total number of cycles that the processor is sleeping
199+ ///
200+ /// ARM recommends that this counter counts all cycles when the processor is sleeping,
201+ /// regardless of whether a WFI or WFE instruction, or the sleep-on-exit functionality,
202+ /// caused the entry to sleep mode.
203+ /// However, all sleep features are implementation defined and therefore when
204+ /// this counter counts is implementation defined.
205+ #[ cfg( not( armv6m) ) ]
206+ #[ inline]
207+ pub fn sleep_count ( ) -> u8 {
208+ // NOTE(unsafe) atomic read with no side effects
209+ unsafe { ( * Self :: ptr ( ) ) . sleepcnt . read ( ) as u8 }
210+ }
211+
212+ /// Set the sleep count
213+ #[ cfg( not( armv6m) ) ]
214+ #[ inline]
215+ pub fn set_sleep_count ( & mut self , count : u8 ) {
216+ unsafe { self . sleepcnt . write ( count as u32 ) }
217+ }
218+
219+ /// Get the additional cycles required to execute all load or store instructions
220+ #[ cfg( not( armv6m) ) ]
221+ #[ inline]
222+ pub fn lsu_count ( ) -> u8 {
223+ // NOTE(unsafe) atomic read with no side effects
224+ unsafe { ( * Self :: ptr ( ) ) . lsucnt . read ( ) as u8 }
225+ }
226+
227+ /// Set the lsu count
228+ #[ cfg( not( armv6m) ) ]
229+ #[ inline]
230+ pub fn set_lsu_count ( & mut self , count : u8 ) {
231+ unsafe { self . lsucnt . write ( count as u32 ) }
232+ }
233+
234+ /// Get the folded instruction count
235+ ///
236+ /// Increments on each instruction that takes 0 cycles.
237+ #[ cfg( not( armv6m) ) ]
238+ #[ inline]
239+ pub fn fold_count ( ) -> u8 {
240+ // NOTE(unsafe) atomic read with no side effects
241+ unsafe { ( * Self :: ptr ( ) ) . foldcnt . read ( ) as u8 }
242+ }
243+
244+ /// Set the folded instruction count
245+ #[ cfg( not( armv6m) ) ]
246+ #[ inline]
247+ pub fn set_fold_count ( & mut self , count : u8 ) {
248+ unsafe { self . foldcnt . write ( count as u32 ) }
249+ }
97250}
0 commit comments