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}