Sound Byte Libs 29c5ff3
C++ firmware library for audio applications on 32-bit ARM Cortex-M processors
Loading...
Searching...
No Matches
dwt.hpp
Go to the documentation of this file.
1/**
2 * @file dwt.hpp
3 * @brief DWT cycle counter for ARM Cortex-M7
4 *
5 * Provides cycle-accurate profiling via the Data Watchpoint and Trace (DWT)
6 * unit's CYCCNT register. At 480 MHz (STM32H750), this gives ~2.08 ns
7 * resolution with wrap every ~8.9 seconds.
8 *
9 * IMPORTANT: Cortex-M7 requires unlocking the DWT via the Lock Access
10 * Register (LAR) before CYCCNT works. M3/M4 code that omits this step
11 * will silently fail on M7 -- writes are ignored, counter never starts.
12 *
13 * @note DWT is ARM Cortex-M specific. RP2xxx profiling requires a
14 * SysTick or hardware timer fallback (not implemented here).
15 */
16#pragma once
17#ifndef SBL_PROFILING_DWT_HPP
18#define SBL_PROFILING_DWT_HPP
19#include <cstdint>
20
21namespace sbl::profiling {
22
23namespace detail {
24
25// CoreDebug, DWT register addresses (ARMv7-M Architecture Reference Manual)
26inline volatile uint32_t& DEMCR = *reinterpret_cast<volatile uint32_t*>(0xE000EDFC);
27inline volatile uint32_t& DWT_CTRL = *reinterpret_cast<volatile uint32_t*>(0xE0001000);
28inline volatile uint32_t& DWT_CYCCNT = *reinterpret_cast<volatile uint32_t*>(0xE0001004);
29inline volatile uint32_t& DWT_LAR = *reinterpret_cast<volatile uint32_t*>(0xE0001FB0);
30
31static constexpr uint32_t TRCENA_BIT = 1u << 24;
32static constexpr uint32_t CYCCNTENA_BIT = 1u << 0;
33static constexpr uint32_t LAR_UNLOCK = 0xC5ACCE55;
34
35} // namespace detail
36
37/// Initialize DWT cycle counter. Call once after clock configuration.
38inline void dwt_init() {
39 detail::DEMCR |= detail::TRCENA_BIT; // enable trace block
40 detail::DWT_LAR = detail::LAR_UNLOCK; // M7: unlock DWT regs
41 detail::DWT_CYCCNT = 0; // reset
42 detail::DWT_CTRL |= detail::CYCCNTENA_BIT; // start counting
43}
44
45/// Read current cycle count (free-running, wraps at 2^32).
46/// Unsigned subtraction handles wraparound correctly.
47inline uint32_t cycles() {
48 return detail::DWT_CYCCNT;
49}
50
51/// RAII scope for measuring a block of code.
52/// Usage: volatile uint32_t elapsed; { CycleScope s(elapsed); /* code */ }
53struct CycleScope {
54 uint32_t start_;
55 volatile uint32_t& result_;
56
57 explicit CycleScope(volatile uint32_t& out)
58 : start_(cycles()), result_(out) {}
60};
61
62} // namespace sbl::profiling
63
64#endif // SBL_PROFILING_DWT_HPP
static constexpr uint32_t CYCCNTENA_BIT
Definition dwt.hpp:32
static constexpr uint32_t TRCENA_BIT
Definition dwt.hpp:31
static constexpr uint32_t LAR_UNLOCK
Definition dwt.hpp:33
volatile uint32_t & DWT_CYCCNT
Definition dwt.hpp:28
volatile uint32_t & DWT_CTRL
Definition dwt.hpp:27
volatile uint32_t & DWT_LAR
Definition dwt.hpp:29
volatile uint32_t & DEMCR
Definition dwt.hpp:26
CPU load monitoring.
uint32_t cycles()
Definition dwt.hpp:47
void dwt_init()
Initialize DWT cycle counter. Call once after clock configuration.
Definition dwt.hpp:38
CycleScope(volatile uint32_t &out)
Definition dwt.hpp:57
volatile uint32_t & result_
Definition dwt.hpp:55