mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
[wpiutil] Remove roboRIO-specific timestamp code (#7669)
This commit is contained in:
@@ -32,8 +32,6 @@ void stress();
|
||||
void stress2();
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
wpi::impl::SetupNowDefaultOnRio();
|
||||
|
||||
if (argc == 2 && std::string_view{argv[1]} == "bench") {
|
||||
bench();
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "ntcore.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
wpi::impl::SetupNowDefaultOnRio();
|
||||
nt::AddLogger(nt::GetDefaultInstance(), 0, UINT_MAX, [](auto& event) {
|
||||
if (auto msg = event.GetLogMessage()) {
|
||||
std::fputs(msg->message.c_str(), stderr);
|
||||
|
||||
@@ -261,9 +261,6 @@ WPI_DestroySignalObject
|
||||
WPI_FreeString
|
||||
WPI_FreeStringArray
|
||||
WPI_GetSystemTime
|
||||
WPI_Impl_SetupNowUseDefaultOnRio
|
||||
WPI_Impl_SetupNowRioWithSession
|
||||
WPI_Impl_ShutdownNowRio
|
||||
WPI_InitString
|
||||
WPI_InitStringWithLength
|
||||
WPI_Now
|
||||
|
||||
@@ -8,24 +8,6 @@
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
#ifdef __FRC_ROBORIO__
|
||||
#include <stdint.h>
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
|
||||
#include <FRC_FPGA_ChipObject/RoboRIO_FRC_ChipObject_Aliases.h>
|
||||
#include <FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tHMB.h>
|
||||
#pragma GCC diagnostic pop
|
||||
namespace fpga {
|
||||
using namespace nFPGA;
|
||||
using namespace nRoboRIO_FPGANamespace;
|
||||
} // namespace fpga
|
||||
#include <memory>
|
||||
|
||||
#include "dlfcn.h" // NOLINT(build/include_subdir)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
|
||||
@@ -39,126 +21,6 @@ using namespace nRoboRIO_FPGANamespace;
|
||||
|
||||
#include "wpi/print.h"
|
||||
|
||||
#ifdef __FRC_ROBORIO__
|
||||
namespace {
|
||||
static constexpr const char hmbName[] = "HMB_0_RAM";
|
||||
static constexpr int timestampLowerOffset = 0xF0;
|
||||
static constexpr int timestampUpperOffset = 0xF1;
|
||||
static constexpr int hmbTimestampOffset = 5; // 5 us offset
|
||||
using NiFpga_CloseHmbFunc = NiFpga_Status (*)(const NiFpga_Session session,
|
||||
const char* memoryName);
|
||||
using NiFpga_OpenHmbFunc = NiFpga_Status (*)(const NiFpga_Session session,
|
||||
const char* memoryName,
|
||||
size_t* memorySize,
|
||||
void** virtualAddress);
|
||||
using NiFpga_FindRegisterFunc = NiFpga_Status (*)(NiFpga_Session session,
|
||||
const char* registerName,
|
||||
uint32_t* registerOffset);
|
||||
using NiFpga_ReadU32Func = NiFpga_Status (*)(NiFpga_Session session,
|
||||
uint32_t indicator,
|
||||
uint32_t* value);
|
||||
using NiFpga_WriteU32Func = NiFpga_Status (*)(NiFpga_Session session,
|
||||
uint32_t control, uint32_t value);
|
||||
static void dlcloseWrapper(void* handle) {
|
||||
dlclose(handle);
|
||||
}
|
||||
static std::atomic_flag hmbInitialized = ATOMIC_FLAG_INIT;
|
||||
static std::atomic_flag nowUseDefaultOnFailure = ATOMIC_FLAG_INIT;
|
||||
struct HMBLowLevel {
|
||||
~HMBLowLevel() { Reset(); }
|
||||
bool Configure(const NiFpga_Session session) {
|
||||
int32_t status = 0;
|
||||
niFpga.reset(dlopen("libNiFpga.so", RTLD_LAZY));
|
||||
if (!niFpga) {
|
||||
wpi::print(stderr, "Could not open libNiFpga.so\n");
|
||||
return false;
|
||||
}
|
||||
NiFpga_OpenHmbFunc openHmb = reinterpret_cast<NiFpga_OpenHmbFunc>(
|
||||
dlsym(niFpga.get(), "NiFpgaDll_OpenHmb"));
|
||||
closeHmb = reinterpret_cast<NiFpga_CloseHmbFunc>(
|
||||
dlsym(niFpga.get(), "NiFpgaDll_CloseHmb"));
|
||||
NiFpga_FindRegisterFunc findRegister =
|
||||
reinterpret_cast<NiFpga_FindRegisterFunc>(
|
||||
dlsym(niFpga.get(), "NiFpgaDll_FindRegister"));
|
||||
NiFpga_ReadU32Func readU32 = reinterpret_cast<NiFpga_ReadU32Func>(
|
||||
dlsym(niFpga.get(), "NiFpgaDll_ReadU32"));
|
||||
NiFpga_WriteU32Func writeU32 = reinterpret_cast<NiFpga_WriteU32Func>(
|
||||
dlsym(niFpga.get(), "NiFpgaDll_WriteU32"));
|
||||
if (openHmb == nullptr || closeHmb == nullptr || findRegister == nullptr ||
|
||||
writeU32 == nullptr || readU32 == nullptr) {
|
||||
wpi::print(stderr, "Could not find HMB symbols in libNiFpga.so\n");
|
||||
niFpga = nullptr;
|
||||
return false;
|
||||
}
|
||||
uint32_t hmbConfigRegister = 0;
|
||||
status = findRegister(session, "HMB.Config", &hmbConfigRegister);
|
||||
if (status != 0) {
|
||||
wpi::print(stderr, "Failed to find HMB.Config register, status code {}\n",
|
||||
status);
|
||||
closeHmb = nullptr;
|
||||
niFpga = nullptr;
|
||||
return false;
|
||||
}
|
||||
size_t hmbBufferSize = 0;
|
||||
status =
|
||||
openHmb(session, hmbName, &hmbBufferSize,
|
||||
reinterpret_cast<void**>(const_cast<uint32_t**>(&hmbBuffer)));
|
||||
if (status != 0) {
|
||||
wpi::print(stderr, "Failed to open HMB, status code {}\n", status);
|
||||
closeHmb = nullptr;
|
||||
niFpga = nullptr;
|
||||
return false;
|
||||
}
|
||||
fpga::tHMB::tConfig cfg;
|
||||
uint32_t read = 0;
|
||||
status = readU32(session, hmbConfigRegister, &read);
|
||||
cfg.value = read;
|
||||
cfg.Enables_Timestamp = 1;
|
||||
status = writeU32(session, hmbConfigRegister, cfg.value);
|
||||
hmbSession.emplace(session);
|
||||
hmbInitialized.test_and_set();
|
||||
return true;
|
||||
}
|
||||
void Reset() {
|
||||
hmbInitialized.clear();
|
||||
std::optional<NiFpga_Session> oldSesh;
|
||||
hmbSession.swap(oldSesh);
|
||||
if (oldSesh.has_value()) {
|
||||
closeHmb(oldSesh.value(), hmbName);
|
||||
niFpga = nullptr;
|
||||
}
|
||||
}
|
||||
std::optional<NiFpga_Session> hmbSession;
|
||||
NiFpga_CloseHmbFunc closeHmb = nullptr;
|
||||
volatile uint32_t* hmbBuffer = nullptr;
|
||||
std::unique_ptr<void, decltype(&dlcloseWrapper)> niFpga{nullptr,
|
||||
dlcloseWrapper};
|
||||
};
|
||||
struct HMBHolder {
|
||||
bool Configure(void* col, std::unique_ptr<fpga::tHMB> hmbObject) {
|
||||
hmb = std::move(hmbObject);
|
||||
chipObjectLibrary.reset(col);
|
||||
if (!lowLevel.Configure(hmb->getSystemInterface()->getHandle())) {
|
||||
hmb = nullptr;
|
||||
chipObjectLibrary = nullptr;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void Reset() {
|
||||
lowLevel.Reset();
|
||||
hmb = nullptr;
|
||||
chipObjectLibrary = nullptr;
|
||||
}
|
||||
HMBLowLevel lowLevel;
|
||||
std::unique_ptr<fpga::tHMB> hmb;
|
||||
std::unique_ptr<void, decltype(&dlcloseWrapper)> chipObjectLibrary{
|
||||
nullptr, dlcloseWrapper};
|
||||
};
|
||||
static HMBHolder hmb;
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
// offset in microseconds
|
||||
static uint64_t time_since_epoch() noexcept {
|
||||
#ifdef _WIN32
|
||||
@@ -232,82 +94,12 @@ uint64_t wpi::NowDefault() {
|
||||
|
||||
static std::atomic<uint64_t (*)()> now_impl{wpi::NowDefault};
|
||||
|
||||
void wpi::impl::SetupNowDefaultOnRio() {
|
||||
#ifdef __FRC_ROBORIO__
|
||||
nowUseDefaultOnFailure.test_and_set();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __FRC_ROBORIO__
|
||||
template <>
|
||||
bool wpi::impl::SetupNowRio(void* chipObjectLibrary,
|
||||
std::unique_ptr<fpga::tHMB> hmbObject) {
|
||||
if (!hmbInitialized.test()) {
|
||||
return hmb.Configure(chipObjectLibrary, std::move(hmbObject));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool wpi::impl::SetupNowRio(uint32_t session) {
|
||||
#ifdef __FRC_ROBORIO__
|
||||
if (!hmbInitialized.test()) {
|
||||
return hmb.lowLevel.Configure(session);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void wpi::impl::ShutdownNowRio() {
|
||||
#ifdef __FRC_ROBORIO__
|
||||
hmb.Reset();
|
||||
#endif
|
||||
}
|
||||
|
||||
void wpi::SetNowImpl(uint64_t (*func)(void)) {
|
||||
now_impl = func ? func : NowDefault;
|
||||
}
|
||||
|
||||
uint64_t wpi::Now() {
|
||||
#ifdef __FRC_ROBORIO__
|
||||
// Same code as HAL_GetFPGATime()
|
||||
if (!hmbInitialized.test()) {
|
||||
if (nowUseDefaultOnFailure.test()) {
|
||||
return timestamp() - offset_val;
|
||||
} else {
|
||||
wpi::print(stderr,
|
||||
"FPGA not yet configured in wpi::Now(). This is a fatal "
|
||||
"error. The process is being terminated.\n");
|
||||
std::fflush(stderr);
|
||||
// Attempt to force a segfault to get a better java log
|
||||
*reinterpret_cast<int*>(0) = 0;
|
||||
// If that fails, terminate
|
||||
std::terminate();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
asm("dmb");
|
||||
uint64_t upper1 = hmb.lowLevel.hmbBuffer[timestampUpperOffset];
|
||||
asm("dmb");
|
||||
uint32_t lower = hmb.lowLevel.hmbBuffer[timestampLowerOffset];
|
||||
asm("dmb");
|
||||
uint64_t upper2 = hmb.lowLevel.hmbBuffer[timestampUpperOffset];
|
||||
|
||||
if (upper1 != upper2) {
|
||||
// Rolled over between the lower call, reread lower
|
||||
asm("dmb");
|
||||
lower = hmb.lowLevel.hmbBuffer[timestampLowerOffset];
|
||||
}
|
||||
// 5 is added here because the time to write from the FPGA
|
||||
// to the HMB buffer is longer then the time to read
|
||||
// from the time register. This would cause register based
|
||||
// timestamps to be ahead of HMB timestamps, which could
|
||||
// be very bad.
|
||||
return (upper2 << 32) + lower + hmbTimestampOffset;
|
||||
#else
|
||||
return (now_impl.load())();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t wpi::GetSystemTime() {
|
||||
@@ -316,18 +108,6 @@ uint64_t wpi::GetSystemTime() {
|
||||
|
||||
extern "C" {
|
||||
|
||||
void WPI_Impl_SetupNowUseDefaultOnRio(void) {
|
||||
return wpi::impl::SetupNowDefaultOnRio();
|
||||
}
|
||||
|
||||
void WPI_Impl_SetupNowRioWithSession(uint32_t session) {
|
||||
wpi::impl::SetupNowRio(session);
|
||||
}
|
||||
|
||||
void WPI_Impl_ShutdownNowRio(void) {
|
||||
return wpi::impl::ShutdownNowRio();
|
||||
}
|
||||
|
||||
uint64_t WPI_NowDefault(void) {
|
||||
return wpi::NowDefault();
|
||||
}
|
||||
|
||||
@@ -16,12 +16,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* De-initialize the on-Rio Now() implementation. No effect on non-Rio
|
||||
* platforms.
|
||||
*/
|
||||
void WPI_Impl_ShutdownNowRio(void);
|
||||
|
||||
/**
|
||||
* The default implementation used for Now().
|
||||
* In general this is the time returned by the operating system.
|
||||
@@ -59,43 +53,6 @@ uint64_t WPI_GetSystemTime(void);
|
||||
#ifdef __cplusplus
|
||||
namespace wpi {
|
||||
|
||||
namespace impl {
|
||||
/**
|
||||
* Initialize the on-Rio Now() implementation to use the desktop timestamp.
|
||||
* No effect on non-Rio platforms. This should only be used for testing
|
||||
* purposes if the HAL is not available.
|
||||
*/
|
||||
void SetupNowDefaultOnRio();
|
||||
|
||||
/**
|
||||
* Initialize the on-Rio Now() implementation to use the FPGA timestamp.
|
||||
* No effect on non-Rio platforms. This is called by HAL_Initialize() and
|
||||
* thus should generally not be called by user code.
|
||||
*/
|
||||
#ifdef __FRC_ROBORIO__
|
||||
template <typename T>
|
||||
bool SetupNowRio(void* chipObjectLibrary, std::unique_ptr<T> hmbObject);
|
||||
#else
|
||||
template <typename T>
|
||||
inline bool SetupNowRio(void*, std::unique_ptr<T>) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initialize the on-Rio Now() implementation to use the FPGA timestamp.
|
||||
* No effect on non-Rio platforms. This take an FPGA session that has
|
||||
* already been initialized, and is used from LabVIEW.
|
||||
*/
|
||||
bool SetupNowRio(uint32_t session);
|
||||
|
||||
/**
|
||||
* De-initialize the on-Rio Now() implementation. No effect on non-Rio
|
||||
* platforms.
|
||||
*/
|
||||
void ShutdownNowRio();
|
||||
} // namespace impl
|
||||
|
||||
/**
|
||||
* The default implementation used for Now().
|
||||
* In general this is the time returned by the operating system.
|
||||
|
||||
Reference in New Issue
Block a user