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}