裸机环境下自定义实现std::chrono::steady_clock::now()的可行性咨询
std::chrono::steady_clock::now() With Your Custom Hardware Timer Absolutely! Since your PowerPC bare-metal environment's default std::chrono::steady_clock is broken (returning -1000000000), hooking your existing monotonic microsecond timer into a custom clock implementation is the perfect solution. Plus, we can make this portable to x64 Linux/Windows with platform-specific fallbacks. Let’s walk through how to do this properly, tailored to GCC 4.9’s C++11 support.
Step 1: Define a Platform-Agnostic Custom Clock
First, create a clock type that adheres to C++11's Clock concept (required for interop with std::chrono utilities). We’ll use preprocessor macros to switch between your PowerPC hardware timer and standard OS clocks for Linux/Windows.
#include <chrono> // Forward declaration of platform-specific timer function uint64_t get_monotonic_microseconds(); // Custom steady clock that wraps our timer struct CustomSteadyClock { using rep = uint64_t; using period = std::micro; // Our timer returns microseconds using duration = std::chrono::duration<rep, period>; using time_point = std::chrono::time_point<CustomSteadyClock>; static constexpr bool is_steady = true; // Critical for steady_clock behavior static time_point now() noexcept { return time_point(duration(get_monotonic_microseconds())); } }; // Optional: Alias to match std::chrono naming for easier refactoring using steady_clock = CustomSteadyClock;
Step 2: Implement Platform-Specific Timer Logic
Now, fill in get_monotonic_microseconds() for each target platform:
PowerPC Bare-Metal (GCC 4.9)
Use your existing hardware timer code here. Make sure to handle any 32-bit timer overflow if needed (e.g., track overflow counts to maintain a 64-bit monotonic counter):
#ifdef __powerpc__ #include "your_hardware_timer_header.h" static uint64_t overflow_count = 0; static uint32_t last_timer_value = 0; uint64_t get_monotonic_microseconds() { uint32_t current_timer = read_hardware_timer(); // Your existing function if (current_timer < last_timer_value) { overflow_count++; } last_timer_value = current_timer; // Assuming your timer counts at 1us per tick (adjust if your timer has a different prescaler) return (overflow_count << 32) | current_timer; } #endif
x64 Linux
Use clock_gettime() with CLOCK_MONOTONIC for a steady system clock:
#ifdef __linux__ #include <time.h> uint64_t get_monotonic_microseconds() { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return static_cast<uint64_t>(ts.tv_sec) * 1000000 + ts.tv_nsec / 1000; } #endif
x64 Windows
Use QueryPerformanceCounter() and QueryPerformanceFrequency() for high-resolution steady time:
#ifdef _WIN32 #include <windows.h> static LARGE_INTEGER freq; static bool freq_initialized = false; uint64_t get_monotonic_microseconds() { if (!freq_initialized) { QueryPerformanceFrequency(&freq); freq_initialized = true; } LARGE_INTEGER counter; QueryPerformanceCounter(&counter); return (counter.QuadPart * 1000000) / freq.QuadPart; } #endif
Step 3: Use the Clock in Your Code
Now you can use your custom clock just like the standard std::chrono::steady_clock:
#include <iostream> int main() { auto start = steady_clock::now(); // Your code to time here auto end = steady_clock::now(); auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start); std::cout << "Elapsed time: " << elapsed.count() << "ms\n"; return 0; }
Key Considerations for GCC 4.9
- C++11 Support: GCC 4.9 has full support for C++11
std::chrono, but double-check that you’re compiling with-std=c++11(or-std=gnu++11for GNU extensions). - Namespace Safety: While we aliased
steady_clockto match the standard, avoid directly modifying thestdnamespace (it’s undefined behavior in standard C++). Using your own alias is safer. - Timer Overflow: Ensure your PowerPC timer’s overflow is handled correctly to maintain a strictly monotonic count—this is critical for
steady_clock's contract. - Microsecond Accuracy: Verify that your hardware timer’s tick rate is indeed 1 microsecond, or adjust the
durationperiod inCustomSteadyClockto match (e.g.,std::nanofor nanosecond ticks).
Testing the Implementation
- On PowerPC: Verify that successive calls to
now()return strictly increasing values, even when the timer overflows. - On Linux/Windows: Compare your clock’s output with the standard
std::chrono::steady_clockto ensure consistency. - Measure known delays (e.g., a
forloop with a fixed number of iterations) to confirm the timing is accurate.
内容的提问来源于stack exchange,提问作者rounin

