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//! ARM Data Watchpoint and Trace Unit
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 Regsiter0
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 Regsiter1
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 Regsiter2
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 Regsiter3
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 [`PCSAMPLENA`] is set to 0.
120        /// Defaults to 0b0 on reset.
121        /// WARN: This bit is UNKNOWN if `NOTPRCPKT` or `NOCYCCNT` is read as one.
122        /// RW
123        CYCEVTENA       OFFSET(22)  NUMBITS(1),
124
125        /// Writing 1 enables generation of folded instruction counter overflow event. Defaults to
126        /// 0b0 on reset.
127        /// WARN: This bit is UNKNOWN if `NOPERFCNT` reads as one.
128        /// RW
129        FOLDEVTENA      OFFSET(21)  NUMBITS(1),
130
131        /// Writing 1 enables generation of LSU counter overflow event.
132        /// Defaults to 0b0 on reset.
133        /// WARN: This bit is UNKNOWN if `NOPERFCNT` reads as one.
134        /// RW
135        LSUEVTENA       OFFSET(20)  NUMBITS(1),
136
137        /// Writing 1 enables generation of sleep counter overflow event.
138        /// Defaults to 0b0 on reset.
139        /// WARN: This bit is UNKNOWN if `NOPERFCNT` reads as one.
140        /// RW
141        SLEEPEVTENA     OFFSET(19)  NUMBITS(1),
142
143        /// Writing 1 enables generation of exception overhead counter overflow event.
144        /// Defaults to 0b0 on reset.
145        /// WARN: This bit is UNKNOWN if `NOPERFCNT` reads as one.
146        /// RW
147        EXCEVTENA       OFFSET(18)  NUMBITS(1),
148
149        /// Writing 1 enables generation of the CPI counter overlow event.
150        /// Defaults to 0b0 on reset.
151        /// WARN: This bit is UNKNOWN if `NOPERFCNT` reads as one.
152        /// RW
153        CPIEVTENA       OFFSET(17)  NUMBITS(1),
154
155        /// Writing 1 enables generation of exception trace.
156        /// Defaults to 0b0 on reset.
157        /// WARN: This bit is UNKNOWN if `NOTRCPKT` reads as one.
158        /// RW
159        EXCTRCENA       OFFSET(16)  NUMBITS(1),
160
161        /// Writing 1 enables use of [`POSTCNT`] counter as a timer for Periodic PC sample packet
162        /// generation.
163        /// Defaults to 0b0 on reset.
164        /// WARN: This bit is UNKNOWN if `NOTRCPKT` or `NOCYCCNT` read as one.
165        /// RW
166        PCSAMPLENA      OFFSET(12)  NUMBITS(1),
167
168        /// Determines the position of synchronisation packet counter tap on the `CYCCNT` counter
169        /// and thus the synchronisation packet rate.
170        /// Defaults to UNKNOWN on reset.
171        /// WARN: This bit is UNKNOWN if `NOCYCCNT` reads as one.
172        /// RW
173        SYNCTAP         OFFSET(10)  NUMBITS(2),
174
175        /// Determines the position of the `POSTCNT` tap on the `CYCCNT` counter.
176        /// Defaults to UNKNOWN on reset.
177        /// WARN: This bit is UNKNOWN if `NOCYCCNT` reads as one.
178        /// RW
179        CYCTAP          OFFSET(9)  NUMBITS(1),
180
181        /// Initial value for the `POSTCNT` counter.
182        /// Defaults to UNKNOWN on reset.
183        /// WARN: This bit is UNKNOWN if `NOCYCCNT` reads as one.
184        /// RW
185        POSTINIT        OFFSET(8)  NUMBITS(4),
186
187        /// Reload value for the `POSTCNT` counter.
188        /// Defaults to UNKNOWN on reset.
189        /// WARN: This bit is UNKNOWN if `NOCYCCNT` reads as one.
190        /// RW
191        POSTPRESET      OFFSET(1)  NUMBITS(4),
192
193        /// Writing 1 enables `CYCCNT`.
194        /// Defaults to 0b0 on reset.
195        /// WARN: This bit is UNKNOWN if `NOCYCCNT` reads as one.
196        /// RW
197        CYCNTENA       OFFSET(0)  NUMBITS(1),
198    ],
199
200    CycleCount[
201        /// When enabled, increases on each processor clock cycle when Control::CYCNTENA and
202        /// DEMCRL::TRCENA read as one.
203        /// Wraps to zero on overflow.
204        CYCCNT          OFFSET(0)   NUMBITS(32),
205    ],
206
207    CpiCount[
208        /// Base instruction overhead counter.
209        CPICNT          OFFSET(0)   NUMBITS(8),
210    ],
211
212    ExceptionOverheadCount[
213        /// Counts cycles spent in exception processing.
214        EXCCNT          OFFSET(0)   NUMBITS(8),
215    ],
216
217    SleepCount[
218        /// Counts each cycle the processor is sleeping.
219        SLEEPCNT        OFFSET(0)   NUMBITS(8),
220    ],
221
222    LsuCount[
223        /// Counts additional cycles required to excecute all load store instructions
224        LSUCNT          OFFSET(0)   NUMBITS(8),
225    ],
226
227    FoldedInstructionCount[
228        /// Increments by one for each instruction that takes 0 cycles to excecute.
229        FOLDCNT          OFFSET(0)   NUMBITS(8),
230    ],
231
232    ProgramCounterSample[
233        /// Samples current value of the program counter
234        /// RO.
235        EIASAMPLE       OFFSET(0)   NUMBITS(32),
236    ],
237
238    Comparator0[
239        /// Reference value for comparator 0.
240        COMP       OFFSET(0)   NUMBITS(32),
241    ],
242
243    Comparator0Mask[
244        /// Size of ignore mask aplied to the access address for address range matching by comparator 0.
245        /// WARN: Maximum Mask size is IMPLEMENTATION DEFINED.
246        MASK       OFFSET(0)   NUMBITS(5),
247    ],
248
249    Comparator0Function[
250        /// Is one if comparator matches. Reading the register clears it to 0.
251        /// RO.
252        MATCHED     OFFSET(24)   NUMBITS(1),
253
254        /// Second comparator number for linked address comparison.
255        /// Works, when `DATAVMATCH` and `LNK1ENA` read as one.
256        /// RW.
257        DATAVADDR1  OFFSET(16)   NUMBITS(4),
258
259        /// Comparator number for linked address comparison.
260        /// Works, when `DATAVMATCH` reads as one.
261        /// RW.
262        DATAVADDR0  OFFSET(12)   NUMBITS(4),
263
264        /// Size of data comparision (Byte, Halfword, Word).
265        /// RW.
266        DATAVSIZE   OFFSET(10)   NUMBITS(2),
267
268        /// Reads as one if a second linked comparator is supported.
269        LNK1ENA     OFFSET(9)    NUMBITS(1),
270
271        /// Enables data value comparison
272        /// When 0: Perform address comparison, when 1: data value comparison.
273        /// RW.
274        DATAVMATCH  OFFSET(8)    NUMBITS(1),
275
276        /// Enable cycle count comparision for comparator 0.
277        /// WARN: Only supported by FUNCTION0
278        /// RW.
279        CYCMATCH    OFFSET(7)    NUMBITS(1),
280
281        /// Write 1 to enable generation of data trace address packets.
282        /// WARN: If `Control::NOTRCPKT` reads as zero, this bit is UNKNOWN.
283        /// RW.
284        EMITRANGE   OFFSET(5)    NUMBITS(1),
285
286        /// Selects action taken on comparator match.
287        /// Resets to 0b0000.
288        /// RW.
289        FUNCTION    OFFSET(0)    NUMBITS(4),
290    ],
291
292    Comparator1[
293        /// Reference value for comparator 0.
294        COMP       OFFSET(0)   NUMBITS(32),
295    ],
296
297    Comparator1Mask[
298        /// Size of ignore mask aplied to the access address for address range matching by comparator 0.
299        /// WARN: Maximum Mask size is IMPLEMENTATION DEFINED.
300        MASK       OFFSET(0)   NUMBITS(5),
301    ],
302
303    Comparator1Function[
304        /// Is one if comparator matches. Reading the register clears it to 0.
305        /// RO.
306        MATCHED     OFFSET(24)   NUMBITS(1),
307
308        /// Second comparator number for linked address comparison.
309        /// Works, when `DATAVMATCH` and `LNK1ENA` read as one.
310        /// RW.
311        DATAVADDR1  OFFSET(16)   NUMBITS(4),
312
313        /// Comparator number for linked address comparison.
314        /// Works, when `DATAVMATCH` reads as one.
315        /// RW.
316        DATAVADDR0  OFFSET(12)   NUMBITS(4),
317
318        /// Size of data comparision (Byte, Halfword, Word).
319        /// RW.
320        DATAVSIZE   OFFSET(10)   NUMBITS(2),
321
322        /// Reads as one if a second linked comparator is supported.
323        LNK1ENA     OFFSET(9)    NUMBITS(1),
324
325        /// Enables data value comparison
326        /// When 0: Perform address comparison, when 1: data value comparison.
327        /// RW.
328        DATAVMATCH  OFFSET(8)    NUMBITS(1),
329
330        /// Write 1 to enable generation of data trace address packets.
331        /// WARN: If `Control::NOTRCPKT` reads as zero, this bit is UNKNOWN.
332        /// RW.
333        EMITRANGE   OFFSET(5)    NUMBITS(1),
334
335        /// Selects action taken on comparator match.
336        /// Resets to 0b0000.
337        /// RW.
338        FUNCTION    OFFSET(0)    NUMBITS(4),
339    ],
340
341    Comparator2[
342        /// Reference value for comparator 0.
343        COMP       OFFSET(0)   NUMBITS(32),
344    ],
345
346    Comparator2Mask[
347        /// Size of ignore mask aplied to the access address for address range matching by comparator 0.
348        /// WARN: Maximum Mask size is IMPLEMENTATION DEFINED.
349        MASK       OFFSET(0)   NUMBITS(5),
350    ],
351
352    Comparator2Function[
353        /// Is one if comparator matches. Reading the register clears it to 0.
354        /// RO.
355        MATCHED     OFFSET(24)   NUMBITS(1),
356
357        /// Second comparator number for linked address comparison.
358        /// Works, when `DATAVMATCH` and `LNK1ENA` read as one.
359        /// RW.
360        DATAVADDR1  OFFSET(16)   NUMBITS(4),
361
362        /// Comparator number for linked address comparison.
363        /// Works, when `DATAVMATCH` reads as one.
364        /// RW.
365        DATAVADDR0  OFFSET(12)   NUMBITS(4),
366
367        /// Size of data comparision (Byte, Halfword, Word).
368        /// RW.
369        DATAVSIZE   OFFSET(10)   NUMBITS(2),
370
371        /// Reads as one if a second linked comparator is supported.
372        LNK1ENA     OFFSET(9)    NUMBITS(1),
373
374        /// Enables data value comparison
375        /// When 0: Perform address comparison, when 1: data value comparison.
376        /// RW.
377        DATAVMATCH  OFFSET(8)    NUMBITS(1),
378
379        /// Write 1 to enable generation of data trace address packets.
380        /// WARN: If `Control::NOTRCPKT` reads as zero, this bit is UNKNOWN.
381        /// RW.
382        EMITRANGE   OFFSET(5)    NUMBITS(1),
383
384        /// Selects action taken on comparator match.
385        /// Resets to 0b0000.
386        /// RW.
387        FUNCTION    OFFSET(0)    NUMBITS(4),
388    ],
389
390    Comparator3[
391        /// Reference value for comparator 0.
392        COMP       OFFSET(0)   NUMBITS(32),
393    ],
394
395    Comparator3Mask[
396        /// Size of ignore mask aplied to the access address for address range matching by comparator 0.
397        /// WARN: Maximum Mask size is IMPLEMENTATION DEFINED.
398        MASK       OFFSET(0)   NUMBITS(5),
399    ],
400
401    Comparator3Function[
402        /// Is one if comparator matches. Reading the register clears it to 0.
403        /// RO.
404        MATCHED     OFFSET(24)   NUMBITS(1),
405
406        /// Second comparator number for linked address comparison.
407        /// Works, when `DATAVMATCH` and `LNK1ENA` read as one.
408        /// RW.
409        DATAVADDR1  OFFSET(16)   NUMBITS(4),
410
411        /// Comparator number for linked address comparison.
412        /// Works, when `DATAVMATCH` reads as one.
413        /// RW.
414        DATAVADDR0  OFFSET(12)   NUMBITS(4),
415
416        /// Size of data comparision (Byte, Halfword, Word).
417        /// RW.
418        DATAVSIZE   OFFSET(10)   NUMBITS(2),
419
420        /// Reads as one if a second linked comparator is supported.
421        LNK1ENA     OFFSET(9)    NUMBITS(1),
422
423        /// Enables data value comparison
424        /// When 0: Perform address comparison, when 1: data value comparison.
425        /// RW.
426        DATAVMATCH  OFFSET(8)    NUMBITS(1),
427
428        /// Write 1 to enable generation of data trace address packets.
429        /// WARN: If `Control::NOTRCPKT` reads as zero, this bit is UNKNOWN.
430        /// RW.
431        EMITRANGE   OFFSET(5)    NUMBITS(1),
432
433        /// Selects action taken on comparator match.
434        /// Resets to 0b0000.
435        /// RW.
436        FUNCTION    OFFSET(0)    NUMBITS(4),
437    ],
438
439];
440
441const DWT: StaticRef<DwtRegisters> = unsafe { StaticRef::new(0xE0001000 as *const DwtRegisters) };
442
443pub struct Dwt {
444    registers: StaticRef<DwtRegisters>,
445}
446
447impl Dwt {
448    pub const fn new() -> Self {
449        Self { registers: DWT }
450    }
451
452    /// Returns wether a cycle counter is present on the chip.
453    pub fn is_cycle_counter_present(&self) -> bool {
454        DWT.ctrl.read(Control::NOCYCCNT) == 0
455    }
456}
457
458impl hil::hw_debug::CycleCounter for Dwt {
459    fn start(&self) {
460        if self.is_cycle_counter_present() {
461            // The cycle counter has to be enabled in the DCB block
462            dcb::enable_debug_and_trace();
463            self.registers.ctrl.modify(Control::CYCNTENA::SET);
464        }
465    }
466
467    fn stop(&self) {
468        self.registers.ctrl.modify(Control::CYCNTENA::CLEAR);
469    }
470
471    fn count(&self) -> u64 {
472        self.registers.cyccnt.read(CycleCount::CYCCNT) as u64
473    }
474
475    fn reset(&self) {
476        self.registers.ctrl.modify(Control::CYCNTENA::CLEAR); // disable the counter
477        self.registers.cyccnt.set(0); // reset the counter
478    }
479}