cortexm/dwt.rs
1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Cortex-M Data Watchpoint and Trace Unit (DWT)
6//!
7//! <https://developer.arm.com/documentation/100166/0001/Data-Watchpoint-and-Trace-Unit/DWT-Programmers--model?lang=en>
8
9use super::dcb;
10use kernel::hil;
11use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
12use kernel::utilities::registers::{register_bitfields, register_structs, ReadOnly, ReadWrite};
13use kernel::utilities::StaticRef;
14
15register_structs! {
16 /// In an ARMv7-M processor, a System Control Block (SCB) in the SCS
17 /// provides key status information and control features for the processor.
18 DwtRegisters {
19 // Control Register
20 (0x00 => ctrl: ReadWrite<u32, Control::Register>),
21
22 // Cycle Count Register
23 (0x04 => cyccnt: ReadWrite<u32, CycleCount::Register>),
24
25 // CPI Count Register
26 (0x08 => cpicnt: ReadWrite<u32, CpiCount::Register>),
27
28 // Exception Overhead Register
29 (0x0C => exccnt: ReadWrite<u32, ExceptionOverheadCount::Register>),
30
31 // Sleep Count Register
32 (0x10 => sleepcnt: ReadWrite<u32, SleepCount::Register>),
33
34 // LSU Count Register
35 (0x14 => lsucnt: ReadWrite<u32, LsuCount::Register>),
36
37 // Folder-Instruction Count Register
38 (0x18 => foldcnt: ReadWrite<u32, FoldedInstructionCount::Register>),
39
40 // Program Count Sample Register
41 (0x1C => pcsr: ReadOnly<u32, ProgramCounterSample::Register>),
42
43 // Comparator Register0
44 (0x20 => comp0: ReadWrite<u32, Comparator0::Register>),
45
46 // Mask Register0
47 // The maximum mask size is 32KB
48 (0x24 => mask0: ReadWrite<u32, Comparator0Mask::Register>),
49
50 // Function Register0
51 (0x28 => function0: ReadWrite<u32, Comparator0Function::Register>),
52
53 (0x2c => _reserved0),
54
55 // Comparator Register1
56 (0x30 => comp1: ReadWrite<u32, Comparator1::Register>),
57
58 // Mask Register1
59 // The maximum mask size is 32KB
60 (0x34 => mask1: ReadWrite<u32, Comparator1Mask::Register>),
61
62 // Function Register1
63 (0x38 => function1: ReadWrite<u32, Comparator1Function::Register>),
64
65 (0x3c => _reserved1),
66
67 // Comparator Register2
68 (0x40 => comp2: ReadWrite<u32, Comparator2::Register>),
69
70 // Mask Register2
71 // The maximum mask size is 32KB
72 (0x44 => mask2: ReadWrite<u32, Comparator2Mask::Register>),
73
74 // Function Register2
75 (0x48 => function2: ReadWrite<u32, Comparator2Function::Register>),
76
77 (0x4c => _reserved2),
78
79 // Comparator Register3
80 (0x50 => comp3: ReadWrite<u32, Comparator3::Register>),
81
82 // Mask Register3
83 // The maximum mask size is 33KB
84 (0x54 => mask3: ReadWrite<u32, Comparator3Mask::Register>),
85
86 // Function Register3
87 (0x58 => function3: ReadWrite<u32, Comparator3Function::Register>),
88
89 (0x5c => @END),
90 }
91}
92
93register_bitfields![u32,
94 Control [
95 /// Number of Camparators implemented.
96 /// RO.
97 NUMCOMP OFFSET(28) NUMBITS(4),
98
99 /// Shows if trace sampling and exception tracing is implemented
100 /// Is 0 if supported, is 1 if it is not.
101 /// RO
102 NOTRCPKT OFFSET(27) NUMBITS(1),
103
104 /// Shows if external match signals ([`CMPMATCH`]) are implemented
105 /// Is 0 if supported, is 1 if it is not.
106 /// RO
107 NOEXITTRIG OFFSET(26) NUMBITS(1),
108
109 /// Shows if the cycle counter is implemented
110 /// Is 0 if supported, is 1 if it is not.
111 /// RO
112 NOCYCCNT OFFSET(25) NUMBITS(1),
113
114 /// Shows if profiling counters are supported.
115 /// Is 0 if supported, is 1 if it is not.
116 /// RO
117 NOPERFCNT OFFSET(24) NUMBITS(1),
118
119 /// Writing 1 enables event counter packets generation if
120 /// [`PCSAMPLENA`] is set to 0. Defaults to 0b0 on reset.
121 /// WARN: This bit is UNKNOWN if [`NOTPRCPKT`] or [`NOCYCCNT`] is read
122 /// as one.
123 /// RW
124 CYCEVTENA OFFSET(22) NUMBITS(1),
125
126 /// Writing 1 enables generation of folded instruction counter overflow
127 /// event. Defaults to 0b0 on reset.
128 /// WARN: This bit is UNKNOWN if [`NOPERFCNT`] reads as one.
129 /// RW
130 FOLDEVTENA OFFSET(21) NUMBITS(1),
131
132 /// Writing 1 enables generation of LSU counter overflow event.
133 /// Defaults to 0b0 on reset.
134 /// WARN: This bit is UNKNOWN if [`NOPERFCNT`] reads as one.
135 /// RW
136 LSUEVTENA OFFSET(20) NUMBITS(1),
137
138 /// Writing 1 enables generation of sleep counter overflow event.
139 /// Defaults to 0b0 on reset.
140 /// WARN: This bit is UNKNOWN if [`NOPERFCNT`] reads as one.
141 /// RW
142 SLEEPEVTENA OFFSET(19) NUMBITS(1),
143
144 /// Writing 1 enables generation of exception overhead counter overflow event.
145 /// Defaults to 0b0 on reset.
146 /// WARN: This bit is UNKNOWN if [`NOPERFCNT`] reads as one.
147 /// RW
148 EXCEVTENA OFFSET(18) NUMBITS(1),
149
150 /// Writing 1 enables generation of the CPI counter overlow event.
151 /// Defaults to 0b0 on reset.
152 /// WARN: This bit is UNKNOWN if [`NOPERFCNT`] reads as one.
153 /// RW
154 CPIEVTENA OFFSET(17) NUMBITS(1),
155
156 /// Writing 1 enables generation of exception trace.
157 /// Defaults to 0b0 on reset.
158 /// WARN: This bit is UNKNOWN if [`NOTRCPKT`] reads as one.
159 /// RW
160 EXCTRCENA OFFSET(16) NUMBITS(1),
161
162 /// Writing 1 enables use of [`POSTCNT`] counter as a timer for Periodic
163 /// PC sample packet generation.
164 /// Defaults to 0b0 on reset.
165 /// WARN: This bit is UNKNOWN if [`NOTRCPKT`] or [`NOCYCCNT`] read as one.
166 /// RW
167 PCSAMPLENA OFFSET(12) NUMBITS(1),
168
169 /// Determines the position of synchronisation packet counter tap on the
170 /// `CYCCNT` counter and thus the synchronisation packet rate. Defaults
171 /// to UNKNOWN on reset.
172 /// WARN: This bit is UNKNOWN if [`NOCYCCNT`] reads as one.
173 /// RW
174 SYNCTAP OFFSET(10) NUMBITS(2),
175
176 /// Determines the position of the [`POSTCNT`] tap on the [`CYCCNT`] counter.
177 /// Defaults to UNKNOWN on reset.
178 /// WARN: This bit is UNKNOWN if [`NOCYCCNT`] reads as one.
179 /// RW
180 CYCTAP OFFSET(9) NUMBITS(1),
181
182 /// Initial value for the [`POSTCNT`] counter.
183 /// Defaults to UNKNOWN on reset.
184 /// WARN: This bit is UNKNOWN if [`NOCYCCNT`] reads as one.
185 /// RW
186 POSTINIT OFFSET(8) NUMBITS(4),
187
188 /// Reload value for the [`POSTCNT`] counter.
189 /// Defaults to UNKNOWN on reset.
190 /// WARN: This bit is UNKNOWN if [`NOCYCCNT`] reads as one.
191 /// RW
192 POSTPRESET OFFSET(1) NUMBITS(4),
193
194 /// Writing 1 enables [`CYCCNT`].
195 /// Defaults to 0b0 on reset.
196 /// WARN: This bit is UNKNOWN if [`NOCYCCNT`] reads as one.
197 /// RW
198 CYCNTENA OFFSET(0) NUMBITS(1),
199 ],
200
201 CycleCount[
202 /// When enabled, increases on each processor clock cycle when
203 /// [`Control::CYCNTENA`] and [`DEMCRL::TRCENA`] read as one. Wraps to
204 /// zero on overflow.
205 CYCCNT OFFSET(0) NUMBITS(32),
206 ],
207
208 CpiCount[
209 /// Base instruction overhead counter.
210 CPICNT OFFSET(0) NUMBITS(8),
211 ],
212
213 ExceptionOverheadCount[
214 /// Counts cycles spent in exception processing.
215 EXCCNT OFFSET(0) NUMBITS(8),
216 ],
217
218 SleepCount[
219 /// Counts each cycle the processor is sleeping.
220 SLEEPCNT OFFSET(0) NUMBITS(8),
221 ],
222
223 LsuCount[
224 /// Counts additional cycles required to execute all load store
225 /// instructions
226 LSUCNT OFFSET(0) NUMBITS(8),
227 ],
228
229 FoldedInstructionCount[
230 /// Increments by one for each instruction that takes 0 cycles to
231 /// execute.
232 FOLDCNT OFFSET(0) NUMBITS(8),
233 ],
234
235 ProgramCounterSample[
236 /// Samples current value of the program counter
237 /// RO.
238 EIASAMPLE OFFSET(0) NUMBITS(32),
239 ],
240
241 Comparator0[
242 /// Reference value for comparator 0.
243 COMP OFFSET(0) NUMBITS(32),
244 ],
245
246 Comparator0Mask[
247 /// Size of ignore mask applied to the access address for address range
248 /// matching by comparator 0.
249 ///
250 /// WARN: Maximum Mask size is IMPLEMENTATION DEFINED.
251 MASK OFFSET(0) NUMBITS(5),
252 ],
253
254 Comparator0Function[
255 /// Is one if comparator matches. Reading the register clears it to 0.
256 /// RO.
257 MATCHED OFFSET(24) NUMBITS(1),
258
259 /// Second comparator number for linked address comparison.
260 /// Works, when `DATAVMATCH` and `LNK1ENA` read as one.
261 /// RW.
262 DATAVADDR1 OFFSET(16) NUMBITS(4),
263
264 /// Comparator number for linked address comparison.
265 /// Works, when `DATAVMATCH` reads as one.
266 /// RW.
267 DATAVADDR0 OFFSET(12) NUMBITS(4),
268
269 /// Size of data comparison (Byte, Halfword, Word).
270 /// RW.
271 DATAVSIZE OFFSET(10) NUMBITS(2),
272
273 /// Reads as one if a second linked comparator is supported.
274 LNK1ENA OFFSET(9) NUMBITS(1),
275
276 /// Enables data value comparison
277 /// When 0: Perform address comparison, when 1: data value comparison.
278 /// RW.
279 DATAVMATCH OFFSET(8) NUMBITS(1),
280
281 /// Enable cycle count comparison for comparator 0.
282 /// WARN: Only supported by FUNCTION0
283 /// RW.
284 CYCMATCH OFFSET(7) NUMBITS(1),
285
286 /// Write 1 to enable generation of data trace address packets.
287 /// WARN: If [`Control::NOTRCPKT`] reads as zero, this bit is UNKNOWN.
288 /// RW.
289 EMITRANGE OFFSET(5) NUMBITS(1),
290
291 /// Selects action taken on comparator match.
292 /// Resets to 0b0000.
293 /// RW.
294 FUNCTION OFFSET(0) NUMBITS(4),
295 ],
296
297 Comparator1[
298 /// Reference value for comparator 0.
299 COMP OFFSET(0) NUMBITS(32),
300 ],
301
302 Comparator1Mask[
303 /// Size of ignore mask applied to the access address for address range
304 /// matching by comparator 0.
305 ///
306 /// WARN: Maximum Mask size is IMPLEMENTATION DEFINED.
307 MASK OFFSET(0) NUMBITS(5),
308 ],
309
310 Comparator1Function[
311 /// Is one if comparator matches. Reading the register clears it to 0.
312 /// RO.
313 MATCHED OFFSET(24) NUMBITS(1),
314
315 /// Second comparator number for linked address comparison.
316 /// Works, when `DATAVMATCH` and `LNK1ENA` read as one.
317 /// RW.
318 DATAVADDR1 OFFSET(16) NUMBITS(4),
319
320 /// Comparator number for linked address comparison.
321 /// Works, when [`DATAVMATCH`] reads as one.
322 /// RW.
323 DATAVADDR0 OFFSET(12) NUMBITS(4),
324
325 /// Size of data comparison (Byte, Halfword, Word).
326 /// RW.
327 DATAVSIZE OFFSET(10) NUMBITS(2),
328
329 /// Reads as one if a second linked comparator is supported.
330 LNK1ENA OFFSET(9) NUMBITS(1),
331
332 /// Enables data value comparison
333 /// When 0: Perform address comparison, when 1: data value comparison.
334 /// RW.
335 DATAVMATCH OFFSET(8) NUMBITS(1),
336
337 /// Write 1 to enable generation of data trace address packets.
338 /// WARN: If `Control::NOTRCPKT` reads as zero, this bit is UNKNOWN.
339 /// RW.
340 EMITRANGE OFFSET(5) NUMBITS(1),
341
342 /// Selects action taken on comparator match.
343 /// Resets to 0b0000.
344 /// RW.
345 FUNCTION OFFSET(0) NUMBITS(4),
346 ],
347
348 Comparator2[
349 /// Reference value for comparator 0.
350 COMP OFFSET(0) NUMBITS(32),
351 ],
352
353 Comparator2Mask[
354 /// Size of ignore mask applied to the access address for address range
355 /// matching by comparator 0.
356 ///
357 /// WARN: Maximum Mask size is IMPLEMENTATION DEFINED.
358 MASK OFFSET(0) NUMBITS(5),
359 ],
360
361 Comparator2Function[
362 /// Is one if comparator matches. Reading the register clears it to 0.
363 /// RO.
364 MATCHED OFFSET(24) NUMBITS(1),
365
366 /// Second comparator number for linked address comparison.
367 /// Works, when [`DATAVMATCH`] and [`LNK1ENA`] read as one.
368 /// RW.
369 DATAVADDR1 OFFSET(16) NUMBITS(4),
370
371 /// Comparator number for linked address comparison.
372 /// Works, when `DATAVMATCH` reads as one.
373 /// RW.
374 DATAVADDR0 OFFSET(12) NUMBITS(4),
375
376 /// Size of data comparison (Byte, Halfword, Word).
377 /// RW.
378 DATAVSIZE OFFSET(10) NUMBITS(2),
379
380 /// Reads as one if a second linked comparator is supported.
381 LNK1ENA OFFSET(9) NUMBITS(1),
382
383 /// Enables data value comparison
384 /// When 0: Perform address comparison, when 1: data value comparison.
385 /// RW.
386 DATAVMATCH OFFSET(8) NUMBITS(1),
387
388 /// Write 1 to enable generation of data trace address packets.
389 /// WARN: If `Control::NOTRCPKT` reads as zero, this bit is UNKNOWN.
390 /// RW.
391 EMITRANGE OFFSET(5) NUMBITS(1),
392
393 /// Selects action taken on comparator match.
394 /// Resets to 0b0000.
395 /// RW.
396 FUNCTION OFFSET(0) NUMBITS(4),
397 ],
398
399 Comparator3[
400 /// Reference value for comparator 0.
401 COMP OFFSET(0) NUMBITS(32),
402 ],
403
404 Comparator3Mask[
405 /// Size of ignore mask applied to the access address for address range
406 /// matching by comparator 0.
407 ///
408 /// WARN: Maximum Mask size is IMPLEMENTATION DEFINED.
409 MASK OFFSET(0) NUMBITS(5),
410 ],
411
412 Comparator3Function[
413 /// Is one if comparator matches. Reading the register clears it to 0.
414 /// RO.
415 MATCHED OFFSET(24) NUMBITS(1),
416
417 /// Second comparator number for linked address comparison.
418 /// Works, when `DATAVMATCH` and `LNK1ENA` read as one.
419 /// RW.
420 DATAVADDR1 OFFSET(16) NUMBITS(4),
421
422 /// Comparator number for linked address comparison.
423 /// Works, when `DATAVMATCH` reads as one.
424 /// RW.
425 DATAVADDR0 OFFSET(12) NUMBITS(4),
426
427 /// Size of data comparison (Byte, Halfword, Word).
428 /// RW.
429 DATAVSIZE OFFSET(10) NUMBITS(2),
430
431 /// Reads as one if a second linked comparator is supported.
432 LNK1ENA OFFSET(9) NUMBITS(1),
433
434 /// Enables data value comparison
435 /// When 0: Perform address comparison, when 1: data value comparison.
436 /// RW.
437 DATAVMATCH OFFSET(8) NUMBITS(1),
438
439 /// Write 1 to enable generation of data trace address packets.
440 /// WARN: If `Control::NOTRCPKT` reads as zero, this bit is UNKNOWN.
441 /// RW.
442 EMITRANGE OFFSET(5) NUMBITS(1),
443
444 /// Selects action taken on comparator match.
445 /// Resets to 0b0000.
446 /// RW.
447 FUNCTION OFFSET(0) NUMBITS(4),
448 ],
449
450];
451
452const DWT: StaticRef<DwtRegisters> = unsafe { StaticRef::new(0xE0001000 as *const DwtRegisters) };
453
454pub struct Dwt {
455 registers: StaticRef<DwtRegisters>,
456}
457
458impl Dwt {
459 pub const fn new() -> Self {
460 Self { registers: DWT }
461 }
462
463 /// Returns whether a cycle counter is present on the chip.
464 pub fn is_cycle_counter_present(&self) -> bool {
465 DWT.ctrl.read(Control::NOCYCCNT) == 0
466 }
467}
468
469impl hil::hw_debug::CycleCounter for Dwt {
470 fn start(&self) {
471 if self.is_cycle_counter_present() {
472 // The cycle counter has to be enabled in the DCB block
473 dcb::enable_debug_and_trace();
474 self.registers.ctrl.modify(Control::CYCNTENA::SET);
475 }
476 }
477
478 fn stop(&self) {
479 self.registers.ctrl.modify(Control::CYCNTENA::CLEAR);
480 }
481
482 fn count(&self) -> u64 {
483 self.registers.cyccnt.read(CycleCount::CYCCNT) as u64
484 }
485
486 fn reset(&self) {
487 // disable the counter
488 self.registers.ctrl.modify(Control::CYCNTENA::CLEAR);
489 // reset the counter
490 self.registers.cyccnt.set(0);
491 }
492}