mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-04 03:11:43 +00:00
[hal,wpilib] Rename FPGA clock to monotonic clock (#8672)
- Remove status return from HAL level (clock getting should never fail) - Remove 32-bit timestamp expand function - Make monotonic_clock.hpp (formerly fpga_clock.hpp) header-only and move to root hal include directory
This commit is contained in:
@@ -41,7 +41,7 @@ void TimedRobot::StartCompetition() {
|
||||
break;
|
||||
}
|
||||
|
||||
m_loopStartTimeUs = RobotController::GetFPGATime();
|
||||
m_loopStartTimeUs = RobotController::GetMonotonicTime();
|
||||
std::chrono::microseconds currentTime{m_loopStartTimeUs};
|
||||
|
||||
callback.func();
|
||||
@@ -76,7 +76,7 @@ void TimedRobot::EndCompetition() {
|
||||
|
||||
TimedRobot::TimedRobot(wpi::units::second_t period)
|
||||
: IterativeRobotBase(period) {
|
||||
m_startTime = std::chrono::microseconds{RobotController::GetFPGATime()};
|
||||
m_startTime = std::chrono::microseconds{RobotController::GetMonotonicTime()};
|
||||
AddPeriodic([=, this] { LoopFunc(); }, period);
|
||||
|
||||
int32_t status = 0;
|
||||
|
||||
@@ -115,7 +115,7 @@ MotorSafety& MotorSafety::operator=(MotorSafety&& rhs) {
|
||||
|
||||
void MotorSafety::Feed() {
|
||||
std::scoped_lock lock(m_thisMutex);
|
||||
m_stopTime = Timer::GetFPGATimestamp() + m_expiration;
|
||||
m_stopTime = Timer::GetMonotonicTimestamp() + m_expiration;
|
||||
}
|
||||
|
||||
void MotorSafety::SetExpiration(wpi::units::second_t expirationTime) {
|
||||
@@ -130,7 +130,7 @@ wpi::units::second_t MotorSafety::GetExpiration() const {
|
||||
|
||||
bool MotorSafety::IsAlive() const {
|
||||
std::scoped_lock lock(m_thisMutex);
|
||||
return !m_enabled || m_stopTime > Timer::GetFPGATimestamp();
|
||||
return !m_enabled || m_stopTime > Timer::GetMonotonicTimestamp();
|
||||
}
|
||||
|
||||
void MotorSafety::SetSafetyEnabled(bool enabled) {
|
||||
@@ -157,7 +157,7 @@ void MotorSafety::Check() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (stopTime < Timer::GetFPGATimestamp()) {
|
||||
if (stopTime < Timer::GetMonotonicTimestamp()) {
|
||||
WPILIB_ReportError(
|
||||
err::Timeout,
|
||||
"{}... Output not updated often enough. See "
|
||||
|
||||
@@ -25,7 +25,7 @@ PeriodicOpMode::Callback::Callback(std::function<void()> func,
|
||||
period{period},
|
||||
expirationTime(
|
||||
startTime + offset + period +
|
||||
(std::chrono::microseconds{wpi::RobotController::GetFPGATime()} -
|
||||
(std::chrono::microseconds{wpi::RobotController::GetMonotonicTime()} -
|
||||
startTime) /
|
||||
period * period) {}
|
||||
|
||||
@@ -38,7 +38,7 @@ PeriodicOpMode::~PeriodicOpMode() {
|
||||
PeriodicOpMode::PeriodicOpMode(wpi::units::second_t period)
|
||||
: m_period{period},
|
||||
m_watchdog(period, [this] { PrintLoopOverrunMessage(); }) {
|
||||
m_startTime = std::chrono::microseconds{RobotController::GetFPGATime()};
|
||||
m_startTime = std::chrono::microseconds{RobotController::GetMonotonicTime()};
|
||||
AddPeriodic([=, this] { LoopFunc(); }, period);
|
||||
|
||||
int32_t status = 0;
|
||||
@@ -116,7 +116,7 @@ void PeriodicOpMode::OpModeRun(int64_t opModeId) {
|
||||
break;
|
||||
}
|
||||
|
||||
m_loopStartTimeUs = RobotController::GetFPGATime();
|
||||
m_loopStartTimeUs = RobotController::GetMonotonicTime();
|
||||
std::chrono::microseconds currentTime{m_loopStartTimeUs};
|
||||
|
||||
callback.func();
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
using namespace wpi;
|
||||
|
||||
std::function<uint64_t()> RobotController::m_timeSource = [] {
|
||||
return RobotController::GetFPGATime();
|
||||
return RobotController::GetMonotonicTime();
|
||||
};
|
||||
|
||||
std::string RobotController::GetSerialNumber() {
|
||||
@@ -47,11 +47,8 @@ uint64_t RobotController::GetTime() {
|
||||
return m_timeSource();
|
||||
}
|
||||
|
||||
uint64_t RobotController::GetFPGATime() {
|
||||
int32_t status = 0;
|
||||
uint64_t time = HAL_GetFPGATime(&status);
|
||||
WPILIB_CheckErrorStatus(status, "GetFPGATime");
|
||||
return time;
|
||||
uint64_t RobotController::GetMonotonicTime() {
|
||||
return HAL_GetMonotonicTime();
|
||||
}
|
||||
|
||||
wpi::units::volt_t RobotController::GetBatteryVoltage() {
|
||||
|
||||
@@ -16,7 +16,7 @@ void Wait(wpi::units::second_t seconds) {
|
||||
std::this_thread::sleep_for(std::chrono::duration<double>(seconds.value()));
|
||||
}
|
||||
|
||||
wpi::units::second_t GetTime() {
|
||||
wpi::units::second_t GetSystemTime() {
|
||||
using std::chrono::duration;
|
||||
using std::chrono::duration_cast;
|
||||
using std::chrono::system_clock;
|
||||
@@ -92,9 +92,10 @@ wpi::units::second_t Timer::GetTimestamp() {
|
||||
return wpi::units::second_t{wpi::RobotController::GetTime() * 1.0e-6};
|
||||
}
|
||||
|
||||
wpi::units::second_t Timer::GetFPGATimestamp() {
|
||||
// FPGA returns the timestamp in microseconds
|
||||
return wpi::units::second_t{wpi::RobotController::GetFPGATime() * 1.0e-6};
|
||||
wpi::units::second_t Timer::GetMonotonicTimestamp() {
|
||||
// Monotonic timestamp is in microseconds
|
||||
return wpi::units::second_t{wpi::RobotController::GetMonotonicTime() *
|
||||
1.0e-6};
|
||||
}
|
||||
|
||||
wpi::units::second_t Timer::GetMatchTime() {
|
||||
|
||||
@@ -17,7 +17,7 @@ Tracer::Tracer() {
|
||||
}
|
||||
|
||||
void Tracer::ResetTimer() {
|
||||
m_startTime = wpi::hal::fpga_clock::now();
|
||||
m_startTime = wpi::hal::monotonic_clock::now();
|
||||
}
|
||||
|
||||
void Tracer::ClearEpochs() {
|
||||
@@ -26,7 +26,7 @@ void Tracer::ClearEpochs() {
|
||||
}
|
||||
|
||||
void Tracer::AddEpoch(std::string_view epochName) {
|
||||
auto currentTime = wpi::hal::fpga_clock::now();
|
||||
auto currentTime = wpi::hal::monotonic_clock::now();
|
||||
m_epochs[epochName] = currentTime - m_startTime;
|
||||
m_startTime = currentTime;
|
||||
}
|
||||
@@ -44,7 +44,7 @@ void Tracer::PrintEpochs(wpi::util::raw_ostream& os) {
|
||||
using std::chrono::duration_cast;
|
||||
using std::chrono::microseconds;
|
||||
|
||||
auto now = wpi::hal::fpga_clock::now();
|
||||
auto now = wpi::hal::monotonic_clock::now();
|
||||
if (now - m_lastEpochsPrintTime > kMinPrintPeriod) {
|
||||
m_lastEpochsPrintTime = now;
|
||||
for (const auto& epoch : m_epochs) {
|
||||
|
||||
@@ -87,7 +87,6 @@ void Watchdog::Impl::UpdateAlarm() {
|
||||
|
||||
void Watchdog::Impl::Main() {
|
||||
for (;;) {
|
||||
int32_t status = 0;
|
||||
HAL_NotifierHandle notifier = m_notifier.load();
|
||||
if (notifier == 0) {
|
||||
break;
|
||||
@@ -95,7 +94,7 @@ void Watchdog::Impl::Main() {
|
||||
if (WPI_WaitForObject(notifier) == 0) {
|
||||
break;
|
||||
}
|
||||
uint64_t curTime = HAL_GetFPGATime(&status);
|
||||
uint64_t curTime = HAL_GetMonotonicTime();
|
||||
|
||||
std::unique_lock lock(m_mutex);
|
||||
|
||||
@@ -163,11 +162,11 @@ Watchdog& Watchdog::operator=(Watchdog&& rhs) {
|
||||
}
|
||||
|
||||
wpi::units::second_t Watchdog::GetTime() const {
|
||||
return Timer::GetFPGATimestamp() - m_startTime;
|
||||
return Timer::GetMonotonicTimestamp() - m_startTime;
|
||||
}
|
||||
|
||||
void Watchdog::SetTimeout(wpi::units::second_t timeout) {
|
||||
m_startTime = Timer::GetFPGATimestamp();
|
||||
m_startTime = Timer::GetMonotonicTimestamp();
|
||||
m_tracer.ClearEpochs();
|
||||
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
@@ -203,7 +202,7 @@ void Watchdog::Reset() {
|
||||
}
|
||||
|
||||
void Watchdog::Enable() {
|
||||
m_startTime = Timer::GetFPGATimestamp();
|
||||
m_startTime = Timer::GetMonotonicTimestamp();
|
||||
m_tracer.ClearEpochs();
|
||||
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
|
||||
@@ -64,9 +64,10 @@ class TimedRobot : public IterativeRobotBase {
|
||||
|
||||
/**
|
||||
* Return the system clock time in microseconds for the start of the current
|
||||
* periodic loop. This is in the same time base as Timer.GetFPGATimestamp(),
|
||||
* but is stable through a loop. It is updated at the beginning of every
|
||||
* periodic callback (including the normal periodic loop).
|
||||
* periodic loop. This is in the same time base as
|
||||
* Timer.GetMonotonicTimestamp(), but is stable through a loop. It is updated
|
||||
* at the beginning of every periodic callback (including the normal periodic
|
||||
* loop).
|
||||
*
|
||||
* @return Robot running time in microseconds, as of the start of the current
|
||||
* periodic function.
|
||||
@@ -107,11 +108,11 @@ class TimedRobot : public IterativeRobotBase {
|
||||
std::chrono::microseconds period, std::chrono::microseconds offset)
|
||||
: func{std::move(func)},
|
||||
period{period},
|
||||
expirationTime(
|
||||
startTime + offset + period +
|
||||
(std::chrono::microseconds{wpi::RobotController::GetFPGATime()} -
|
||||
startTime) /
|
||||
period * period) {}
|
||||
expirationTime(startTime + offset + period +
|
||||
(std::chrono::microseconds{
|
||||
wpi::RobotController::GetMonotonicTime()} -
|
||||
startTime) /
|
||||
period * period) {}
|
||||
|
||||
bool operator>(const Callback& rhs) const {
|
||||
return expirationTime > rhs.expirationTime;
|
||||
|
||||
@@ -114,7 +114,7 @@ class MotorSafety {
|
||||
bool m_enabled = false;
|
||||
|
||||
// The FPGA clock value when the motor has expired
|
||||
wpi::units::second_t m_stopTime = Timer::GetFPGATimestamp();
|
||||
wpi::units::second_t m_stopTime = Timer::GetMonotonicTimestamp();
|
||||
|
||||
mutable wpi::util::mutex m_thisMutex;
|
||||
};
|
||||
|
||||
@@ -91,9 +91,10 @@ class PeriodicOpMode : public OpMode {
|
||||
|
||||
/**
|
||||
* Return the system clock time in microseconds for the start of the current
|
||||
* periodic loop. This is in the same time base as Timer.getFPGATimestamp(),
|
||||
* but is stable through a loop. It is updated at the beginning of every
|
||||
* periodic callback (including the normal periodic loop).
|
||||
* periodic loop. This is in the same time base as
|
||||
* Timer::GetMonotonicTimestamp(), but is stable through a loop. It is updated
|
||||
* at the beginning of every periodic callback (including the normal periodic
|
||||
* loop).
|
||||
*
|
||||
* @return Robot running time in microseconds, as of the start of the current
|
||||
* periodic function.
|
||||
|
||||
@@ -60,22 +60,21 @@ class RobotController {
|
||||
static void SetTimeSource(std::function<uint64_t()> supplier);
|
||||
|
||||
/**
|
||||
* Read the microsecond timestamp. By default, the time is based on the FPGA
|
||||
* hardware clock in microseconds since the FPGA started. However, the return
|
||||
* value of this method may be modified to use any time base, including
|
||||
* non-monotonic and non-continuous time bases.
|
||||
* Read the microsecond timestamp. By default, the time is based on the
|
||||
* monotonic clock. However, the return value of this method may be modified
|
||||
* to use any time base, including non-monotonic and non-continuous time
|
||||
* bases.
|
||||
*
|
||||
* @return The current time in microseconds.
|
||||
*/
|
||||
static uint64_t GetTime();
|
||||
|
||||
/**
|
||||
* Read the microsecond-resolution timer on the FPGA.
|
||||
* Read the microsecond-resolution monotonic timer.
|
||||
*
|
||||
* @return The current time in microseconds according to the FPGA (since FPGA
|
||||
* reset).
|
||||
* @return The current monotonic time in microseconds.
|
||||
*/
|
||||
static uint64_t GetFPGATime();
|
||||
static uint64_t GetMonotonicTime();
|
||||
|
||||
/**
|
||||
* Read the battery voltage.
|
||||
|
||||
@@ -25,7 +25,7 @@ void Wait(wpi::units::second_t seconds);
|
||||
* @return The time, just in case you want the robot to start autonomous at 8pm
|
||||
* on Saturday.
|
||||
*/
|
||||
wpi::units::second_t GetTime();
|
||||
wpi::units::second_t GetSystemTime();
|
||||
|
||||
/**
|
||||
* A timer class.
|
||||
@@ -119,24 +119,22 @@ class Timer {
|
||||
bool IsRunning() const;
|
||||
|
||||
/**
|
||||
* Return the clock time in seconds. By default, the time is based on the FPGA
|
||||
* hardware clock in seconds since the FPGA started. However, the return value
|
||||
* of this method may be modified to use any time base, including
|
||||
* non-monotonic time bases.
|
||||
* Return the clock time in seconds. By default, the time is the time returned
|
||||
* by GetMonotonicTimestamp(). However, the return value of this method may be
|
||||
* modified to use any time base, including non-monotonic time bases.
|
||||
*
|
||||
* @returns Robot running time in seconds.
|
||||
*/
|
||||
static wpi::units::second_t GetTimestamp();
|
||||
|
||||
/**
|
||||
* Return the FPGA system clock time in seconds.
|
||||
* Return the monotonic clock time in seconds.
|
||||
*
|
||||
* Return the time from the FPGA hardware clock in seconds since the FPGA
|
||||
* started. Rolls over after 71 minutes.
|
||||
* Return the time from the monotonic clock in seconds.
|
||||
*
|
||||
* @returns Robot running time in seconds.
|
||||
* @returns Monotonic time in seconds.
|
||||
*/
|
||||
static wpi::units::second_t GetFPGATimestamp();
|
||||
static wpi::units::second_t GetMonotonicTimestamp();
|
||||
|
||||
/**
|
||||
* Return the approximate match time. The FMS does not send an official match
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <chrono>
|
||||
#include <string_view>
|
||||
|
||||
#include "wpi/hal/cpp/fpga_clock.hpp"
|
||||
#include "wpi/hal/monotonic_clock.hpp"
|
||||
#include "wpi/util/StringMap.hpp"
|
||||
|
||||
namespace wpi::util {
|
||||
@@ -65,9 +65,9 @@ class Tracer {
|
||||
private:
|
||||
static constexpr std::chrono::milliseconds kMinPrintPeriod{1000};
|
||||
|
||||
wpi::hal::fpga_clock::time_point m_startTime;
|
||||
wpi::hal::fpga_clock::time_point m_lastEpochsPrintTime =
|
||||
wpi::hal::fpga_clock::epoch();
|
||||
wpi::hal::monotonic_clock::time_point m_startTime;
|
||||
wpi::hal::monotonic_clock::time_point m_lastEpochsPrintTime =
|
||||
wpi::hal::monotonic_clock::epoch();
|
||||
|
||||
wpi::util::StringMap<std::chrono::nanoseconds> m_epochs;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user