diff --git a/hal/src/main/native/athena/AddressableLED.cpp b/hal/src/main/native/athena/AddressableLED.cpp index ba446901e5..5e55c93e14 100644 --- a/hal/src/main/native/athena/AddressableLED.cpp +++ b/hal/src/main/native/athena/AddressableLED.cpp @@ -6,11 +6,11 @@ #include -#include #include #include "ConstantsInternal.h" #include "DigitalInternal.h" +#include "FPGACalls.h" #include "HALInitializer.h" #include "HALInternal.h" #include "PortsInternal.h" @@ -21,51 +21,6 @@ using namespace hal; -extern "C" { -NiFpga_Status NiFpga_ClientFunctionCall(NiFpga_Session session, uint32_t group, - uint32_t functionId, - const void* inBuffer, - size_t inBufferSize, void* outBuffer, - size_t outBufferSize); -} // extern "C" - -// Shim for broken ChipObject function -static const uint32_t clientFeature_hostMemoryBuffer = 0; -static const uint32_t hostMemoryBufferFunction_open = 2; - -// Input arguments for HMB open -struct AtomicHMBOpenInputs { - const char* memoryName; -}; - -// Output arguments for HMB open -struct AtomicHMBOpenOutputs { - size_t size; - void* virtualAddress; -}; - -static NiFpga_Status OpenHostMemoryBuffer(NiFpga_Session session, - const char* memoryName, - void** virtualAddress, size_t* size) { - struct AtomicHMBOpenOutputs outputs; - - struct AtomicHMBOpenInputs inputs; - inputs.memoryName = memoryName; - - NiFpga_Status retval = NiFpga_ClientFunctionCall( - session, clientFeature_hostMemoryBuffer, hostMemoryBufferFunction_open, - &inputs, sizeof(struct AtomicHMBOpenInputs), &outputs, - sizeof(struct AtomicHMBOpenOutputs)); - if (NiFpga_IsError(retval)) { - return retval; - } - *virtualAddress = outputs.virtualAddress; - if (size) { - *size = outputs.size; - } - return retval; -} - namespace { struct AddressableLED { std::unique_ptr led; @@ -89,6 +44,8 @@ void InitializeAddressableLED() { } } // namespace hal::init +static constexpr const char* HmbName = "HMB_0_LED"; + extern "C" { HAL_AddressableLEDHandle HAL_InitializeAddressableLED( @@ -146,8 +103,8 @@ HAL_AddressableLEDHandle HAL_InitializeAddressableLED( uint32_t session = led->led->getSystemInterface()->getHandle(); - *status = OpenHostMemoryBuffer(session, "HMB_0_LED", &led->ledBuffer, - &led->ledBufferSize); + *status = hal::HAL_NiFpga_OpenHmb(session, HmbName, &led->ledBufferSize, + &led->ledBuffer); if (*status != 0) { addressableLEDHandles->Free(handle); @@ -158,6 +115,12 @@ HAL_AddressableLEDHandle HAL_InitializeAddressableLED( } void HAL_FreeAddressableLED(HAL_AddressableLEDHandle handle) { + auto led = addressableLEDHandles->Get(handle); + if (!led) { + return; + } + uint32_t session = led->led->getSystemInterface()->getHandle(); + hal::HAL_NiFpga_CloseHmb(session, HmbName); addressableLEDHandles->Free(handle); } diff --git a/hal/src/main/native/athena/FPGACalls.cpp b/hal/src/main/native/athena/FPGACalls.cpp new file mode 100644 index 0000000000..0b04019b1d --- /dev/null +++ b/hal/src/main/native/athena/FPGACalls.cpp @@ -0,0 +1,66 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "FPGACalls.h" + +#include + +#include "dlfcn.h" +#include "hal/Errors.h" + +static void* NiFpgaLibrary = nullptr; + +namespace hal { +HAL_NiFpga_ReserveIrqContextFunc HAL_NiFpga_ReserveIrqContext; +HAL_NiFpga_UnreserveIrqContextFunc HAL_NiFpga_UnreserveIrqContext; +HAL_NiFpga_WaitOnIrqsFunc HAL_NiFpga_WaitOnIrqs; +HAL_NiFpga_AcknowledgeIrqsFunc HAL_NiFpga_AcknowledgeIrqs; +HAL_NiFpga_OpenHmbFunc HAL_NiFpga_OpenHmb; +HAL_NiFpga_CloseHmbFunc HAL_NiFpga_CloseHmb; + +namespace init { +int InitializeFPGA() { + NiFpgaLibrary = dlopen("libNiFpga.so", RTLD_LAZY); + if (!NiFpgaLibrary) { + return errno; + } + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" + HAL_NiFpga_ReserveIrqContext = + reinterpret_cast( + dlsym(NiFpgaLibrary, "NiFpgaDll_ReserveIrqContext")); + HAL_NiFpga_UnreserveIrqContext = + reinterpret_cast( + dlsym(NiFpgaLibrary, "NiFpgaDll_UnreserveIrqContext")); + HAL_NiFpga_WaitOnIrqs = reinterpret_cast( + dlsym(NiFpgaLibrary, "NiFpgaDll_WaitOnIrqs")); + HAL_NiFpga_AcknowledgeIrqs = reinterpret_cast( + dlsym(NiFpgaLibrary, "NiFpgaDll_AcknowledgeIrqs")); + HAL_NiFpga_OpenHmb = reinterpret_cast( + dlsym(NiFpgaLibrary, "NiFpgaDll_OpenHmb")); + HAL_NiFpga_CloseHmb = reinterpret_cast( + dlsym(NiFpgaLibrary, "NiFpgaDll_CloseHmb")); +#pragma GCC diagnostic pop + + if (HAL_NiFpga_ReserveIrqContext == nullptr || + HAL_NiFpga_UnreserveIrqContext == nullptr || + HAL_NiFpga_WaitOnIrqs == nullptr || + HAL_NiFpga_AcknowledgeIrqs == nullptr || HAL_NiFpga_OpenHmb == nullptr || + HAL_NiFpga_CloseHmb == nullptr) { + HAL_NiFpga_ReserveIrqContext = nullptr; + HAL_NiFpga_UnreserveIrqContext = nullptr; + HAL_NiFpga_WaitOnIrqs = nullptr; + HAL_NiFpga_AcknowledgeIrqs = nullptr; + HAL_NiFpga_OpenHmb = nullptr; + HAL_NiFpga_CloseHmb = nullptr; + dlclose(NiFpgaLibrary); + NiFpgaLibrary = nullptr; + return NO_AVAILABLE_RESOURCES; + } + + return HAL_SUCCESS; +} +} // namespace init +} // namespace hal diff --git a/hal/src/main/native/athena/FPGACalls.h b/hal/src/main/native/athena/FPGACalls.h new file mode 100644 index 0000000000..46e8ac407c --- /dev/null +++ b/hal/src/main/native/athena/FPGACalls.h @@ -0,0 +1,46 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#pragma once + +#include + +namespace hal { +namespace init { +[[nodiscard]] int InitializeFPGA(); +} // namespace init + +using HAL_NiFpga_ReserveIrqContextFunc = + NiFpga_Status (*)(NiFpga_Session session, NiFpga_IrqContext* context); + +extern HAL_NiFpga_ReserveIrqContextFunc HAL_NiFpga_ReserveIrqContext; + +using HAL_NiFpga_UnreserveIrqContextFunc = + NiFpga_Status (*)(NiFpga_Session session, NiFpga_IrqContext context); + +extern HAL_NiFpga_UnreserveIrqContextFunc HAL_NiFpga_UnreserveIrqContext; + +using HAL_NiFpga_WaitOnIrqsFunc = NiFpga_Status (*)( + NiFpga_Session session, NiFpga_IrqContext context, uint32_t irqs, + uint32_t timeout, uint32_t* irqsAsserted, NiFpga_Bool* timedOut); + +extern HAL_NiFpga_WaitOnIrqsFunc HAL_NiFpga_WaitOnIrqs; + +using HAL_NiFpga_AcknowledgeIrqsFunc = NiFpga_Status (*)(NiFpga_Session session, + uint32_t irqs); + +extern HAL_NiFpga_AcknowledgeIrqsFunc HAL_NiFpga_AcknowledgeIrqs; + +using HAL_NiFpga_OpenHmbFunc = NiFpga_Status (*)(const NiFpga_Session session, + const char* memoryName, + size_t* memorySize, + void** virtualAddress); + +extern HAL_NiFpga_OpenHmbFunc HAL_NiFpga_OpenHmb; + +using HAL_NiFpga_CloseHmbFunc = NiFpga_Status (*)(const NiFpga_Session session, + const char* memoryName); + +extern HAL_NiFpga_CloseHmbFunc HAL_NiFpga_CloseHmb; +} // namespace hal diff --git a/hal/src/main/native/athena/HAL.cpp b/hal/src/main/native/athena/HAL.cpp index 08abf14bb6..6fd045903f 100644 --- a/hal/src/main/native/athena/HAL.cpp +++ b/hal/src/main/native/athena/HAL.cpp @@ -21,6 +21,7 @@ #include #include +#include "FPGACalls.h" #include "HALInitializer.h" #include "HALInternal.h" #include "hal/ChipObject.h" @@ -394,6 +395,11 @@ HAL_Bool HAL_Initialize(int32_t timeout, int32_t mode) { return true; } + int fpgaInit = hal::init::InitializeFPGA(); + if (fpgaInit != HAL_SUCCESS) { + return false; + } + hal::init::InitializeHAL(); hal::init::HAL_IsInitialized.store(true); @@ -426,11 +432,7 @@ HAL_Bool HAL_Initialize(int32_t timeout, int32_t mode) { return false; } - status = InterruptManager::Initialize(global->getSystemInterface()); - - if (status != 0) { - return false; - } + InterruptManager::Initialize(global->getSystemInterface()); hal::InitializeDriverStation(); diff --git a/hal/src/main/native/athena/InterruptManager.cpp b/hal/src/main/native/athena/InterruptManager.cpp index 0bd0672ad5..420f8065c8 100644 --- a/hal/src/main/native/athena/InterruptManager.cpp +++ b/hal/src/main/native/athena/InterruptManager.cpp @@ -6,34 +6,11 @@ #include +#include "FPGACalls.h" #include "HALInternal.h" #include "dlfcn.h" #include "hal/Errors.h" -// Low level FPGA calls -using HAL_NiFpga_ReserveIrqContextFunc = - NiFpga_Status (*)(NiFpga_Session session, NiFpga_IrqContext* context); - -static HAL_NiFpga_ReserveIrqContextFunc HAL_NiFpga_ReserveIrqContext; - -using HAL_NiFpga_UnreserveIrqContextFunc = - NiFpga_Status (*)(NiFpga_Session session, NiFpga_IrqContext context); - -static HAL_NiFpga_UnreserveIrqContextFunc HAL_NiFpga_UnreserveIrqContext; - -using HAL_NiFpga_WaitOnIrqsFunc = NiFpga_Status (*)( - NiFpga_Session session, NiFpga_IrqContext context, uint32_t irqs, - uint32_t timeout, uint32_t* irqsAsserted, NiFpga_Bool* timedOut); - -static HAL_NiFpga_WaitOnIrqsFunc HAL_NiFpga_WaitOnIrqs; - -using HAL_NiFpga_AcknowledgeIrqsFunc = NiFpga_Status (*)(NiFpga_Session session, - uint32_t irqs); - -static HAL_NiFpga_AcknowledgeIrqsFunc HAL_NiFpga_AcknowledgeIrqs; - -static void* NiFpgaLibrary = nullptr; - using namespace hal; InterruptManager& InterruptManager::GetInstance() { @@ -41,37 +18,9 @@ InterruptManager& InterruptManager::GetInstance() { return manager; } -int32_t InterruptManager::Initialize(tSystemInterface* baseSystem) { +void InterruptManager::Initialize(tSystemInterface* baseSystem) { auto& manager = GetInstance(); manager.fpgaSession = baseSystem->getHandle(); - - NiFpgaLibrary = dlopen("libNiFpga.so", RTLD_LAZY); - if (!NiFpgaLibrary) { - return errno; - } - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - HAL_NiFpga_ReserveIrqContext = - reinterpret_cast( - dlsym(NiFpgaLibrary, "NiFpgaDll_ReserveIrqContext")); - HAL_NiFpga_UnreserveIrqContext = - reinterpret_cast( - dlsym(NiFpgaLibrary, "NiFpgaDll_UnreserveIrqContext")); - HAL_NiFpga_WaitOnIrqs = reinterpret_cast( - dlsym(NiFpgaLibrary, "NiFpgaDll_WaitOnIrqs")); - HAL_NiFpga_AcknowledgeIrqs = reinterpret_cast( - dlsym(NiFpgaLibrary, "NiFpgaDll_AcknowledgeIrqs")); -#pragma GCC diagnostic pop - - if (HAL_NiFpga_ReserveIrqContext == nullptr || - HAL_NiFpga_UnreserveIrqContext == nullptr || - HAL_NiFpga_WaitOnIrqs == nullptr || - HAL_NiFpga_AcknowledgeIrqs == nullptr) { - return NO_AVAILABLE_RESOURCES; - } - - return HAL_SUCCESS; } NiFpga_IrqContext InterruptManager::GetContext() noexcept { diff --git a/hal/src/main/native/include/hal/roborio/InterruptManager.h b/hal/src/main/native/include/hal/roborio/InterruptManager.h index ee7fc38c43..36d904b49e 100644 --- a/hal/src/main/native/include/hal/roborio/InterruptManager.h +++ b/hal/src/main/native/include/hal/roborio/InterruptManager.h @@ -14,7 +14,7 @@ namespace hal { class InterruptManager { public: static InterruptManager& GetInstance(); - static int32_t Initialize(tSystemInterface* baseSystem); + static void Initialize(tSystemInterface* baseSystem); NiFpga_IrqContext GetContext() noexcept; void ReleaseContext(NiFpga_IrqContext context) noexcept;