1 // Copyright 2022 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 15 // This timing interface enables and targets ARM registers to enable clock cycle 16 // counting. The documentation can be found here: 17 // https://developer.arm.com/documentation/ddi0337/e/System-Debug/DWT?lang=en 18 // https://developer.arm.com/documentation/ddi0337/e/CEGHJDCF 19 20 #pragma once 21 22 #include <cstdint> 23 24 #include "pw_perf_test/internal/duration_unit.h" 25 26 namespace pw::perf_test::internal::backend { 27 28 // Creates a reference to the DWT Control unit 29 inline volatile uint32_t& kDwtCtrl = 30 *reinterpret_cast<volatile uint32_t*>(0xE0001000); 31 // Creates a reference to the memory address in which the DWT register stores 32 // clock incrementations 33 inline volatile uint32_t& kDwtCcynt = 34 *reinterpret_cast<volatile uint32_t*>(0xE0001004); 35 // Creates a reference to the location of the Debug Exception and Monitor 36 // Control register. 37 inline volatile uint32_t& kDemcr = 38 *reinterpret_cast<volatile uint32_t*>(0xE000EDFC); 39 40 using Timestamp = uint32_t; 41 42 inline constexpr DurationUnit kDurationUnit = DurationUnit::kClockCycle; 43 TimerPrepare()44[[nodiscard]] inline bool TimerPrepare() { 45 kDemcr |= 0x01000000; // Enables the DWT control register 46 kDwtCtrl |= 0x00000001; // Enables the DWT clock 47 kDwtCcynt = 0x00000000; // Intializes the clock to 0 48 return (kDemcr & 0x01000000) && (kDwtCtrl & 0x00000001); 49 } 50 51 // Disables the DWT clock TimerCleanup()52inline void TimerCleanup() { kDwtCtrl &= ~0x00000001; } 53 GetCurrentTimestamp()54inline Timestamp GetCurrentTimestamp() { return kDwtCcynt; } 55 56 // Warning: this duration will overflow if the duration is greater that 2^32 57 // clock cycles. GetDuration(Timestamp begin,Timestamp end)58inline int64_t GetDuration(Timestamp begin, Timestamp end) { 59 return static_cast<int64_t>(end - begin); 60 } 61 62 } // namespace pw::perf_test::internal::backend 63