Skip to content

Commit

Permalink
[wpiutil] Remove roboRIO-specific timestamp code (#7669)
Browse files Browse the repository at this point in the history
  • Loading branch information
ThadHouse authored Jan 13, 2025
1 parent e41b339 commit afbaa43
Show file tree
Hide file tree
Showing 5 changed files with 0 additions and 269 deletions.
2 changes: 0 additions & 2 deletions ntcore/src/dev/native/cpp/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 0 additions & 1 deletion ntcore/src/test/native/cpp/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 0 additions & 3 deletions ntcoreffi/src/main/native/symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
220 changes: 0 additions & 220 deletions wpiutil/src/main/native/cpp/timestamp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand All @@ -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
Expand Down Expand Up @@ -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() {
Expand All @@ -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();
}
Expand Down
43 changes: 0 additions & 43 deletions wpiutil/src/main/native/include/wpi/timestamp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit afbaa43

Please sign in to comment.